diff --git a/README.md b/README.md index b08a93f23e..88750cf654 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -**UPDATE**: The price of "Learn Spring Security OAuth" will permanently change on the 11th of December, along with the upcoming OAuth2 material: http://bit.ly/github-lss - The Courses ============================== diff --git a/algorithms-genetic/README.md b/algorithms-genetic/README.md index 1c9e831ac2..eb4e3fb798 100644 --- a/algorithms-genetic/README.md +++ b/algorithms-genetic/README.md @@ -5,6 +5,6 @@ This module contains articles about genetic algorithms. ### Relevant articles: - [Introduction to Jenetics Library](https://www.baeldung.com/jenetics) -- [Ant Colony Optimization](https://www.baeldung.com/java-ant-colony-optimization) +- [Ant Colony Optimization with a Java Example](https://www.baeldung.com/java-ant-colony-optimization) - [Design a Genetic Algorithm in Java](https://www.baeldung.com/java-genetic-algorithm) - [The Traveling Salesman Problem in Java](https://www.baeldung.com/java-simulated-annealing-for-traveling-salesman) diff --git a/algorithms-miscellaneous-1/README.md b/algorithms-miscellaneous-1/README.md index 25e2733538..02bf874197 100644 --- a/algorithms-miscellaneous-1/README.md +++ b/algorithms-miscellaneous-1/README.md @@ -6,8 +6,8 @@ This module contains articles about algorithms. Some classes of algorithms, e.g. ### Relevant articles: - [Validating Input With Finite Automata in Java](https://www.baeldung.com/java-finite-automata) -- [Example of Hill Climbing Algorithm](https://www.baeldung.com/java-hill-climbing-algorithm) -- [Introduction to Minimax Algorithm](https://www.baeldung.com/java-minimax-algorithm) +- [Example of Hill Climbing Algorithm in Java](https://www.baeldung.com/java-hill-climbing-algorithm) +- [Introduction to Minimax Algorithm with a Java Implementation](https://www.baeldung.com/java-minimax-algorithm) - [How to Calculate Levenshtein Distance in Java?](https://www.baeldung.com/java-levenshtein-distance) - [How to Find the Kth Largest Element in Java](https://www.baeldung.com/java-kth-largest-element) -- More articles: [[next -->]](/../algorithms-miscellaneous-2) +- More articles: [[next -->]](/algorithms-miscellaneous-2) diff --git a/algorithms-miscellaneous-2/README.md b/algorithms-miscellaneous-2/README.md index 26737b61f0..265416534e 100644 --- a/algorithms-miscellaneous-2/README.md +++ b/algorithms-miscellaneous-2/README.md @@ -14,4 +14,4 @@ This module contains articles about algorithms. Some classes of algorithms, e.g. - [Displaying Money Amounts in Words](https://www.baeldung.com/java-money-into-words) - [A Collaborative Filtering Recommendation System in Java](https://www.baeldung.com/java-collaborative-filtering-recommendations) - [Implementing A* Pathfinding in Java](https://www.baeldung.com/java-a-star-pathfinding) -- More articles: [[<-- prev]](/../algorithms-miscellaneous-1) [[next -->]](/../algorithms-miscellaneous-3) +- More articles: [[<-- prev]](/algorithms-miscellaneous-1) [[next -->]](/algorithms-miscellaneous-3) diff --git a/algorithms-miscellaneous-4/README.md b/algorithms-miscellaneous-4/README.md index fd33b58d72..2649df9fc9 100644 --- a/algorithms-miscellaneous-4/README.md +++ b/algorithms-miscellaneous-4/README.md @@ -5,8 +5,8 @@ This module contains articles about algorithms. Some classes of algorithms, e.g. ### Relevant articles: - [Multi-Swarm Optimization Algorithm in Java](https://www.baeldung.com/java-multi-swarm-algorithm) -- [Check If a String Contains All The Letters of The Alphabet](https://www.baeldung.com/java-string-contains-all-letters) -- [Find the Middle Element of a Linked List](https://www.baeldung.com/java-linked-list-middle-element) +- [Check If a String Contains All The Letters of The Alphabet with Java](https://www.baeldung.com/java-string-contains-all-letters) +- [Find the Middle Element of a Linked List in Java](https://www.baeldung.com/java-linked-list-middle-element) - [Find Substrings That Are Palindromes in Java](https://www.baeldung.com/java-palindrome-substrings) - [Find the Longest Substring without Repeating Characters](https://www.baeldung.com/java-longest-substring-without-repeated-characters) - [Permutations of an Array in Java](https://www.baeldung.com/java-array-permutations) diff --git a/algorithms-miscellaneous-5/README.md b/algorithms-miscellaneous-5/README.md index 3e6eeb4c93..54b936586f 100644 --- a/algorithms-miscellaneous-5/README.md +++ b/algorithms-miscellaneous-5/README.md @@ -9,11 +9,11 @@ This module contains articles about algorithms. Some classes of algorithms, e.g. - [Reversing a Binary Tree in Java](https://www.baeldung.com/java-reversing-a-binary-tree) - [Find If Two Numbers Are Relatively Prime in Java](https://www.baeldung.com/java-two-relatively-prime-numbers) - [Knapsack Problem Implementation in Java](https://www.baeldung.com/java-knapsack) -- [How to Determine if a Binary Tree is Balanced](https://www.baeldung.com/java-balanced-binary-tree) +- [How to Determine if a Binary Tree is Balanced in Java](https://www.baeldung.com/java-balanced-binary-tree) - [Overview of Combinatorial Problems in Java](https://www.baeldung.com/java-combinatorial-algorithms) -- [Prim’s Algorithm](https://www.baeldung.com/java-prim-algorithm) -- [Maximum Subarray Problem](https://www.baeldung.com/java-maximum-subarray) -- [How to Merge Two Sorted Arrays](https://www.baeldung.com/java-merge-sorted-arrays) -- [Median of Stream of Integers using Heap](https://www.baeldung.com/java-stream-integers-median-using-heap) -- More articles: [[<-- prev]](/../algorithms-miscellaneous-4) [[next -->]](/../algorithms-miscellaneous-6) +- [Prim’s Algorithm with a Java Implementation](https://www.baeldung.com/java-prim-algorithm) +- [Maximum Subarray Problem in Java](https://www.baeldung.com/java-maximum-subarray) +- [How to Merge Two Sorted Arrays in Java](https://www.baeldung.com/java-merge-sorted-arrays) +- [Median of Stream of Integers using Heap in Java](https://www.baeldung.com/java-stream-integers-median-using-heap) +- More articles: [[<-- prev]](/algorithms-miscellaneous-4) [[next -->]](/algorithms-miscellaneous-6) diff --git a/algorithms-miscellaneous-6/README.md b/algorithms-miscellaneous-6/README.md index 6ddae75f43..f21eddeed8 100644 --- a/algorithms-miscellaneous-6/README.md +++ b/algorithms-miscellaneous-6/README.md @@ -1,12 +1,13 @@ ### Relevant Articles: -- [Boruvka’s Algorithm for Minimum Spanning Trees](https://www.baeldung.com/java-boruvka-algorithm) +- [Boruvka’s Algorithm for Minimum Spanning Trees in Java](https://www.baeldung.com/java-boruvka-algorithm) - [Gradient Descent in Java](https://www.baeldung.com/java-gradient-descent) -- [Kruskal’s Algorithm for Spanning Trees](https://www.baeldung.com/java-spanning-trees-kruskal) +- [Kruskal’s Algorithm for Spanning Trees with a Java Implementation](https://www.baeldung.com/java-spanning-trees-kruskal) - [Balanced Brackets Algorithm in Java](https://www.baeldung.com/java-balanced-brackets-algorithm) - [Efficiently Merge Sorted Java Sequences](https://www.baeldung.com/java-merge-sorted-sequences) - [Introduction to Greedy Algorithms with Java](https://www.baeldung.com/java-greedy-algorithms) - [The Caesar Cipher in Java](https://www.baeldung.com/java-caesar-cipher) - [Implementing a 2048 Solver in Java](https://www.baeldung.com/2048-java-solver) -- [Finding Top K Elements in an Array](https://www.baeldung.com/java-array-top-elements) -- More articles: [[<-- prev]](/../algorithms-miscellaneous-5) +- [Finding Top K Elements in a Java Array](https://www.baeldung.com/java-array-top-elements) +- [Reversing a Linked List in Java](https://www.baeldung.com/java-reverse-linked-list) +- More articles: [[<-- prev]](/algorithms-miscellaneous-5) diff --git a/algorithms-searching/README.md b/algorithms-searching/README.md index a3ea023da3..7d10100832 100644 --- a/algorithms-searching/README.md +++ b/algorithms-searching/README.md @@ -8,8 +8,8 @@ This module contains articles about searching algorithms. - [Depth First Search in Java](https://www.baeldung.com/java-depth-first-search) - [Interpolation Search in Java](https://www.baeldung.com/java-interpolation-search) - [Breadth-First Search Algorithm in Java](https://www.baeldung.com/java-breadth-first-search) -- [String Search Algorithms for Large Texts](https://www.baeldung.com/java-full-text-search-algorithms) -- [Monte Carlo Tree Search for Tic-Tac-Toe Game](https://www.baeldung.com/java-monte-carlo-tree-search) +- [String Search Algorithms for Large Texts with Java](https://www.baeldung.com/java-full-text-search-algorithms) +- [Monte Carlo Tree Search for Tic-Tac-Toe Game in Java](https://www.baeldung.com/java-monte-carlo-tree-search) - [Range Search Algorithm in Java](https://www.baeldung.com/java-range-search) -- [Fast Pattern Matching of Strings Using Suffix Tree](https://www.baeldung.com/java-pattern-matching-suffix-tree) -- [Find the Kth Smallest Element in Two Sorted Arrays](https://www.baeldung.com/java-kth-smallest-element-in-sorted-arrays) +- [Fast Pattern Matching of Strings Using Suffix Tree in Java](https://www.baeldung.com/java-pattern-matching-suffix-tree) +- [Find the Kth Smallest Element in Two Sorted Arrays in Java](https://www.baeldung.com/java-kth-smallest-element-in-sorted-arrays) diff --git a/algorithms-sorting-2/README.md b/algorithms-sorting-2/README.md index 71c9b8f86c..b31cfceb42 100644 --- a/algorithms-sorting-2/README.md +++ b/algorithms-sorting-2/README.md @@ -2,6 +2,6 @@ - [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) +- [Guide to In-Place Sorting Algorithm Works with a Java Implementation](https://www.baeldung.com/java-in-place-sorting) +- [Partitioning and Sorting Arrays with Many Repeated Entries with Java Examples](https://www.baeldung.com/java-sorting-arrays-with-repeated-entries) - More articles: [[<-- prev]](/algorithms-sorting) diff --git a/apache-libraries/pom.xml b/apache-libraries/pom.xml index 9f800f1e0b..15404676cc 100644 --- a/apache-libraries/pom.xml +++ b/apache-libraries/pom.xml @@ -129,6 +129,11 @@ zookeeper ${zookeeper.version} + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + com.fasterxml.jackson.core jackson-databind diff --git a/apache-spark/README.md b/apache-spark/README.md index c60b556d51..3a2d2f4e15 100644 --- a/apache-spark/README.md +++ b/apache-spark/README.md @@ -8,3 +8,4 @@ This module contains articles about Apache Spark - [Building a Data Pipeline with Kafka, Spark Streaming and Cassandra](https://www.baeldung.com/kafka-spark-data-pipeline) - [Machine Learning with Spark MLlib](https://www.baeldung.com/spark-mlib-machine-learning) - [Introduction to Spark Graph Processing with GraphFrames](https://www.baeldung.com/spark-graph-graphframes) +- [Apache Spark: Differences between Dataframes, Datasets and RDDs](https://www.baeldung.com/java-spark-dataframe-dataset-rdd) diff --git a/apache-spark/data/Tourist.csv b/apache-spark/data/Tourist.csv new file mode 100644 index 0000000000..4970e8c2f0 --- /dev/null +++ b/apache-spark/data/Tourist.csv @@ -0,0 +1,2247 @@ +Region,Country,Year,Series,Series_Type,Series_Type_Footnote,Value,Footnotes,Source +4,Afghanistan,2010,Tourism expenditure (millions of US dollars),,,147.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +4,Afghanistan,2016,Tourism expenditure (millions of US dollars),,,62.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +4,Afghanistan,2017,Tourism expenditure (millions of US dollars),,,16.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +4,Afghanistan,2018,Tourism expenditure (millions of US dollars),,,50.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +8,Albania,2010,Tourist/visitor arrivals (thousands),TF,,2191.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +8,Albania,2016,Tourist/visitor arrivals (thousands),TF,,4070.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +8,Albania,2017,Tourist/visitor arrivals (thousands),TF,,4643.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +8,Albania,2018,Tourist/visitor arrivals (thousands),TF,,5340.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +8,Albania,1995,Tourism expenditure (millions of US dollars),,,70.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +8,Albania,2005,Tourism expenditure (millions of US dollars),,,880.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +8,Albania,2010,Tourism expenditure (millions of US dollars),,,1778.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +8,Albania,2016,Tourism expenditure (millions of US dollars),,,1821.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +8,Albania,2017,Tourism expenditure (millions of US dollars),,,2050.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +8,Albania,2018,Tourism expenditure (millions of US dollars),,,2306.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +12,Algeria,1995,Tourist/visitor arrivals (thousands),VF,,520.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +12,Algeria,2005,Tourist/visitor arrivals (thousands),VF,,1443.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +12,Algeria,2010,Tourist/visitor arrivals (thousands),VF,,2070.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +12,Algeria,2016,Tourist/visitor arrivals (thousands),VF,,2039.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +12,Algeria,2017,Tourist/visitor arrivals (thousands),VF,,2451.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +12,Algeria,2018,Tourist/visitor arrivals (thousands),VF,,2657.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +12,Algeria,2005,Tourism expenditure (millions of US dollars),,,477.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +12,Algeria,2010,Tourism expenditure (millions of US dollars),,,324.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +12,Algeria,2016,Tourism expenditure (millions of US dollars),,,246.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +12,Algeria,2017,Tourism expenditure (millions of US dollars),,,172.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +16,American Samoa,1995,Tourist/visitor arrivals (thousands),TF,,34.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +16,American Samoa,2005,Tourist/visitor arrivals (thousands),TF,,24.5000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +16,American Samoa,2010,Tourist/visitor arrivals (thousands),TF,,23.1000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +16,American Samoa,2016,Tourist/visitor arrivals (thousands),TF,,20.1000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +16,American Samoa,2017,Tourist/visitor arrivals (thousands),TF,,20.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +16,American Samoa,2018,Tourist/visitor arrivals (thousands),TF,,20.2000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +16,American Samoa,2016,Tourism expenditure (millions of US dollars),,,22.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +16,American Samoa,2017,Tourism expenditure (millions of US dollars),,,22.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +20,Andorra,2005,Tourist/visitor arrivals (thousands),TF,,2418.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +20,Andorra,2010,Tourist/visitor arrivals (thousands),TF,,1808.0000,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +20,Andorra,2016,Tourist/visitor arrivals (thousands),TF,,2819.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +20,Andorra,2017,Tourist/visitor arrivals (thousands),TF,,3003.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +20,Andorra,2018,Tourist/visitor arrivals (thousands),TF,,3042.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +24,Angola,1995,Tourist/visitor arrivals (thousands),TF,,9.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +24,Angola,2005,Tourist/visitor arrivals (thousands),TF,,210.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +24,Angola,2010,Tourist/visitor arrivals (thousands),TF,,425.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +24,Angola,2016,Tourist/visitor arrivals (thousands),TF,,397.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +24,Angola,2017,Tourist/visitor arrivals (thousands),TF,,261.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +24,Angola,2018,Tourist/visitor arrivals (thousands),TF,,218.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +24,Angola,1995,Tourism expenditure (millions of US dollars),,,27.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +24,Angola,2005,Tourism expenditure (millions of US dollars),,,103.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +24,Angola,2010,Tourism expenditure (millions of US dollars),,,726.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +24,Angola,2016,Tourism expenditure (millions of US dollars),,,628.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +24,Angola,2017,Tourism expenditure (millions of US dollars),,,884.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +24,Angola,2018,Tourism expenditure (millions of US dollars),,,557.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +660,Anguilla,1995,Tourist/visitor arrivals (thousands),TF,,39.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +660,Anguilla,2005,Tourist/visitor arrivals (thousands),TF,,62.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +660,Anguilla,2010,Tourist/visitor arrivals (thousands),TF,,62.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +660,Anguilla,2016,Tourist/visitor arrivals (thousands),TF,,79.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +660,Anguilla,2017,Tourist/visitor arrivals (thousands),TF,,68.3000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +660,Anguilla,2018,Tourist/visitor arrivals (thousands),TF,,55.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +660,Anguilla,1995,Tourism expenditure (millions of US dollars),,,50.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +660,Anguilla,2005,Tourism expenditure (millions of US dollars),,,86.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +660,Anguilla,2010,Tourism expenditure (millions of US dollars),,,99.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +660,Anguilla,2016,Tourism expenditure (millions of US dollars),,,136.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +660,Anguilla,2017,Tourism expenditure (millions of US dollars),,,141.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +660,Anguilla,2018,Tourism expenditure (millions of US dollars),,,102.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +28,Antigua and Barbuda,1995,Tourist/visitor arrivals (thousands),TF,,220.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +28,Antigua and Barbuda,2005,Tourist/visitor arrivals (thousands),TF,,245.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +28,Antigua and Barbuda,2010,Tourist/visitor arrivals (thousands),TF,,230.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +28,Antigua and Barbuda,2016,Tourist/visitor arrivals (thousands),TF,,265.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +28,Antigua and Barbuda,2017,Tourist/visitor arrivals (thousands),TF,,247.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +28,Antigua and Barbuda,2018,Tourist/visitor arrivals (thousands),TF,,269.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +28,Antigua and Barbuda,1995,Tourism expenditure (millions of US dollars),,,247.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +28,Antigua and Barbuda,2005,Tourism expenditure (millions of US dollars),,,309.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +28,Antigua and Barbuda,2010,Tourism expenditure (millions of US dollars),,,298.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +28,Antigua and Barbuda,2016,Tourism expenditure (millions of US dollars),,,753.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +28,Antigua and Barbuda,2017,Tourism expenditure (millions of US dollars),,,737.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +28,Antigua and Barbuda,2018,Tourism expenditure (millions of US dollars),,,881.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +32,Argentina,1995,Tourist/visitor arrivals (thousands),TF,,2289.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +32,Argentina,2005,Tourist/visitor arrivals (thousands),TF,,3823.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +32,Argentina,2010,Tourist/visitor arrivals (thousands),TF,,6800.0000,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +32,Argentina,2016,Tourist/visitor arrivals (thousands),TF,,6668.0000,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +32,Argentina,2017,Tourist/visitor arrivals (thousands),TF,,6711.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +32,Argentina,2018,Tourist/visitor arrivals (thousands),TF,,6942.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +32,Argentina,1995,Tourism expenditure (millions of US dollars),,,2550.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +32,Argentina,2005,Tourism expenditure (millions of US dollars),,,3209.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +32,Argentina,2010,Tourism expenditure (millions of US dollars),,,5605.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +32,Argentina,2016,Tourism expenditure (millions of US dollars),,,5466.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +32,Argentina,2017,Tourism expenditure (millions of US dollars),,,5835.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +32,Argentina,2018,Tourism expenditure (millions of US dollars),,,5999.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +51,Armenia,1995,Tourist/visitor arrivals (thousands),TF,,12.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +51,Armenia,2005,Tourist/visitor arrivals (thousands),TF,,319.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +51,Armenia,2010,Tourist/visitor arrivals (thousands),TF,,684.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +51,Armenia,2016,Tourist/visitor arrivals (thousands),TF,,1260.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +51,Armenia,2017,Tourist/visitor arrivals (thousands),TF,,1495.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +51,Armenia,2018,Tourist/visitor arrivals (thousands),TF,,1652.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +51,Armenia,1995,Tourism expenditure (millions of US dollars),,,14.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +51,Armenia,2005,Tourism expenditure (millions of US dollars),,,243.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +51,Armenia,2010,Tourism expenditure (millions of US dollars),,,694.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +51,Armenia,2016,Tourism expenditure (millions of US dollars),,,988.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +51,Armenia,2017,Tourism expenditure (millions of US dollars),,,1140.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +51,Armenia,2018,Tourism expenditure (millions of US dollars),,,1237.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +533,Aruba,1995,Tourist/visitor arrivals (thousands),TF,,619.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +533,Aruba,2005,Tourist/visitor arrivals (thousands),TF,,733.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +533,Aruba,2010,Tourist/visitor arrivals (thousands),TF,,824.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +533,Aruba,2016,Tourist/visitor arrivals (thousands),TF,,1102.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +533,Aruba,2017,Tourist/visitor arrivals (thousands),TF,,1070.5000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +533,Aruba,2018,Tourist/visitor arrivals (thousands),TF,,1082.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +533,Aruba,1995,Tourism expenditure (millions of US dollars),,,554.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +533,Aruba,2005,Tourism expenditure (millions of US dollars),,,1097.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +533,Aruba,2010,Tourism expenditure (millions of US dollars),,,1254.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +533,Aruba,2016,Tourism expenditure (millions of US dollars),,,1764.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +533,Aruba,2017,Tourism expenditure (millions of US dollars),,,1857.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +533,Aruba,2018,Tourism expenditure (millions of US dollars),,,2024.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +36,Australia,1995,Tourist/visitor arrivals (thousands),VF,,3726.0000,Excluding nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +36,Australia,2005,Tourist/visitor arrivals (thousands),VF,,5499.0000,Excluding nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +36,Australia,2010,Tourist/visitor arrivals (thousands),VF,,5790.0000,Excluding nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +36,Australia,2016,Tourist/visitor arrivals (thousands),VF,,8269.0000,Excluding nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +36,Australia,2017,Tourist/visitor arrivals (thousands),VF,,8815.0000,Excluding nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +36,Australia,2018,Tourist/visitor arrivals (thousands),VF,,9246.0000,Excluding nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +36,Australia,1995,Tourism expenditure (millions of US dollars),,,10370.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +36,Australia,2005,Tourism expenditure (millions of US dollars),,,19719.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +36,Australia,2010,Tourism expenditure (millions of US dollars),,,31064.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +36,Australia,2016,Tourism expenditure (millions of US dollars),,,39059.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +36,Australia,2017,Tourism expenditure (millions of US dollars),,,43975.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +36,Australia,2018,Tourism expenditure (millions of US dollars),,,47327.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +40,Austria,1995,Tourist/visitor arrivals (thousands),TCE,,17173.0000,Only paid accommodation; excluding stays at friends and relatives and second homes.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +40,Austria,2005,Tourist/visitor arrivals (thousands),TCE,,19952.0000,Only paid accommodation; excluding stays at friends and relatives and second homes.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +40,Austria,2010,Tourist/visitor arrivals (thousands),TCE,,22004.0000,Only paid accommodation; excluding stays at friends and relatives and second homes.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +40,Austria,2016,Tourist/visitor arrivals (thousands),TCE,,28121.0000,Only paid accommodation; excluding stays at friends and relatives and second homes.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +40,Austria,2017,Tourist/visitor arrivals (thousands),TCE,,29460.0000,Only paid accommodation; excluding stays at friends and relatives and second homes.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +40,Austria,2018,Tourist/visitor arrivals (thousands),TCE,,30816.0000,Only paid accommodation; excluding stays at friends and relatives and second homes.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +40,Austria,1995,Tourism expenditure (millions of US dollars),,,13435.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +40,Austria,2005,Tourism expenditure (millions of US dollars),,,16243.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +40,Austria,2010,Tourism expenditure (millions of US dollars),,,18751.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +40,Austria,2016,Tourism expenditure (millions of US dollars),,,19244.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +40,Austria,2017,Tourism expenditure (millions of US dollars),,,20333.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +40,Austria,2018,Tourism expenditure (millions of US dollars),,,23233.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +31,Azerbaijan,2005,Tourist/visitor arrivals (thousands),TF,,693.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +31,Azerbaijan,2010,Tourist/visitor arrivals (thousands),TF,,1280.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +31,Azerbaijan,2016,Tourist/visitor arrivals (thousands),TF,,2044.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +31,Azerbaijan,2017,Tourist/visitor arrivals (thousands),TF,,2454.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +31,Azerbaijan,2018,Tourist/visitor arrivals (thousands),TF,,2633.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +31,Azerbaijan,1995,Tourism expenditure (millions of US dollars),,,87.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +31,Azerbaijan,2005,Tourism expenditure (millions of US dollars),,,100.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +31,Azerbaijan,2010,Tourism expenditure (millions of US dollars),,,792.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +31,Azerbaijan,2016,Tourism expenditure (millions of US dollars),,,2855.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +31,Azerbaijan,2017,Tourism expenditure (millions of US dollars),,,3214.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +31,Azerbaijan,2018,Tourism expenditure (millions of US dollars),,,2830.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +44,Bahamas,1995,Tourist/visitor arrivals (thousands),TF,,1598.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +44,Bahamas,2005,Tourist/visitor arrivals (thousands),TF,,1608.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +44,Bahamas,2010,Tourist/visitor arrivals (thousands),TF,,1370.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +44,Bahamas,2016,Tourist/visitor arrivals (thousands),TF,,1500.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +44,Bahamas,2017,Tourist/visitor arrivals (thousands),TF,,1442.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +44,Bahamas,2018,Tourist/visitor arrivals (thousands),TF,,1633.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +44,Bahamas,1995,Tourism expenditure (millions of US dollars),,,1356.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +44,Bahamas,2005,Tourism expenditure (millions of US dollars),,,2081.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +44,Bahamas,2010,Tourism expenditure (millions of US dollars),,,2159.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +44,Bahamas,2016,Tourism expenditure (millions of US dollars),,,3091.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +44,Bahamas,2017,Tourism expenditure (millions of US dollars),,,3017.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +44,Bahamas,2018,Tourism expenditure (millions of US dollars),,,3383.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +48,Bahrain,1995,Tourist/visitor arrivals (thousands),VF,,2311.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +48,Bahrain,2005,Tourist/visitor arrivals (thousands),VF,,6313.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +48,Bahrain,2010,Tourist/visitor arrivals (thousands),VF,,11952.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +48,Bahrain,2016,Tourist/visitor arrivals (thousands),VF,,10158.0000,Break in the time series.;Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +48,Bahrain,2017,Tourist/visitor arrivals (thousands),VF,,11374.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +48,Bahrain,2018,Tourist/visitor arrivals (thousands),VF,,12045.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +48,Bahrain,1995,Tourism expenditure (millions of US dollars),,,593.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +48,Bahrain,2005,Tourism expenditure (millions of US dollars),,,1603.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +48,Bahrain,2010,Tourism expenditure (millions of US dollars),,,2163.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +48,Bahrain,2016,Tourism expenditure (millions of US dollars),,,4021.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +48,Bahrain,2017,Tourism expenditure (millions of US dollars),,,4380.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +48,Bahrain,2018,Tourism expenditure (millions of US dollars),,,3834.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +50,Bangladesh,1995,Tourist/visitor arrivals (thousands),TF,,156.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +50,Bangladesh,2005,Tourist/visitor arrivals (thousands),TF,,208.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +50,Bangladesh,2010,Tourist/visitor arrivals (thousands),TF,,303.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +50,Bangladesh,2016,Tourist/visitor arrivals (thousands),TF,,830.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +50,Bangladesh,2017,Tourist/visitor arrivals (thousands),TF,,1026.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +50,Bangladesh,2005,Tourism expenditure (millions of US dollars),,,82.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +50,Bangladesh,2010,Tourism expenditure (millions of US dollars),,,103.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +50,Bangladesh,2016,Tourism expenditure (millions of US dollars),,,214.3000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +50,Bangladesh,2017,Tourism expenditure (millions of US dollars),,,348.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +50,Bangladesh,2018,Tourism expenditure (millions of US dollars),,,357.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +52,Barbados,1995,Tourist/visitor arrivals (thousands),TF,,442.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +52,Barbados,2005,Tourist/visitor arrivals (thousands),TF,,548.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +52,Barbados,2010,Tourist/visitor arrivals (thousands),TF,,532.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +52,Barbados,2016,Tourist/visitor arrivals (thousands),TF,,632.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +52,Barbados,2017,Tourist/visitor arrivals (thousands),TF,,664.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +52,Barbados,2018,Tourist/visitor arrivals (thousands),TF,,680.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +52,Barbados,1995,Tourism expenditure (millions of US dollars),,,630.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +52,Barbados,2005,Tourism expenditure (millions of US dollars),,,1081.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +52,Barbados,2010,Tourism expenditure (millions of US dollars),,,1074.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +112,Belarus,1995,Tourist/visitor arrivals (thousands),TF,,160.6000,Excludes the Belarusian-Russian border segment.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +112,Belarus,2005,Tourist/visitor arrivals (thousands),TF,,91.0000,Excludes the Belarusian-Russian border segment.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +112,Belarus,2010,Tourist/visitor arrivals (thousands),TF,,119.3000,Excludes the Belarusian-Russian border segment.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +112,Belarus,2016,Tourist/visitor arrivals (thousands),TF,,10935.4000,Includes estimation of the Belarusian-Russian border segment.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +112,Belarus,2017,Tourist/visitor arrivals (thousands),TF,,11060.2000,Includes estimation of the Belarusian-Russian border segment.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +112,Belarus,2018,Tourist/visitor arrivals (thousands),TF,,11501.6000,Includes estimation of the Belarusian-Russian border segment.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +112,Belarus,1995,Tourism expenditure (millions of US dollars),,,28.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +112,Belarus,2005,Tourism expenditure (millions of US dollars),,,346.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +112,Belarus,2010,Tourism expenditure (millions of US dollars),,,665.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +112,Belarus,2016,Tourism expenditure (millions of US dollars),,,1019.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +112,Belarus,2017,Tourism expenditure (millions of US dollars),,,1124.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +112,Belarus,2018,Tourism expenditure (millions of US dollars),,,1221.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +56,Belgium,1995,Tourist/visitor arrivals (thousands),TCE,,5560.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +56,Belgium,2005,Tourist/visitor arrivals (thousands),TCE,,6747.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +56,Belgium,2010,Tourist/visitor arrivals (thousands),TCE,,7186.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +56,Belgium,2016,Tourist/visitor arrivals (thousands),TCE,,7481.0000,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +56,Belgium,2017,Tourist/visitor arrivals (thousands),TCE,,8385.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +56,Belgium,2018,Tourist/visitor arrivals (thousands),TCE,,9119.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +56,Belgium,2005,Tourism expenditure (millions of US dollars),,,10881.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +56,Belgium,2010,Tourism expenditure (millions of US dollars),,,12680.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +56,Belgium,2016,Tourism expenditure (millions of US dollars),,,8784.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +56,Belgium,2017,Tourism expenditure (millions of US dollars),,,9636.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +56,Belgium,2018,Tourism expenditure (millions of US dollars),,,10381.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +84,Belize,1995,Tourist/visitor arrivals (thousands),TF,,131.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +84,Belize,2005,Tourist/visitor arrivals (thousands),TF,,237.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +84,Belize,2010,Tourist/visitor arrivals (thousands),TF,,242.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +84,Belize,2016,Tourist/visitor arrivals (thousands),TF,,386.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +84,Belize,2017,Tourist/visitor arrivals (thousands),TF,,427.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +84,Belize,2018,Tourist/visitor arrivals (thousands),TF,,489.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +84,Belize,1995,Tourism expenditure (millions of US dollars),,,78.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +84,Belize,2005,Tourism expenditure (millions of US dollars),,,214.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +84,Belize,2010,Tourism expenditure (millions of US dollars),,,264.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +84,Belize,2016,Tourism expenditure (millions of US dollars),,,391.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +84,Belize,2017,Tourism expenditure (millions of US dollars),,,427.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +84,Belize,2018,Tourism expenditure (millions of US dollars),,,487.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +204,Benin,1995,Tourist/visitor arrivals (thousands),TF,,138.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +204,Benin,2005,Tourist/visitor arrivals (thousands),TF,,176.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +204,Benin,2010,Tourist/visitor arrivals (thousands),TF,,199.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +204,Benin,2016,Tourist/visitor arrivals (thousands),TF,,267.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +204,Benin,2017,Tourist/visitor arrivals (thousands),TF,,281.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +204,Benin,2018,Tourist/visitor arrivals (thousands),TF,,295.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +204,Benin,2005,Tourism expenditure (millions of US dollars),,,107.7000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +204,Benin,2010,Tourism expenditure (millions of US dollars),,,149.4000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +204,Benin,2016,Tourism expenditure (millions of US dollars),,,129.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +204,Benin,2017,Tourism expenditure (millions of US dollars),,,160.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +60,Bermuda,1995,Tourist/visitor arrivals (thousands),TF,,387.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +60,Bermuda,2005,Tourist/visitor arrivals (thousands),TF,,270.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +60,Bermuda,2010,Tourist/visitor arrivals (thousands),TF,,232.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +60,Bermuda,2016,Tourist/visitor arrivals (thousands),TF,,244.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +60,Bermuda,2017,Tourist/visitor arrivals (thousands),TF,,270.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +60,Bermuda,2018,Tourist/visitor arrivals (thousands),TF,,282.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +60,Bermuda,1995,Tourism expenditure (millions of US dollars),,,488.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +60,Bermuda,2005,Tourism expenditure (millions of US dollars),,,429.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +60,Bermuda,2010,Tourism expenditure (millions of US dollars),,,442.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +60,Bermuda,2016,Tourism expenditure (millions of US dollars),,,441.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +60,Bermuda,2017,Tourism expenditure (millions of US dollars),,,513.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +60,Bermuda,2018,Tourism expenditure (millions of US dollars),,,583.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +64,Bhutan,1995,Tourist/visitor arrivals (thousands),TF,,4.8000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +64,Bhutan,2005,Tourist/visitor arrivals (thousands),TF,,13.6000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +64,Bhutan,2010,Tourist/visitor arrivals (thousands),TF,,41.0000,Break in the time series.;Including regional high end tourists.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +64,Bhutan,2016,Tourist/visitor arrivals (thousands),TF,,210.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +64,Bhutan,2017,Tourist/visitor arrivals (thousands),TF,,255.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +64,Bhutan,2018,Tourist/visitor arrivals (thousands),TF,,274.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +64,Bhutan,1995,Tourism expenditure (millions of US dollars),,,5.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +64,Bhutan,2005,Tourism expenditure (millions of US dollars),,,19.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +64,Bhutan,2010,Tourism expenditure (millions of US dollars),,,64.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +64,Bhutan,2016,Tourism expenditure (millions of US dollars),,,139.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +64,Bhutan,2017,Tourism expenditure (millions of US dollars),,,153.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +64,Bhutan,2018,Tourism expenditure (millions of US dollars),,,121.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +68,Bolivia (Plurin. State of),1995,Tourist/visitor arrivals (thousands),TF,,284.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +68,Bolivia (Plurin. State of),2005,Tourist/visitor arrivals (thousands),TF,,524.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +68,Bolivia (Plurin. State of),2010,Tourist/visitor arrivals (thousands),TF,,679.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +68,Bolivia (Plurin. State of),2016,Tourist/visitor arrivals (thousands),TF,,961.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +68,Bolivia (Plurin. State of),2017,Tourist/visitor arrivals (thousands),TF,,1109.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +68,Bolivia (Plurin. State of),2018,Tourist/visitor arrivals (thousands),TF,,1142.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +68,Bolivia (Plurin. State of),1995,Tourism expenditure (millions of US dollars),,,92.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +68,Bolivia (Plurin. State of),2005,Tourism expenditure (millions of US dollars),,,345.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +68,Bolivia (Plurin. State of),2010,Tourism expenditure (millions of US dollars),,,339.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +68,Bolivia (Plurin. State of),2016,Tourism expenditure (millions of US dollars),,,827.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +68,Bolivia (Plurin. State of),2017,Tourism expenditure (millions of US dollars),,,912.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +68,Bolivia (Plurin. State of),2018,Tourism expenditure (millions of US dollars),,,970.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +669,Bonaire,1995,Tourist/visitor arrivals (thousands),TF,,59.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +669,Bonaire,2005,Tourist/visitor arrivals (thousands),TF,,63.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +669,Bonaire,2010,Tourist/visitor arrivals (thousands),TF,,71.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +669,Bonaire,1995,Tourism expenditure (millions of US dollars),,,37.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +669,Bonaire,2005,Tourism expenditure (millions of US dollars),,,87.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +70,Bosnia and Herzegovina,2005,Tourist/visitor arrivals (thousands),TCE,,217.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +70,Bosnia and Herzegovina,2010,Tourist/visitor arrivals (thousands),TCE,,365.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +70,Bosnia and Herzegovina,2016,Tourist/visitor arrivals (thousands),TCE,,778.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +70,Bosnia and Herzegovina,2017,Tourist/visitor arrivals (thousands),TCE,,923.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +70,Bosnia and Herzegovina,2018,Tourist/visitor arrivals (thousands),TCE,,1053.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +70,Bosnia and Herzegovina,2005,Tourism expenditure (millions of US dollars),,,557.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +70,Bosnia and Herzegovina,2010,Tourism expenditure (millions of US dollars),,,662.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +70,Bosnia and Herzegovina,2016,Tourism expenditure (millions of US dollars),,,876.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +70,Bosnia and Herzegovina,2017,Tourism expenditure (millions of US dollars),,,985.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +70,Bosnia and Herzegovina,2018,Tourism expenditure (millions of US dollars),,,1081.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +72,Botswana,1995,Tourist/visitor arrivals (thousands),TF,,521.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +72,Botswana,2005,Tourist/visitor arrivals (thousands),TF,,1474.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +72,Botswana,2010,Tourist/visitor arrivals (thousands),TF,,1973.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +72,Botswana,2016,Tourist/visitor arrivals (thousands),TF,,1574.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +72,Botswana,2017,Tourist/visitor arrivals (thousands),TF,,1623.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +72,Botswana,1995,Tourism expenditure (millions of US dollars),,,176.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +72,Botswana,2005,Tourism expenditure (millions of US dollars),,,563.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +72,Botswana,2010,Tourism expenditure (millions of US dollars),,,440.1000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +72,Botswana,2016,Tourism expenditure (millions of US dollars),,,505.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +72,Botswana,2017,Tourism expenditure (millions of US dollars),,,541.6000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +72,Botswana,2018,Tourism expenditure (millions of US dollars),,,575.3000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +76,Brazil,1995,Tourist/visitor arrivals (thousands),TF,,1991.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +76,Brazil,2005,Tourist/visitor arrivals (thousands),TF,,5358.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +76,Brazil,2010,Tourist/visitor arrivals (thousands),TF,,5161.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +76,Brazil,2016,Tourist/visitor arrivals (thousands),TF,,6547.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +76,Brazil,2017,Tourist/visitor arrivals (thousands),TF,,6589.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +76,Brazil,2018,Tourist/visitor arrivals (thousands),TF,,6621.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +76,Brazil,1995,Tourism expenditure (millions of US dollars),,,1085.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +76,Brazil,2005,Tourism expenditure (millions of US dollars),,,4168.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +76,Brazil,2010,Tourism expenditure (millions of US dollars),,,5522.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +76,Brazil,2016,Tourism expenditure (millions of US dollars),,,6613.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +76,Brazil,2017,Tourism expenditure (millions of US dollars),,,6175.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +76,Brazil,2018,Tourism expenditure (millions of US dollars),,,6324.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +92,British Virgin Islands,1995,Tourist/visitor arrivals (thousands),TF,,219.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +92,British Virgin Islands,2005,Tourist/visitor arrivals (thousands),TF,,337.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +92,British Virgin Islands,2010,Tourist/visitor arrivals (thousands),TF,,330.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +92,British Virgin Islands,2016,Tourist/visitor arrivals (thousands),TF,,408.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +92,British Virgin Islands,2017,Tourist/visitor arrivals (thousands),TF,,335.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +92,British Virgin Islands,2018,Tourist/visitor arrivals (thousands),TF,,192.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +92,British Virgin Islands,1995,Tourism expenditure (millions of US dollars),,,211.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +92,British Virgin Islands,2005,Tourism expenditure (millions of US dollars),,,412.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +92,British Virgin Islands,2010,Tourism expenditure (millions of US dollars),,,389.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +96,Brunei Darussalam,2005,Tourist/visitor arrivals (thousands),TF,,126.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +96,Brunei Darussalam,2010,Tourist/visitor arrivals (thousands),TF,,214.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +96,Brunei Darussalam,2016,Tourist/visitor arrivals (thousands),TF,,219.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +96,Brunei Darussalam,2017,Tourist/visitor arrivals (thousands),TF,,259.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +96,Brunei Darussalam,2018,Tourist/visitor arrivals (thousands),TF,,278.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +96,Brunei Darussalam,2005,Tourism expenditure (millions of US dollars),,,191.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +96,Brunei Darussalam,2016,Tourism expenditure (millions of US dollars),,,144.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +96,Brunei Darussalam,2017,Tourism expenditure (millions of US dollars),,,177.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +96,Brunei Darussalam,2018,Tourism expenditure (millions of US dollars),,,190.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +100,Bulgaria,1995,Tourist/visitor arrivals (thousands),TF,,3466.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +100,Bulgaria,2005,Tourist/visitor arrivals (thousands),TF,,4837.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +100,Bulgaria,2010,Tourist/visitor arrivals (thousands),TF,,6047.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +100,Bulgaria,2016,Tourist/visitor arrivals (thousands),TF,,8252.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +100,Bulgaria,2017,Tourist/visitor arrivals (thousands),TF,,8883.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +100,Bulgaria,2018,Tourist/visitor arrivals (thousands),TF,,9273.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +100,Bulgaria,1995,Tourism expenditure (millions of US dollars),,,662.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +100,Bulgaria,2005,Tourism expenditure (millions of US dollars),,,3063.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +100,Bulgaria,2010,Tourism expenditure (millions of US dollars),,,3807.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +100,Bulgaria,2016,Tourism expenditure (millions of US dollars),,,4164.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +100,Bulgaria,2017,Tourism expenditure (millions of US dollars),,,4678.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +100,Bulgaria,2018,Tourism expenditure (millions of US dollars),,,5072.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +854,Burkina Faso,1995,Tourist/visitor arrivals (thousands),THS,,124.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +854,Burkina Faso,2005,Tourist/visitor arrivals (thousands),THS,,245.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +854,Burkina Faso,2010,Tourist/visitor arrivals (thousands),THS,,274.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +854,Burkina Faso,2016,Tourist/visitor arrivals (thousands),THS,,152.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +854,Burkina Faso,2017,Tourist/visitor arrivals (thousands),THS,,143.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +854,Burkina Faso,2018,Tourist/visitor arrivals (thousands),THS,,144.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +854,Burkina Faso,2005,Tourism expenditure (millions of US dollars),,,46.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +854,Burkina Faso,2010,Tourism expenditure (millions of US dollars),,,105.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +854,Burkina Faso,2016,Tourism expenditure (millions of US dollars),,,172.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +854,Burkina Faso,2017,Tourism expenditure (millions of US dollars),,,172.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +108,Burundi,1995,Tourist/visitor arrivals (thousands),TF,,34.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +108,Burundi,2005,Tourist/visitor arrivals (thousands),TF,,148.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +108,Burundi,2010,Tourist/visitor arrivals (thousands),TF,,142.0000,Break in the time series.;Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +108,Burundi,2016,Tourist/visitor arrivals (thousands),TF,,187.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +108,Burundi,2017,Tourist/visitor arrivals (thousands),TF,,299.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +108,Burundi,1995,Tourism expenditure (millions of US dollars),,,2.4250,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +108,Burundi,2005,Tourism expenditure (millions of US dollars),,,1.9000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +108,Burundi,2010,Tourism expenditure (millions of US dollars),,,2.1000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +132,Cabo Verde,1995,Tourist/visitor arrivals (thousands),TF,,28.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +132,Cabo Verde,2005,Tourist/visitor arrivals (thousands),TF,,198.0000,Non-resident tourists staying in hotels and similar establishments.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +132,Cabo Verde,2010,Tourist/visitor arrivals (thousands),TF,,336.0000,Non-resident tourists staying in hotels and similar establishments.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +132,Cabo Verde,2016,Tourist/visitor arrivals (thousands),TF,,598.0000,Non-resident tourists staying in hotels and similar establishments.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +132,Cabo Verde,2017,Tourist/visitor arrivals (thousands),TF,,668.0000,Non-resident tourists staying in hotels and similar establishments.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +132,Cabo Verde,2018,Tourist/visitor arrivals (thousands),TF,,710.0000,Non-resident tourists staying in hotels and similar establishments.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +132,Cabo Verde,1995,Tourism expenditure (millions of US dollars),,,29.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +132,Cabo Verde,2005,Tourism expenditure (millions of US dollars),,,177.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +132,Cabo Verde,2010,Tourism expenditure (millions of US dollars),,,387.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +132,Cabo Verde,2016,Tourism expenditure (millions of US dollars),,,397.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +132,Cabo Verde,2017,Tourism expenditure (millions of US dollars),,,450.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +132,Cabo Verde,2018,Tourism expenditure (millions of US dollars),,,524.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +116,Cambodia,1995,Tourist/visitor arrivals (thousands),TF,,220.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +116,Cambodia,2005,Tourist/visitor arrivals (thousands),TF,,1422.0000,Arrivals by all means of transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +116,Cambodia,2010,Tourist/visitor arrivals (thousands),TF,,2508.0000,Arrivals by all means of transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +116,Cambodia,2016,Tourist/visitor arrivals (thousands),TF,,5012.0000,Arrivals by all means of transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +116,Cambodia,2017,Tourist/visitor arrivals (thousands),TF,,5602.0000,Arrivals by all means of transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +116,Cambodia,2018,Tourist/visitor arrivals (thousands),TF,,6201.0000,Arrivals by all means of transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +116,Cambodia,1995,Tourism expenditure (millions of US dollars),,,71.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +116,Cambodia,2005,Tourism expenditure (millions of US dollars),,,929.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +116,Cambodia,2010,Tourism expenditure (millions of US dollars),,,1671.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +116,Cambodia,2016,Tourism expenditure (millions of US dollars),,,3523.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +116,Cambodia,2017,Tourism expenditure (millions of US dollars),,,4024.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +116,Cambodia,2018,Tourism expenditure (millions of US dollars),,,4832.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +120,Cameroon,2010,Tourist/visitor arrivals (thousands),VF,,573.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +120,Cameroon,2016,Tourist/visitor arrivals (thousands),VF,,994.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +120,Cameroon,2017,Tourist/visitor arrivals (thousands),VF,,1081.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +120,Cameroon,1995,Tourism expenditure (millions of US dollars),,,75.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +120,Cameroon,2005,Tourism expenditure (millions of US dollars),,,229.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +120,Cameroon,2010,Tourism expenditure (millions of US dollars),,,171.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +120,Cameroon,2016,Tourism expenditure (millions of US dollars),,,508.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +120,Cameroon,2017,Tourism expenditure (millions of US dollars),,,543.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +120,Cameroon,2018,Tourism expenditure (millions of US dollars),,,633.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +124,Canada,1995,Tourist/visitor arrivals (thousands),TF,,16932.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +124,Canada,2005,Tourist/visitor arrivals (thousands),TF,,18771.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +124,Canada,2010,Tourist/visitor arrivals (thousands),TF,,16219.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +124,Canada,2016,Tourist/visitor arrivals (thousands),TF,,19971.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +124,Canada,2017,Tourist/visitor arrivals (thousands),TF,,20883.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +124,Canada,2018,Tourist/visitor arrivals (thousands),TF,,21134.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +124,Canada,1995,Tourism expenditure (millions of US dollars),,,9176.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +124,Canada,2005,Tourism expenditure (millions of US dollars),,,15887.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +124,Canada,2010,Tourism expenditure (millions of US dollars),,,18439.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +136,Cayman Islands,1995,Tourist/visitor arrivals (thousands),TF,,361.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +136,Cayman Islands,2005,Tourist/visitor arrivals (thousands),TF,,168.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +136,Cayman Islands,2010,Tourist/visitor arrivals (thousands),TF,,288.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +136,Cayman Islands,2016,Tourist/visitor arrivals (thousands),TF,,385.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +136,Cayman Islands,2017,Tourist/visitor arrivals (thousands),TF,,418.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +136,Cayman Islands,2018,Tourist/visitor arrivals (thousands),TF,,463.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +136,Cayman Islands,1995,Tourism expenditure (millions of US dollars),,,394.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +136,Cayman Islands,2005,Tourism expenditure (millions of US dollars),,,356.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +136,Cayman Islands,2010,Tourism expenditure (millions of US dollars),,,465.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +136,Cayman Islands,2016,Tourism expenditure (millions of US dollars),,,696.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +136,Cayman Islands,2017,Tourism expenditure (millions of US dollars),,,782.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +136,Cayman Islands,2018,Tourism expenditure (millions of US dollars),,,880.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +140,Central African Republic,1995,Tourist/visitor arrivals (thousands),TF,,26.0000,Arrivals by air at Bangui only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +140,Central African Republic,2005,Tourist/visitor arrivals (thousands),TF,,12.0000,Arrivals by air at Bangui only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +140,Central African Republic,2010,Tourist/visitor arrivals (thousands),TF,,53.8000,Arrivals by air at Bangui only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +140,Central African Republic,2016,Tourist/visitor arrivals (thousands),TF,,82.0000,Arrivals by air at Bangui only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +140,Central African Republic,2017,Tourist/visitor arrivals (thousands),TF,,107.0000,Arrivals by air at Bangui only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +140,Central African Republic,1995,Tourism expenditure (millions of US dollars),,,4.0000,Arrivals by air at Bangui only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +140,Central African Republic,2005,Tourism expenditure (millions of US dollars),,,7.2000,Arrivals by air at Bangui only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +140,Central African Republic,2010,Tourism expenditure (millions of US dollars),,,14.4000,Arrivals by air at Bangui only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +148,Chad,2010,Tourist/visitor arrivals (thousands),TF,,71.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +148,Chad,2016,Tourist/visitor arrivals (thousands),TF,,98.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +148,Chad,2017,Tourist/visitor arrivals (thousands),TF,,87.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +148,Chad,1995,Tourism expenditure (millions of US dollars),,,43.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +152,Chile,1995,Tourist/visitor arrivals (thousands),TF,,1540.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +152,Chile,2005,Tourist/visitor arrivals (thousands),TF,,2027.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +152,Chile,2010,Tourist/visitor arrivals (thousands),TF,,2801.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +152,Chile,2016,Tourist/visitor arrivals (thousands),TF,,5641.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +152,Chile,2017,Tourist/visitor arrivals (thousands),TF,,6450.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +152,Chile,2018,Tourist/visitor arrivals (thousands),TF,,5723.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +152,Chile,1995,Tourism expenditure (millions of US dollars),,,1186.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +152,Chile,2005,Tourism expenditure (millions of US dollars),,,1608.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +152,Chile,2010,Tourism expenditure (millions of US dollars),,,2362.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +152,Chile,2016,Tourism expenditure (millions of US dollars),,,3744.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +152,Chile,2017,Tourism expenditure (millions of US dollars),,,4372.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +152,Chile,2018,Tourism expenditure (millions of US dollars),,,3972.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +156,China,1995,Tourist/visitor arrivals (thousands),TF,,20034.0000,"For statistical purposes, the data for China do not include those for the Hong Kong Special Administrative Region (Hong Kong SAR), Macao Special Administrative Region (Macao SAR) and Taiwan Province of China.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +156,China,2005,Tourist/visitor arrivals (thousands),TF,,46809.0000,"For statistical purposes, the data for China do not include those for the Hong Kong Special Administrative Region (Hong Kong SAR), Macao Special Administrative Region (Macao SAR) and Taiwan Province of China.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +156,China,2010,Tourist/visitor arrivals (thousands),TF,,55664.0000,"For statistical purposes, the data for China do not include those for the Hong Kong Special Administrative Region (Hong Kong SAR), Macao Special Administrative Region (Macao SAR) and Taiwan Province of China.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +156,China,2016,Tourist/visitor arrivals (thousands),TF,,59270.0000,"For statistical purposes, the data for China do not include those for the Hong Kong Special Administrative Region (Hong Kong SAR), Macao Special Administrative Region (Macao SAR) and Taiwan Province of China.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +156,China,2017,Tourist/visitor arrivals (thousands),TF,,60740.0000,"For statistical purposes, the data for China do not include those for the Hong Kong Special Administrative Region (Hong Kong SAR), Macao Special Administrative Region (Macao SAR) and Taiwan Province of China.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +156,China,2018,Tourist/visitor arrivals (thousands),TF,,62900.0000,"For statistical purposes, the data for China do not include those for the Hong Kong Special Administrative Region (Hong Kong SAR), Macao Special Administrative Region (Macao SAR) and Taiwan Province of China.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +156,China,1995,Tourism expenditure (millions of US dollars),,,8730.0000,"For statistical purposes, the data for China do not include those for the Hong Kong Special Administrative Region (Hong Kong SAR), Macao Special Administrative Region (Macao SAR) and Taiwan Province of China.;Excluding passenger transport.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +156,China,2005,Tourism expenditure (millions of US dollars),,,29296.0000,"For statistical purposes, the data for China do not include those for the Hong Kong Special Administrative Region (Hong Kong SAR), Macao Special Administrative Region (Macao SAR) and Taiwan Province of China.;Excluding passenger transport.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +156,China,2010,Tourism expenditure (millions of US dollars),,,45814.0000,"For statistical purposes, the data for China do not include those for the Hong Kong Special Administrative Region (Hong Kong SAR), Macao Special Administrative Region (Macao SAR) and Taiwan Province of China.;Excluding passenger transport.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +156,China,2016,Tourism expenditure (millions of US dollars),,,44432.0000,"For statistical purposes, the data for China do not include those for the Hong Kong Special Administrative Region (Hong Kong SAR), Macao Special Administrative Region (Macao SAR) and Taiwan Province of China.;Excluding passenger transport.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +156,China,2017,Tourism expenditure (millions of US dollars),,,38559.0000,"For statistical purposes, the data for China do not include those for the Hong Kong Special Administrative Region (Hong Kong SAR), Macao Special Administrative Region (Macao SAR) and Taiwan Province of China.;Excluding passenger transport.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +156,China,2018,Tourism expenditure (millions of US dollars),,,40386.0000,"For statistical purposes, the data for China do not include those for the Hong Kong Special Administrative Region (Hong Kong SAR), Macao Special Administrative Region (Macao SAR) and Taiwan Province of China.;Excluding passenger transport.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +344,"China, Hong Kong SAR",2005,Tourist/visitor arrivals (thousands),TF,,14773.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +344,"China, Hong Kong SAR",2010,Tourist/visitor arrivals (thousands),TF,,20085.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +344,"China, Hong Kong SAR",2016,Tourist/visitor arrivals (thousands),TF,,26553.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +344,"China, Hong Kong SAR",2017,Tourist/visitor arrivals (thousands),TF,,27884.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +344,"China, Hong Kong SAR",2018,Tourist/visitor arrivals (thousands),TF,,29263.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +344,"China, Hong Kong SAR",2005,Tourism expenditure (millions of US dollars),,,13588.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +344,"China, Hong Kong SAR",2010,Tourism expenditure (millions of US dollars),,,27208.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +344,"China, Hong Kong SAR",2016,Tourism expenditure (millions of US dollars),,,37838.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +344,"China, Hong Kong SAR",2017,Tourism expenditure (millions of US dollars),,,38170.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +344,"China, Hong Kong SAR",2018,Tourism expenditure (millions of US dollars),,,41870.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +446,"China, Macao SAR",1995,Tourist/visitor arrivals (thousands),TF,,4202.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +446,"China, Macao SAR",2005,Tourist/visitor arrivals (thousands),TF,,9014.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +446,"China, Macao SAR",2010,Tourist/visitor arrivals (thousands),TF,,11926.0000,"Does not include other non-residents namely workers, students, etc.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +446,"China, Macao SAR",2016,Tourist/visitor arrivals (thousands),TF,,15703.6000,"Does not include other non-residents namely workers, students, etc.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +446,"China, Macao SAR",2017,Tourist/visitor arrivals (thousands),TF,,17255.0000,"Does not include other non-residents namely workers, students, etc.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +446,"China, Macao SAR",2018,Tourist/visitor arrivals (thousands),TF,,18493.0000,"Does not include other non-residents namely workers, students, etc.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +446,"China, Macao SAR",1995,Tourism expenditure (millions of US dollars),,,3233.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +446,"China, Macao SAR",2005,Tourism expenditure (millions of US dollars),,,7181.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +446,"China, Macao SAR",2010,Tourism expenditure (millions of US dollars),,,22688.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +446,"China, Macao SAR",2016,Tourism expenditure (millions of US dollars),,,31015.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +446,"China, Macao SAR",2017,Tourism expenditure (millions of US dollars),,,36465.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +446,"China, Macao SAR",2018,Tourism expenditure (millions of US dollars),,,40358.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +170,Colombia,1995,Tourist/visitor arrivals (thousands),TF,,1399.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +170,Colombia,2005,Tourist/visitor arrivals (thousands),TF,,933.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +170,Colombia,2010,Tourist/visitor arrivals (thousands),TF,,1405.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +170,Colombia,2016,Tourist/visitor arrivals (thousands),TF,,3254.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +170,Colombia,2017,Tourist/visitor arrivals (thousands),TF,,3631.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +170,Colombia,2018,Tourist/visitor arrivals (thousands),TF,,3904.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +170,Colombia,1995,Tourism expenditure (millions of US dollars),,,887.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +170,Colombia,2005,Tourism expenditure (millions of US dollars),,,1891.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +170,Colombia,2010,Tourism expenditure (millions of US dollars),,,3441.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +170,Colombia,2016,Tourism expenditure (millions of US dollars),,,5584.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +170,Colombia,2017,Tourism expenditure (millions of US dollars),,,5882.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +170,Colombia,2018,Tourism expenditure (millions of US dollars),,,6617.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +174,Comoros,1995,Tourist/visitor arrivals (thousands),TF,,23.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +174,Comoros,2005,Tourist/visitor arrivals (thousands),TF,,25.9000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +174,Comoros,2010,Tourist/visitor arrivals (thousands),TF,,15.3000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +174,Comoros,2016,Tourist/visitor arrivals (thousands),TF,,26.8000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +174,Comoros,2017,Tourist/visitor arrivals (thousands),TF,,28.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +174,Comoros,2018,Tourist/visitor arrivals (thousands),TF,,35.9000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +174,Comoros,1995,Tourism expenditure (millions of US dollars),,,22.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +174,Comoros,2005,Tourism expenditure (millions of US dollars),,,24.4000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +174,Comoros,2010,Tourism expenditure (millions of US dollars),,,35.2000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +174,Comoros,2016,Tourism expenditure (millions of US dollars),,,50.5000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +174,Comoros,2017,Tourism expenditure (millions of US dollars),,,60.6000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +174,Comoros,2018,Tourism expenditure (millions of US dollars),,,76.7000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +178,Congo,2005,Tourist/visitor arrivals (thousands),TF,,35.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +178,Congo,2010,Tourist/visitor arrivals (thousands),TF,,194.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +178,Congo,2016,Tourist/visitor arrivals (thousands),TF,,211.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +178,Congo,2017,Tourist/visitor arrivals (thousands),TF,,149.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +178,Congo,2018,Tourist/visitor arrivals (thousands),TF,,156.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +178,Congo,1995,Tourism expenditure (millions of US dollars),,,14.6691,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +178,Congo,2010,Tourism expenditure (millions of US dollars),,,39.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +178,Congo,2016,Tourism expenditure (millions of US dollars),,,42.9000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +184,Cook Islands,1995,Tourist/visitor arrivals (thousands),TF,,48.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +184,Cook Islands,2005,Tourist/visitor arrivals (thousands),TF,,88.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +184,Cook Islands,2010,Tourist/visitor arrivals (thousands),TF,,104.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +184,Cook Islands,2016,Tourist/visitor arrivals (thousands),TF,,146.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +184,Cook Islands,2017,Tourist/visitor arrivals (thousands),TF,,161.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +184,Cook Islands,2018,Tourist/visitor arrivals (thousands),TF,,169.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +184,Cook Islands,1995,Tourism expenditure (millions of US dollars),,,28.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +184,Cook Islands,2005,Tourism expenditure (millions of US dollars),,,91.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +184,Cook Islands,2010,Tourism expenditure (millions of US dollars),,,111.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +184,Cook Islands,2016,Tourism expenditure (millions of US dollars),,,137.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +184,Cook Islands,2017,Tourism expenditure (millions of US dollars),,,153.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +188,Costa Rica,1995,Tourist/visitor arrivals (thousands),TF,,785.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +188,Costa Rica,2005,Tourist/visitor arrivals (thousands),TF,,1679.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +188,Costa Rica,2010,Tourist/visitor arrivals (thousands),TF,,2100.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +188,Costa Rica,2016,Tourist/visitor arrivals (thousands),TF,,2925.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +188,Costa Rica,2017,Tourist/visitor arrivals (thousands),TF,,2960.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +188,Costa Rica,2018,Tourist/visitor arrivals (thousands),TF,,3017.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +188,Costa Rica,1995,Tourism expenditure (millions of US dollars),,,763.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +188,Costa Rica,2005,Tourism expenditure (millions of US dollars),,,2008.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +188,Costa Rica,2010,Tourism expenditure (millions of US dollars),,,2426.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +188,Costa Rica,2016,Tourism expenditure (millions of US dollars),,,3776.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +188,Costa Rica,2017,Tourism expenditure (millions of US dollars),,,3826.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +188,Costa Rica,2018,Tourism expenditure (millions of US dollars),,,3995.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +384,Côte d’Ivoire,2010,Tourist/visitor arrivals (thousands),VF,,252.0000,Arrivals to Félix Houphouët Boigny Airport only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +384,Côte d’Ivoire,2016,Tourist/visitor arrivals (thousands),VF,,1583.0000,Arrivals to Félix Houphouët Boigny Airport only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +384,Côte d’Ivoire,2017,Tourist/visitor arrivals (thousands),VF,,1800.0000,Arrivals to Félix Houphouët Boigny Airport only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +384,Côte d’Ivoire,2018,Tourist/visitor arrivals (thousands),VF,,1965.0000,Arrivals to Félix Houphouët Boigny Airport only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +384,Côte d’Ivoire,1995,Tourism expenditure (millions of US dollars),,,103.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +384,Côte d’Ivoire,2005,Tourism expenditure (millions of US dollars),,,93.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +384,Côte d’Ivoire,2010,Tourism expenditure (millions of US dollars),,,213.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +384,Côte d’Ivoire,2016,Tourism expenditure (millions of US dollars),,,477.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +384,Côte d’Ivoire,2017,Tourism expenditure (millions of US dollars),,,508.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +191,Croatia,1995,Tourist/visitor arrivals (thousands),TCE,,1485.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +191,Croatia,2005,Tourist/visitor arrivals (thousands),TCE,,7743.0000,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +191,Croatia,2010,Tourist/visitor arrivals (thousands),TCE,,9111.0000,Excluding arrivals in ports of nautical tourism.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +191,Croatia,2016,Tourist/visitor arrivals (thousands),TCE,,13809.0000,Excluding arrivals in ports of nautical tourism.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +191,Croatia,2017,Tourist/visitor arrivals (thousands),TCE,,15593.0000,Excluding arrivals in ports of nautical tourism.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +191,Croatia,2018,Tourist/visitor arrivals (thousands),TCE,,16645.0000,Excluding arrivals in ports of nautical tourism.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +191,Croatia,2005,Tourism expenditure (millions of US dollars),,,7625.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +191,Croatia,2010,Tourism expenditure (millions of US dollars),,,8299.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +191,Croatia,2016,Tourism expenditure (millions of US dollars),,,9820.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +191,Croatia,2017,Tourism expenditure (millions of US dollars),,,11128.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +191,Croatia,2018,Tourism expenditure (millions of US dollars),,,12075.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +192,Cuba,1995,Tourist/visitor arrivals (thousands),TF,,742.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +192,Cuba,2005,Tourist/visitor arrivals (thousands),TF,,2261.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +192,Cuba,2010,Tourist/visitor arrivals (thousands),TF,,2507.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +192,Cuba,2016,Tourist/visitor arrivals (thousands),TF,,3975.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +192,Cuba,2017,Tourist/visitor arrivals (thousands),TF,,4594.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +192,Cuba,2018,Tourist/visitor arrivals (thousands),TF,,4684.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +192,Cuba,1995,Tourism expenditure (millions of US dollars),,,1100.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +192,Cuba,2005,Tourism expenditure (millions of US dollars),,,2591.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +192,Cuba,2010,Tourism expenditure (millions of US dollars),,,2396.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +192,Cuba,2016,Tourism expenditure (millions of US dollars),,,3069.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +192,Cuba,2017,Tourism expenditure (millions of US dollars),,,3302.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +192,Cuba,2018,Tourism expenditure (millions of US dollars),,,2969.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +531,Curaçao,1995,Tourist/visitor arrivals (thousands),TF,,224.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +531,Curaçao,2005,Tourist/visitor arrivals (thousands),TF,,222.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +531,Curaçao,2010,Tourist/visitor arrivals (thousands),TF,,342.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +531,Curaçao,2016,Tourist/visitor arrivals (thousands),TF,,441.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +531,Curaçao,2017,Tourist/visitor arrivals (thousands),TF,,399.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +531,Curaçao,2018,Tourist/visitor arrivals (thousands),TF,,432.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +531,Curaçao,1995,Tourism expenditure (millions of US dollars),,,175.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +531,Curaçao,2005,Tourism expenditure (millions of US dollars),,,244.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +531,Curaçao,2010,Tourism expenditure (millions of US dollars),,,438.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +531,Curaçao,2016,Tourism expenditure (millions of US dollars),,,644.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +531,Curaçao,2017,Tourism expenditure (millions of US dollars),,,572.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +531,Curaçao,2018,Tourism expenditure (millions of US dollars),,,605.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +196,Cyprus,1995,Tourist/visitor arrivals (thousands),TF,,2100.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +196,Cyprus,2005,Tourist/visitor arrivals (thousands),TF,,2470.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +196,Cyprus,2010,Tourist/visitor arrivals (thousands),TF,,2173.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +196,Cyprus,2016,Tourist/visitor arrivals (thousands),TF,,3187.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +196,Cyprus,2017,Tourist/visitor arrivals (thousands),TF,,3652.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +196,Cyprus,2018,Tourist/visitor arrivals (thousands),TF,,3939.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +196,Cyprus,1995,Tourism expenditure (millions of US dollars),,,2018.0443,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +196,Cyprus,2005,Tourism expenditure (millions of US dollars),,,2644.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +196,Cyprus,2010,Tourism expenditure (millions of US dollars),,,2137.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +196,Cyprus,2016,Tourism expenditure (millions of US dollars),,,2870.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +196,Cyprus,2017,Tourism expenditure (millions of US dollars),,,3274.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +196,Cyprus,2018,Tourism expenditure (millions of US dollars),,,3449.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +203,Czechia,2005,Tourist/visitor arrivals (thousands),TF,,9404.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +203,Czechia,2010,Tourist/visitor arrivals (thousands),TF,,8629.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +203,Czechia,2016,Tourist/visitor arrivals (thousands),TF,,12808.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +203,Czechia,2017,Tourist/visitor arrivals (thousands),TF,,13665.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +203,Czechia,2005,Tourism expenditure (millions of US dollars),,,5772.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +203,Czechia,2010,Tourism expenditure (millions of US dollars),,,8068.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +203,Czechia,2016,Tourism expenditure (millions of US dollars),,,7041.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +203,Czechia,2017,Tourism expenditure (millions of US dollars),,,7695.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +203,Czechia,2018,Tourism expenditure (millions of US dollars),,,8291.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +180,Dem. Rep. of the Congo,1995,Tourist/visitor arrivals (thousands),TF,,35.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +180,Dem. Rep. of the Congo,2005,Tourist/visitor arrivals (thousands),TF,,61.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +180,Dem. Rep. of the Congo,2010,Tourist/visitor arrivals (thousands),TF,,81.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +180,Dem. Rep. of the Congo,2016,Tourist/visitor arrivals (thousands),TF,,351.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +180,Dem. Rep. of the Congo,2005,Tourism expenditure (millions of US dollars),,,3.2000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +180,Dem. Rep. of the Congo,2010,Tourism expenditure (millions of US dollars),,,10.7000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +180,Dem. Rep. of the Congo,2016,Tourism expenditure (millions of US dollars),,,4.3000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +180,Dem. Rep. of the Congo,2017,Tourism expenditure (millions of US dollars),,,6.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +180,Dem. Rep. of the Congo,2018,Tourism expenditure (millions of US dollars),,,60.5000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +208,Denmark,2005,Tourist/visitor arrivals (thousands),TCE,,9587.0000,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +208,Denmark,2010,Tourist/visitor arrivals (thousands),TCE,,9425.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +208,Denmark,2016,Tourist/visitor arrivals (thousands),TCE,,10781.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +208,Denmark,2017,Tourist/visitor arrivals (thousands),TCE,,12426.0000,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +208,Denmark,2018,Tourist/visitor arrivals (thousands),TCE,,12749.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +208,Denmark,1995,Tourism expenditure (millions of US dollars),,,3691.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +208,Denmark,2005,Tourism expenditure (millions of US dollars),,,5293.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +208,Denmark,2010,Tourism expenditure (millions of US dollars),,,5704.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +208,Denmark,2016,Tourism expenditure (millions of US dollars),,,7494.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +208,Denmark,2017,Tourism expenditure (millions of US dollars),,,8508.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +208,Denmark,2018,Tourism expenditure (millions of US dollars),,,9097.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +262,Djibouti,1995,Tourist/visitor arrivals (thousands),THS,,21.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +262,Djibouti,2005,Tourist/visitor arrivals (thousands),THS,,30.2000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +262,Djibouti,2010,Tourist/visitor arrivals (thousands),THS,,51.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +262,Djibouti,1995,Tourism expenditure (millions of US dollars),,,5.4000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +262,Djibouti,2005,Tourism expenditure (millions of US dollars),,,7.1000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +262,Djibouti,2010,Tourism expenditure (millions of US dollars),,,18.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +262,Djibouti,2016,Tourism expenditure (millions of US dollars),,,33.5000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +262,Djibouti,2017,Tourism expenditure (millions of US dollars),,,36.2000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +262,Djibouti,2018,Tourism expenditure (millions of US dollars),,,57.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +212,Dominica,1995,Tourist/visitor arrivals (thousands),TF,,60.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +212,Dominica,2005,Tourist/visitor arrivals (thousands),TF,,79.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +212,Dominica,2010,Tourist/visitor arrivals (thousands),TF,,77.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +212,Dominica,2016,Tourist/visitor arrivals (thousands),TF,,78.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +212,Dominica,2017,Tourist/visitor arrivals (thousands),TF,,72.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +212,Dominica,2018,Tourist/visitor arrivals (thousands),TF,,63.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +212,Dominica,1995,Tourism expenditure (millions of US dollars),,,42.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +212,Dominica,2005,Tourism expenditure (millions of US dollars),,,57.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +212,Dominica,2010,Tourism expenditure (millions of US dollars),,,94.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +212,Dominica,2016,Tourism expenditure (millions of US dollars),,,198.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +212,Dominica,2017,Tourism expenditure (millions of US dollars),,,161.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +212,Dominica,2018,Tourism expenditure (millions of US dollars),,,111.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +214,Dominican Republic,1995,Tourist/visitor arrivals (thousands),TF,,1776.0000,Including nationals residing abroad.;Arrivals by air.;Excluding the passengers at Herrera airport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +214,Dominican Republic,2005,Tourist/visitor arrivals (thousands),TF,,3691.0000,Including nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +214,Dominican Republic,2010,Tourist/visitor arrivals (thousands),TF,,4125.0000,Including nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +214,Dominican Republic,2016,Tourist/visitor arrivals (thousands),TF,,5959.3000,Including nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +214,Dominican Republic,2017,Tourist/visitor arrivals (thousands),TF,,6188.0000,Including nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +214,Dominican Republic,2018,Tourist/visitor arrivals (thousands),TF,,6569.0000,Including nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +214,Dominican Republic,1995,Tourism expenditure (millions of US dollars),,,1571.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +214,Dominican Republic,2005,Tourism expenditure (millions of US dollars),,,3518.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +214,Dominican Republic,2010,Tourism expenditure (millions of US dollars),,,4162.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +214,Dominican Republic,2016,Tourism expenditure (millions of US dollars),,,6720.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +214,Dominican Republic,2017,Tourism expenditure (millions of US dollars),,,7184.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +214,Dominican Republic,2018,Tourism expenditure (millions of US dollars),,,7561.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +218,Ecuador,1995,Tourist/visitor arrivals (thousands),VF,,440.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +218,Ecuador,2005,Tourist/visitor arrivals (thousands),VF,,860.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +218,Ecuador,2010,Tourist/visitor arrivals (thousands),VF,,1047.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +218,Ecuador,2016,Tourist/visitor arrivals (thousands),VF,,1569.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +218,Ecuador,2017,Tourist/visitor arrivals (thousands),VF,,1806.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +218,Ecuador,2018,Tourist/visitor arrivals (thousands),VF,,2535.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +218,Ecuador,1995,Tourism expenditure (millions of US dollars),,,315.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +218,Ecuador,2005,Tourism expenditure (millions of US dollars),,,488.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +218,Ecuador,2010,Tourism expenditure (millions of US dollars),,,786.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +218,Ecuador,2016,Tourism expenditure (millions of US dollars),,,1450.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +218,Ecuador,2017,Tourism expenditure (millions of US dollars),,,1554.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +218,Ecuador,2018,Tourism expenditure (millions of US dollars),,,1878.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +818,Egypt,1995,Tourist/visitor arrivals (thousands),TF,,2871.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +818,Egypt,2005,Tourist/visitor arrivals (thousands),TF,,8244.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +818,Egypt,2010,Tourist/visitor arrivals (thousands),TF,,14051.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +818,Egypt,2016,Tourist/visitor arrivals (thousands),TF,,5258.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +818,Egypt,2017,Tourist/visitor arrivals (thousands),TF,,8157.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +818,Egypt,2018,Tourist/visitor arrivals (thousands),TF,,11196.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +818,Egypt,1995,Tourism expenditure (millions of US dollars),,,2954.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +818,Egypt,2005,Tourism expenditure (millions of US dollars),,,7206.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +818,Egypt,2010,Tourism expenditure (millions of US dollars),,,13633.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +818,Egypt,2016,Tourism expenditure (millions of US dollars),,,3306.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +818,Egypt,2017,Tourism expenditure (millions of US dollars),,,8636.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +818,Egypt,2018,Tourism expenditure (millions of US dollars),,,12704.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +222,El Salvador,1995,Tourist/visitor arrivals (thousands),TF,,235.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +222,El Salvador,2005,Tourist/visitor arrivals (thousands),TF,,1127.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +222,El Salvador,2010,Tourist/visitor arrivals (thousands),TF,,1150.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +222,El Salvador,2016,Tourist/visitor arrivals (thousands),TF,,1434.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +222,El Salvador,2017,Tourist/visitor arrivals (thousands),TF,,1556.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +222,El Salvador,2018,Tourist/visitor arrivals (thousands),TF,,1677.3000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +222,El Salvador,1995,Tourism expenditure (millions of US dollars),,,152.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +222,El Salvador,2005,Tourism expenditure (millions of US dollars),,,656.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +222,El Salvador,2010,Tourism expenditure (millions of US dollars),,,646.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +222,El Salvador,2016,Tourism expenditure (millions of US dollars),,,1161.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +222,El Salvador,2017,Tourism expenditure (millions of US dollars),,,1227.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +222,El Salvador,2018,Tourism expenditure (millions of US dollars),,,1370.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +226,Equatorial Guinea,1995,Tourism expenditure (millions of US dollars),,,1.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +232,Eritrea,1995,Tourist/visitor arrivals (thousands),VF,,315.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +232,Eritrea,2005,Tourist/visitor arrivals (thousands),VF,,83.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +232,Eritrea,2010,Tourist/visitor arrivals (thousands),VF,,84.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +232,Eritrea,2016,Tourist/visitor arrivals (thousands),VF,,142.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +232,Eritrea,1995,Tourism expenditure (millions of US dollars),,,58.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +232,Eritrea,2005,Tourism expenditure (millions of US dollars),,,66.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +232,Eritrea,2016,Tourism expenditure (millions of US dollars),,,48.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +233,Estonia,1995,Tourist/visitor arrivals (thousands),TF,,530.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +233,Estonia,2005,Tourist/visitor arrivals (thousands),TF,,1917.0000,"Border statistics are not collected any more, surveys used instead.;Calculated on the basis of accommodation statistics and “Foreign Visitor Survey” carried out by the Statistical Office of Estonia.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +233,Estonia,2010,Tourist/visitor arrivals (thousands),TF,,2511.0000,"Border statistics are not collected any more, surveys used instead.;Based on mobile positioning data.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +233,Estonia,2016,Tourist/visitor arrivals (thousands),TF,,3131.0000,"Border statistics are not collected any more, surveys used instead.;Based on mobile positioning data.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +233,Estonia,2017,Tourist/visitor arrivals (thousands),TF,,3244.0000,"Border statistics are not collected any more, surveys used instead.;Based on mobile positioning data.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +233,Estonia,2018,Tourist/visitor arrivals (thousands),TF,,3234.0000,"Border statistics are not collected any more, surveys used instead.;Based on mobile positioning data.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +233,Estonia,1995,Tourism expenditure (millions of US dollars),,,452.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +233,Estonia,2005,Tourism expenditure (millions of US dollars),,,1229.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +233,Estonia,2016,Tourism expenditure (millions of US dollars),,,1916.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +233,Estonia,2017,Tourism expenditure (millions of US dollars),,,2126.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +233,Estonia,2018,Tourism expenditure (millions of US dollars),,,2332.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +748,Eswatini,1995,Tourist/visitor arrivals (thousands),TF,,300.0000,Arrivals in hotels only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +748,Eswatini,2005,Tourist/visitor arrivals (thousands),TF,,837.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +748,Eswatini,2010,Tourist/visitor arrivals (thousands),TF,,868.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +748,Eswatini,2016,Tourist/visitor arrivals (thousands),TF,,947.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +748,Eswatini,2017,Tourist/visitor arrivals (thousands),TF,,921.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +748,Eswatini,2018,Tourist/visitor arrivals (thousands),TF,,782.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +748,Eswatini,1995,Tourism expenditure (millions of US dollars),,,54.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +748,Eswatini,2005,Tourism expenditure (millions of US dollars),,,77.3000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +748,Eswatini,2010,Tourism expenditure (millions of US dollars),,,51.4000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +748,Eswatini,2016,Tourism expenditure (millions of US dollars),,,13.2000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +748,Eswatini,2017,Tourism expenditure (millions of US dollars),,,13.2000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +748,Eswatini,2018,Tourism expenditure (millions of US dollars),,,16.4000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +231,Ethiopia,1995,Tourist/visitor arrivals (thousands),TF,,103.0000,Arrivals to Bole airport only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +231,Ethiopia,2005,Tourist/visitor arrivals (thousands),TF,,227.0000,Including nationals residing abroad.;Arrivals through all ports of entry.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +231,Ethiopia,2010,Tourist/visitor arrivals (thousands),TF,,468.0000,Including nationals residing abroad.;Arrivals through all ports of entry.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +231,Ethiopia,2016,Tourist/visitor arrivals (thousands),TF,,871.0000,Including nationals residing abroad.;Arrivals through all ports of entry.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +231,Ethiopia,2017,Tourist/visitor arrivals (thousands),TF,,933.0000,Including nationals residing abroad.;Arrivals through all ports of entry.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +231,Ethiopia,2018,Tourist/visitor arrivals (thousands),TF,,849.0000,Including nationals residing abroad.;Arrivals through all ports of entry.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +231,Ethiopia,1995,Tourism expenditure (millions of US dollars),,,177.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +231,Ethiopia,2005,Tourism expenditure (millions of US dollars),,,533.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +231,Ethiopia,2010,Tourism expenditure (millions of US dollars),,,1434.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +231,Ethiopia,2016,Tourism expenditure (millions of US dollars),,,2138.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +231,Ethiopia,2017,Tourism expenditure (millions of US dollars),,,2505.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +231,Ethiopia,2018,Tourism expenditure (millions of US dollars),,,3548.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +242,Fiji,1995,Tourist/visitor arrivals (thousands),TF,,318.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +242,Fiji,2005,Tourist/visitor arrivals (thousands),TF,,545.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +242,Fiji,2010,Tourist/visitor arrivals (thousands),TF,,632.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +242,Fiji,2016,Tourist/visitor arrivals (thousands),TF,,792.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +242,Fiji,2017,Tourist/visitor arrivals (thousands),TF,,843.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +242,Fiji,2018,Tourist/visitor arrivals (thousands),TF,,870.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +242,Fiji,1995,Tourism expenditure (millions of US dollars),,,369.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +242,Fiji,2005,Tourism expenditure (millions of US dollars),,,722.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +242,Fiji,2010,Tourism expenditure (millions of US dollars),,,825.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +242,Fiji,2016,Tourism expenditure (millions of US dollars),,,1149.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +242,Fiji,2017,Tourism expenditure (millions of US dollars),,,1243.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +242,Fiji,2018,Tourism expenditure (millions of US dollars),,,1370.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +246,Finland,1995,Tourist/visitor arrivals (thousands),TCE,,1779.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +246,Finland,2005,Tourist/visitor arrivals (thousands),TCE,,2080.0000,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +246,Finland,2010,Tourist/visitor arrivals (thousands),TCE,,2319.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +246,Finland,2016,Tourist/visitor arrivals (thousands),TCE,,2789.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +246,Finland,2017,Tourist/visitor arrivals (thousands),TCE,,3180.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +246,Finland,2018,Tourist/visitor arrivals (thousands),TCE,,3224.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +246,Finland,1995,Tourism expenditure (millions of US dollars),,,2383.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +246,Finland,2005,Tourism expenditure (millions of US dollars),,,3069.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +246,Finland,2010,Tourism expenditure (millions of US dollars),,,4497.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +246,Finland,2016,Tourism expenditure (millions of US dollars),,,4016.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +246,Finland,2017,Tourism expenditure (millions of US dollars),,,5207.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +246,Finland,2018,Tourism expenditure (millions of US dollars),,,5663.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +250,France,1995,Tourist/visitor arrivals (thousands),TF,,60033.0000,Estimated based on surveys at national borders.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +250,France,2005,Tourist/visitor arrivals (thousands),TF,,74988.0000,Arrivals of non-resident visitors.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +250,France,2010,Tourist/visitor arrivals (thousands),TF,,76647.0000,Arrivals of non-resident visitors.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +250,France,2016,Tourist/visitor arrivals (thousands),TF,,82682.0000,Arrivals of non-resident visitors.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +250,France,2017,Tourist/visitor arrivals (thousands),TF,,86758.0000,Arrivals of non-resident visitors.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +250,France,2018,Tourist/visitor arrivals (thousands),TF,,89322.0000,Estimate.;Arrivals of non-resident visitors.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +250,France,1995,Tourism expenditure (millions of US dollars),,,31295.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +250,France,2005,Tourism expenditure (millions of US dollars),,,52126.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +250,France,2010,Tourism expenditure (millions of US dollars),,,56178.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +250,France,2016,Tourism expenditure (millions of US dollars),,,63557.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +250,France,2017,Tourism expenditure (millions of US dollars),,,67936.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +250,France,2018,Tourism expenditure (millions of US dollars),,,73125.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +254,French Guiana,2005,Tourist/visitor arrivals (thousands),TF,,95.0000,Survey at Cayenne-Rochambeau airport on departure.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +254,French Guiana,2016,Tourist/visitor arrivals (thousands),TF,,96.0000,Survey at Cayenne-Rochambeau airport on departure.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +254,French Guiana,2017,Tourist/visitor arrivals (thousands),TF,,111.0000,Survey at Cayenne-Rochambeau airport on departure.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +254,French Guiana,2005,Tourism expenditure (millions of US dollars),,,44.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +258,French Polynesia,1995,Tourist/visitor arrivals (thousands),TF,,172.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +258,French Polynesia,2005,Tourist/visitor arrivals (thousands),TF,,208.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +258,French Polynesia,2010,Tourist/visitor arrivals (thousands),TF,,154.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +258,French Polynesia,2016,Tourist/visitor arrivals (thousands),TF,,192.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +258,French Polynesia,2017,Tourist/visitor arrivals (thousands),TF,,199.0000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +258,French Polynesia,2018,Tourist/visitor arrivals (thousands),TF,,216.3000,Excluding nationals residing abroad.;Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +258,French Polynesia,1995,Tourism expenditure (millions of US dollars),,,326.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +258,French Polynesia,2005,Tourism expenditure (millions of US dollars),,,759.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +258,French Polynesia,2010,Tourism expenditure (millions of US dollars),,,630.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +258,French Polynesia,2016,Tourism expenditure (millions of US dollars),,,782.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +266,Gabon,1995,Tourist/visitor arrivals (thousands),TF,,125.0000,Arrivals of non-resident tourists at Libreville airport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +266,Gabon,2005,Tourist/visitor arrivals (thousands),TF,,269.0000,Arrivals of non-resident tourists at Libreville airport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +266,Gabon,1995,Tourism expenditure (millions of US dollars),,,94.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +266,Gabon,2005,Tourism expenditure (millions of US dollars),,,13.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +266,Gabon,2010,Tourism expenditure (millions of US dollars),,,89.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +266,Gabon,2016,Tourism expenditure (millions of US dollars),,,28.7000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +270,Gambia,1995,Tourist/visitor arrivals (thousands),TF,,45.0000,Including nationals residing abroad.;Arrivals by air only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +270,Gambia,2005,Tourist/visitor arrivals (thousands),TF,,108.0000,Including nationals residing abroad.;Arrivals by air only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +270,Gambia,2010,Tourist/visitor arrivals (thousands),TF,,91.0000,Including nationals residing abroad.;Arrivals by air only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +270,Gambia,2016,Tourist/visitor arrivals (thousands),TF,,450.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +270,Gambia,2017,Tourist/visitor arrivals (thousands),TF,,522.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +270,Gambia,2018,Tourist/visitor arrivals (thousands),TF,,552.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +270,Gambia,2005,Tourism expenditure (millions of US dollars),,,59.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +270,Gambia,2010,Tourism expenditure (millions of US dollars),,,80.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +270,Gambia,2016,Tourism expenditure (millions of US dollars),,,120.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +270,Gambia,2017,Tourism expenditure (millions of US dollars),,,116.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +270,Gambia,2018,Tourism expenditure (millions of US dollars),,,168.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +268,Georgia,2010,Tourist/visitor arrivals (thousands),TF,,1067.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +268,Georgia,2016,Tourist/visitor arrivals (thousands),TF,,3297.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +268,Georgia,2017,Tourist/visitor arrivals (thousands),TF,,4069.4000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +268,Georgia,2018,Tourist/visitor arrivals (thousands),TF,,4757.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +268,Georgia,2005,Tourism expenditure (millions of US dollars),,,287.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +268,Georgia,2010,Tourism expenditure (millions of US dollars),,,737.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +268,Georgia,2016,Tourism expenditure (millions of US dollars),,,2315.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +268,Georgia,2017,Tourism expenditure (millions of US dollars),,,2971.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +268,Georgia,2018,Tourism expenditure (millions of US dollars),,,3518.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +276,Germany,1995,Tourist/visitor arrivals (thousands),TCE,,14847.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +276,Germany,2005,Tourist/visitor arrivals (thousands),TCE,,21500.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +276,Germany,2010,Tourist/visitor arrivals (thousands),TCE,,26875.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +276,Germany,2016,Tourist/visitor arrivals (thousands),TCE,,35555.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +276,Germany,2017,Tourist/visitor arrivals (thousands),TCE,,37452.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +276,Germany,2018,Tourist/visitor arrivals (thousands),TCE,,38881.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +276,Germany,1995,Tourism expenditure (millions of US dollars),,,24053.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +276,Germany,2005,Tourism expenditure (millions of US dollars),,,40518.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +276,Germany,2010,Tourism expenditure (millions of US dollars),,,49116.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +276,Germany,2016,Tourism expenditure (millions of US dollars),,,52229.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +276,Germany,2017,Tourism expenditure (millions of US dollars),,,56330.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +276,Germany,2018,Tourism expenditure (millions of US dollars),,,60260.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +288,Ghana,1995,Tourist/visitor arrivals (thousands),TF,,286.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +288,Ghana,2005,Tourist/visitor arrivals (thousands),TF,,429.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +288,Ghana,2010,Tourist/visitor arrivals (thousands),TF,,931.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +288,Ghana,1995,Tourism expenditure (millions of US dollars),,,30.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +288,Ghana,2005,Tourism expenditure (millions of US dollars),,,867.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +288,Ghana,2010,Tourism expenditure (millions of US dollars),,,706.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +288,Ghana,2016,Tourism expenditure (millions of US dollars),,,952.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +288,Ghana,2017,Tourism expenditure (millions of US dollars),,,919.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +288,Ghana,2018,Tourism expenditure (millions of US dollars),,,996.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +300,Greece,1995,Tourist/visitor arrivals (thousands),TF,,10130.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +300,Greece,2005,Tourist/visitor arrivals (thousands),TF,,14765.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +300,Greece,2010,Tourist/visitor arrivals (thousands),TF,,15007.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +300,Greece,2016,Tourist/visitor arrivals (thousands),TF,,24799.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +300,Greece,2017,Tourist/visitor arrivals (thousands),TF,,27194.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +300,Greece,2018,Tourist/visitor arrivals (thousands),TF,,30123.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +300,Greece,1995,Tourism expenditure (millions of US dollars),,,4182.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +300,Greece,2005,Tourism expenditure (millions of US dollars),,,13455.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +300,Greece,2010,Tourism expenditure (millions of US dollars),,,13857.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +300,Greece,2016,Tourism expenditure (millions of US dollars),,,16811.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +300,Greece,2017,Tourism expenditure (millions of US dollars),,,19139.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +300,Greece,2018,Tourism expenditure (millions of US dollars),,,21594.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +308,Grenada,1995,Tourist/visitor arrivals (thousands),TF,,108.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +308,Grenada,2005,Tourist/visitor arrivals (thousands),TF,,99.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +308,Grenada,2010,Tourist/visitor arrivals (thousands),TF,,110.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +308,Grenada,2016,Tourist/visitor arrivals (thousands),TF,,156.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +308,Grenada,2017,Tourist/visitor arrivals (thousands),TF,,168.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +308,Grenada,2018,Tourist/visitor arrivals (thousands),TF,,185.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +308,Grenada,1995,Tourism expenditure (millions of US dollars),,,76.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +308,Grenada,2005,Tourism expenditure (millions of US dollars),,,71.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +308,Grenada,2010,Tourism expenditure (millions of US dollars),,,112.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +308,Grenada,2016,Tourism expenditure (millions of US dollars),,,437.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +308,Grenada,2017,Tourism expenditure (millions of US dollars),,,482.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +308,Grenada,2018,Tourism expenditure (millions of US dollars),,,548.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +312,Guadeloupe,1995,Tourist/visitor arrivals (thousands),TF,,640.0000,"Arrivals by air.;Excluding the north islands, Saint Barthélemy and Saint Martin (French part).;Non-resident tourists staying in all types of accommodation establishments.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +312,Guadeloupe,2005,Tourist/visitor arrivals (thousands),TF,,372.0000,"Arrivals by air.;Excluding the north islands, Saint Barthélemy and Saint Martin (French part).","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +312,Guadeloupe,2010,Tourist/visitor arrivals (thousands),TF,,392.0000,"Arrivals by air.;Excluding the north islands, Saint Barthélemy and Saint Martin (French part).","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +312,Guadeloupe,2016,Tourist/visitor arrivals (thousands),TF,,581.0000,"Arrivals by air.;Excluding the north islands, Saint Barthélemy and Saint Martin (French part).","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +312,Guadeloupe,2017,Tourist/visitor arrivals (thousands),TF,,650.0000,"Arrivals by air.;Excluding the north islands, Saint Barthélemy and Saint Martin (French part).","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +312,Guadeloupe,2018,Tourist/visitor arrivals (thousands),TF,,735.0000,"Arrivals by air.;Excluding the north islands, Saint Barthélemy and Saint Martin (French part).","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +312,Guadeloupe,1995,Tourism expenditure (millions of US dollars),,,458.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +312,Guadeloupe,2005,Tourism expenditure (millions of US dollars),,,306.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +312,Guadeloupe,2010,Tourism expenditure (millions of US dollars),,,510.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +312,Guadeloupe,2018,Tourism expenditure (millions of US dollars),,,860.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +316,Guam,1995,Tourist/visitor arrivals (thousands),TF,,1362.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +316,Guam,2005,Tourist/visitor arrivals (thousands),TF,,1228.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +316,Guam,2010,Tourist/visitor arrivals (thousands),TF,,1197.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +316,Guam,2016,Tourist/visitor arrivals (thousands),TF,,1536.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +316,Guam,2017,Tourist/visitor arrivals (thousands),TF,,1545.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +316,Guam,2018,Tourist/visitor arrivals (thousands),TF,,1549.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +320,Guatemala,2010,Tourist/visitor arrivals (thousands),TF,,1119.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +320,Guatemala,2016,Tourist/visitor arrivals (thousands),TF,,1585.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +320,Guatemala,2017,Tourist/visitor arrivals (thousands),TF,,1660.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +320,Guatemala,2018,Tourist/visitor arrivals (thousands),TF,,1781.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +320,Guatemala,1995,Tourism expenditure (millions of US dollars),,,213.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +320,Guatemala,2005,Tourism expenditure (millions of US dollars),,,791.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +320,Guatemala,2010,Tourism expenditure (millions of US dollars),,,1378.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +320,Guatemala,2016,Tourism expenditure (millions of US dollars),,,1550.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +320,Guatemala,2017,Tourism expenditure (millions of US dollars),,,1566.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +320,Guatemala,2018,Tourism expenditure (millions of US dollars),,,1549.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +324,Guinea,2005,Tourist/visitor arrivals (thousands),TF,,45.0000,Arrivals by air at Conakry airport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +324,Guinea,2010,Tourist/visitor arrivals (thousands),TF,,12.4000,Arrivals by air at Conakry airport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +324,Guinea,2016,Tourist/visitor arrivals (thousands),TF,,63.0000,Arrivals by air at Conakry airport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +324,Guinea,2017,Tourist/visitor arrivals (thousands),TF,,99.0000,Arrivals by air at Conakry airport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +324,Guinea,1995,Tourism expenditure (millions of US dollars),,,0.9110,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +324,Guinea,2010,Tourism expenditure (millions of US dollars),,,2.0400,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +324,Guinea,2016,Tourism expenditure (millions of US dollars),,,16.6000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +324,Guinea,2017,Tourism expenditure (millions of US dollars),,,16.6000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +324,Guinea,2018,Tourism expenditure (millions of US dollars),,,7.7000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +624,Guinea-Bissau,2005,Tourist/visitor arrivals (thousands),TF,,5.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +624,Guinea-Bissau,2010,Tourist/visitor arrivals (thousands),TF,,22.3000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +624,Guinea-Bissau,2016,Tourist/visitor arrivals (thousands),TF,,45.2000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +624,Guinea-Bissau,2005,Tourism expenditure (millions of US dollars),,,1.6000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +624,Guinea-Bissau,2010,Tourism expenditure (millions of US dollars),,,13.3000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +624,Guinea-Bissau,2016,Tourism expenditure (millions of US dollars),,,11.5000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +624,Guinea-Bissau,2017,Tourism expenditure (millions of US dollars),,,16.3000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +624,Guinea-Bissau,2018,Tourism expenditure (millions of US dollars),,,19.8000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +328,Guyana,1995,Tourist/visitor arrivals (thousands),TF,,106.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +328,Guyana,2005,Tourist/visitor arrivals (thousands),TF,,117.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +328,Guyana,2010,Tourist/visitor arrivals (thousands),TF,,152.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +328,Guyana,2016,Tourist/visitor arrivals (thousands),TF,,235.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +328,Guyana,2017,Tourist/visitor arrivals (thousands),TF,,247.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +328,Guyana,2018,Tourist/visitor arrivals (thousands),TF,,287.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +328,Guyana,1995,Tourism expenditure (millions of US dollars),,,33.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +328,Guyana,2005,Tourism expenditure (millions of US dollars),,,35.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +328,Guyana,2010,Tourism expenditure (millions of US dollars),,,80.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +328,Guyana,2016,Tourism expenditure (millions of US dollars),,,104.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +328,Guyana,2017,Tourism expenditure (millions of US dollars),,,95.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +328,Guyana,2018,Tourism expenditure (millions of US dollars),,,28.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +332,Haiti,1995,Tourist/visitor arrivals (thousands),TF,,145.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +332,Haiti,2005,Tourist/visitor arrivals (thousands),TF,,112.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +332,Haiti,2010,Tourist/visitor arrivals (thousands),TF,,255.0000,Arrivals by air.;Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +332,Haiti,2016,Tourist/visitor arrivals (thousands),TF,,445.0000,Arrivals by air.;Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +332,Haiti,2017,Tourist/visitor arrivals (thousands),TF,,467.0000,Arrivals by air.;Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +332,Haiti,2018,Tourist/visitor arrivals (thousands),TF,,447.0000,Arrivals by air.;Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +332,Haiti,1995,Tourism expenditure (millions of US dollars),,,90.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +332,Haiti,2005,Tourism expenditure (millions of US dollars),,,80.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +332,Haiti,2010,Tourism expenditure (millions of US dollars),,,383.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +332,Haiti,2016,Tourism expenditure (millions of US dollars),,,511.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +332,Haiti,2017,Tourism expenditure (millions of US dollars),,,460.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +332,Haiti,2018,Tourism expenditure (millions of US dollars),,,620.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +340,Honduras,1995,Tourist/visitor arrivals (thousands),TF,,271.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +340,Honduras,2005,Tourist/visitor arrivals (thousands),TF,,673.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +340,Honduras,2010,Tourist/visitor arrivals (thousands),TF,,863.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +340,Honduras,2016,Tourist/visitor arrivals (thousands),TF,,838.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +340,Honduras,2017,Tourist/visitor arrivals (thousands),TF,,851.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +340,Honduras,1995,Tourism expenditure (millions of US dollars),,,85.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +340,Honduras,2005,Tourism expenditure (millions of US dollars),,,465.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +340,Honduras,2010,Tourism expenditure (millions of US dollars),,,626.7000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +340,Honduras,2016,Tourism expenditure (millions of US dollars),,,700.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +340,Honduras,2017,Tourism expenditure (millions of US dollars),,,722.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +340,Honduras,2018,Tourism expenditure (millions of US dollars),,,745.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +348,Hungary,2005,Tourist/visitor arrivals (thousands),TF,,9979.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +348,Hungary,2010,Tourist/visitor arrivals (thousands),TF,,9510.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +348,Hungary,2016,Tourist/visitor arrivals (thousands),TF,,15255.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +348,Hungary,2017,Tourist/visitor arrivals (thousands),TF,,15785.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +348,Hungary,2018,Tourist/visitor arrivals (thousands),TF,,17552.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +348,Hungary,1995,Tourism expenditure (millions of US dollars),,,2938.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +348,Hungary,2005,Tourism expenditure (millions of US dollars),,,4761.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +348,Hungary,2010,Tourism expenditure (millions of US dollars),,,6595.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +348,Hungary,2016,Tourism expenditure (millions of US dollars),,,7481.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +348,Hungary,2017,Tourism expenditure (millions of US dollars),,,8448.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +348,Hungary,2018,Tourism expenditure (millions of US dollars),,,9595.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +352,Iceland,1995,Tourist/visitor arrivals (thousands),TF,,190.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +352,Iceland,2005,Tourist/visitor arrivals (thousands),TF,,374.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +352,Iceland,2010,Tourist/visitor arrivals (thousands),TF,,489.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +352,Iceland,2016,Tourist/visitor arrivals (thousands),TF,,1792.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +352,Iceland,2017,Tourist/visitor arrivals (thousands),TF,,2225.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +352,Iceland,2018,Tourist/visitor arrivals (thousands),TF,,2343.8000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +352,Iceland,1995,Tourism expenditure (millions of US dollars),,,186.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +352,Iceland,2005,Tourism expenditure (millions of US dollars),,,413.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +352,Iceland,2010,Tourism expenditure (millions of US dollars),,,562.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +352,Iceland,2016,Tourism expenditure (millions of US dollars),,,2411.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +352,Iceland,2017,Tourism expenditure (millions of US dollars),,,3024.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +352,Iceland,2018,Tourism expenditure (millions of US dollars),,,3128.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +356,India,1995,Tourist/visitor arrivals (thousands),TF,,2124.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +356,India,2005,Tourist/visitor arrivals (thousands),TF,,3919.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +356,India,2010,Tourist/visitor arrivals (thousands),TF,,5776.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +356,India,2016,Tourist/visitor arrivals (thousands),TF,,14570.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +356,India,2017,Tourist/visitor arrivals (thousands),TF,,15543.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +356,India,2018,Tourist/visitor arrivals (thousands),TF,,17423.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +356,India,2005,Tourism expenditure (millions of US dollars),,,7659.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +356,India,2016,Tourism expenditure (millions of US dollars),,,23111.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +356,India,2017,Tourism expenditure (millions of US dollars),,,27878.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +356,India,2018,Tourism expenditure (millions of US dollars),,,29143.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +360,Indonesia,1995,Tourist/visitor arrivals (thousands),VF,,4324.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +360,Indonesia,2005,Tourist/visitor arrivals (thousands),VF,,5002.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +360,Indonesia,2010,Tourist/visitor arrivals (thousands),VF,,7003.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +360,Indonesia,2016,Tourist/visitor arrivals (thousands),VF,,11519.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +360,Indonesia,2017,Tourist/visitor arrivals (thousands),VF,,14040.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +360,Indonesia,2018,Tourist/visitor arrivals (thousands),VF,,15810.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +360,Indonesia,2005,Tourism expenditure (millions of US dollars),,,5094.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +360,Indonesia,2010,Tourism expenditure (millions of US dollars),,,7618.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +360,Indonesia,2016,Tourism expenditure (millions of US dollars),,,12566.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +360,Indonesia,2017,Tourism expenditure (millions of US dollars),,,14691.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +360,Indonesia,2018,Tourism expenditure (millions of US dollars),,,15600.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +364,Iran (Islamic Republic of),1995,Tourist/visitor arrivals (thousands),VF,,568.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +364,Iran (Islamic Republic of),2010,Tourist/visitor arrivals (thousands),VF,,2938.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +364,Iran (Islamic Republic of),2016,Tourist/visitor arrivals (thousands),VF,,4942.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +364,Iran (Islamic Republic of),2017,Tourist/visitor arrivals (thousands),VF,,4867.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +364,Iran (Islamic Republic of),2018,Tourist/visitor arrivals (thousands),VF,,7295.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +364,Iran (Islamic Republic of),1995,Tourism expenditure (millions of US dollars),,,205.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +364,Iran (Islamic Republic of),2005,Tourism expenditure (millions of US dollars),,,1025.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +364,Iran (Islamic Republic of),2010,Tourism expenditure (millions of US dollars),,,2631.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +364,Iran (Islamic Republic of),2016,Tourism expenditure (millions of US dollars),,,3914.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +364,Iran (Islamic Republic of),2017,Tourism expenditure (millions of US dollars),,,4632.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +368,Iraq,1995,Tourist/visitor arrivals (thousands),VF,,61.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +368,Iraq,2010,Tourist/visitor arrivals (thousands),VF,,1518.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +368,Iraq,2005,Tourism expenditure (millions of US dollars),,,186.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +368,Iraq,2010,Tourism expenditure (millions of US dollars),,,1736.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +368,Iraq,2016,Tourism expenditure (millions of US dollars),,,3120.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +368,Iraq,2017,Tourism expenditure (millions of US dollars),,,2959.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +368,Iraq,2018,Tourism expenditure (millions of US dollars),,,1986.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +372,Ireland,1995,Tourist/visitor arrivals (thousands),TF,,4818.0000,Including tourists from Northern Ireland.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +372,Ireland,2005,Tourist/visitor arrivals (thousands),TF,,7333.0000,Including tourists from Northern Ireland.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +372,Ireland,2010,Tourist/visitor arrivals (thousands),TF,,7134.0000,Break in the time series.;Including tourists from Northern Ireland.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +372,Ireland,2016,Tourist/visitor arrivals (thousands),TF,,10100.0000,Including tourists from Northern Ireland.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +372,Ireland,2017,Tourist/visitor arrivals (thousands),TF,,10338.0000,Including tourists from Northern Ireland.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +372,Ireland,2018,Tourist/visitor arrivals (thousands),TF,,10926.0000,Including tourists from Northern Ireland.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +372,Ireland,1995,Tourism expenditure (millions of US dollars),,,2697.7927,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +372,Ireland,2005,Tourism expenditure (millions of US dollars),,,6779.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +372,Ireland,2010,Tourism expenditure (millions of US dollars),,,8185.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +372,Ireland,2016,Tourism expenditure (millions of US dollars),,,11429.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +372,Ireland,2017,Tourism expenditure (millions of US dollars),,,14294.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +372,Ireland,2018,Tourism expenditure (millions of US dollars),,,14658.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +376,Israel,1995,Tourist/visitor arrivals (thousands),TF,,2215.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +376,Israel,2005,Tourist/visitor arrivals (thousands),TF,,1903.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +376,Israel,2010,Tourist/visitor arrivals (thousands),TF,,2803.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +376,Israel,2016,Tourist/visitor arrivals (thousands),TF,,2900.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +376,Israel,2017,Tourist/visitor arrivals (thousands),TF,,3613.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +376,Israel,2018,Tourist/visitor arrivals (thousands),TF,,4121.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +376,Israel,1995,Tourism expenditure (millions of US dollars),,,3491.0000,Including the expenditures of foreign workers in Israel.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +376,Israel,2005,Tourism expenditure (millions of US dollars),,,2750.0000,Including the expenditures of foreign workers in Israel.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +376,Israel,2010,Tourism expenditure (millions of US dollars),,,5621.0000,Including the expenditures of foreign workers in Israel.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +376,Israel,2016,Tourism expenditure (millions of US dollars),,,6587.0000,Including the expenditures of foreign workers in Israel.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +376,Israel,2017,Tourism expenditure (millions of US dollars),,,7578.0000,Including the expenditures of foreign workers in Israel.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +376,Israel,2018,Tourism expenditure (millions of US dollars),,,8073.0000,Including the expenditures of foreign workers in Israel.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +380,Italy,1995,Tourist/visitor arrivals (thousands),TF,,31052.0000,Excluding seasonal and border workers.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +380,Italy,2005,Tourist/visitor arrivals (thousands),TF,,36513.0000,Excluding seasonal and border workers.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +380,Italy,2010,Tourist/visitor arrivals (thousands),TF,,43626.0000,Excluding seasonal and border workers.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +380,Italy,2016,Tourist/visitor arrivals (thousands),TF,,52372.0000,Excluding seasonal and border workers.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +380,Italy,2017,Tourist/visitor arrivals (thousands),TF,,58253.0000,Excluding seasonal and border workers.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +380,Italy,2018,Tourist/visitor arrivals (thousands),TF,,61567.2000,Excluding seasonal and border workers.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +380,Italy,1995,Tourism expenditure (millions of US dollars),,,30411.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +380,Italy,2005,Tourism expenditure (millions of US dollars),,,38364.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +380,Italy,2016,Tourism expenditure (millions of US dollars),,,42423.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +380,Italy,2017,Tourism expenditure (millions of US dollars),,,46719.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +380,Italy,2018,Tourism expenditure (millions of US dollars),,,51602.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +388,Jamaica,1995,Tourist/visitor arrivals (thousands),TF,,1147.0000,Including nationals residing abroad; E/D cards.;Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +388,Jamaica,2005,Tourist/visitor arrivals (thousands),TF,,1479.0000,Including nationals residing abroad; E/D cards.;Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +388,Jamaica,2010,Tourist/visitor arrivals (thousands),TF,,1922.0000,Including nationals residing abroad; E/D cards.;Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +388,Jamaica,2016,Tourist/visitor arrivals (thousands),TF,,2182.0000,Including nationals residing abroad; E/D cards.;Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +388,Jamaica,2017,Tourist/visitor arrivals (thousands),TF,,2353.0000,Including nationals residing abroad; E/D cards.;Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +388,Jamaica,2018,Tourist/visitor arrivals (thousands),TF,,2473.0000,Including nationals residing abroad; E/D cards.;Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +388,Jamaica,1995,Tourism expenditure (millions of US dollars),,,1069.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +388,Jamaica,2005,Tourism expenditure (millions of US dollars),,,1545.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +388,Jamaica,2010,Tourism expenditure (millions of US dollars),,,2001.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +388,Jamaica,2016,Tourism expenditure (millions of US dollars),,,2539.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +388,Jamaica,2017,Tourism expenditure (millions of US dollars),,,2809.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +388,Jamaica,2018,Tourism expenditure (millions of US dollars),,,3099.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +392,Japan,1995,Tourist/visitor arrivals (thousands),VF,,3345.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +392,Japan,2005,Tourist/visitor arrivals (thousands),VF,,6728.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +392,Japan,2010,Tourist/visitor arrivals (thousands),VF,,8611.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +392,Japan,2016,Tourist/visitor arrivals (thousands),VF,,24040.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +392,Japan,2017,Tourist/visitor arrivals (thousands),VF,,28691.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +392,Japan,2018,Tourist/visitor arrivals (thousands),VF,,31192.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +392,Japan,1995,Tourism expenditure (millions of US dollars),,,4894.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +392,Japan,2005,Tourism expenditure (millions of US dollars),,,15554.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +392,Japan,2010,Tourism expenditure (millions of US dollars),,,15356.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +392,Japan,2016,Tourism expenditure (millions of US dollars),,,33456.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +392,Japan,2017,Tourism expenditure (millions of US dollars),,,36978.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +392,Japan,2018,Tourism expenditure (millions of US dollars),,,45276.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +400,Jordan,1995,Tourist/visitor arrivals (thousands),TF,,1075.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +400,Jordan,2005,Tourist/visitor arrivals (thousands),TF,,2987.0000,Break in the time series.;Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +400,Jordan,2010,Tourist/visitor arrivals (thousands),TF,,4207.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +400,Jordan,2016,Tourist/visitor arrivals (thousands),TF,,3567.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +400,Jordan,2017,Tourist/visitor arrivals (thousands),TF,,3843.5000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +400,Jordan,2018,Tourist/visitor arrivals (thousands),TF,,4150.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +400,Jordan,1995,Tourism expenditure (millions of US dollars),,,973.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +400,Jordan,2005,Tourism expenditure (millions of US dollars),,,1759.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +400,Jordan,2010,Tourism expenditure (millions of US dollars),,,4390.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +400,Jordan,2016,Tourism expenditure (millions of US dollars),,,4943.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +400,Jordan,2017,Tourism expenditure (millions of US dollars),,,5549.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +400,Jordan,2018,Tourism expenditure (millions of US dollars),,,6221.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +398,Kazakhstan,2005,Tourist/visitor arrivals (thousands),TF,,3143.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +398,Kazakhstan,2010,Tourist/visitor arrivals (thousands),TF,,2991.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +398,Kazakhstan,1995,Tourism expenditure (millions of US dollars),,,155.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +398,Kazakhstan,2005,Tourism expenditure (millions of US dollars),,,801.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +398,Kazakhstan,2010,Tourism expenditure (millions of US dollars),,,1236.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +398,Kazakhstan,2016,Tourism expenditure (millions of US dollars),,,2038.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +398,Kazakhstan,2017,Tourism expenditure (millions of US dollars),,,2356.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +398,Kazakhstan,2018,Tourism expenditure (millions of US dollars),,,2651.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +404,Kenya,1995,Tourist/visitor arrivals (thousands),TF,,918.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +404,Kenya,2005,Tourist/visitor arrivals (thousands),TF,,1399.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +404,Kenya,2010,Tourist/visitor arrivals (thousands),TF,,1470.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +404,Kenya,2016,Tourist/visitor arrivals (thousands),TF,,1268.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +404,Kenya,2017,Tourist/visitor arrivals (thousands),TF,,1364.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +404,Kenya,1995,Tourism expenditure (millions of US dollars),,,785.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +404,Kenya,2005,Tourism expenditure (millions of US dollars),,,969.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +404,Kenya,2010,Tourism expenditure (millions of US dollars),,,1620.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +404,Kenya,2016,Tourism expenditure (millions of US dollars),,,1471.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +404,Kenya,2017,Tourism expenditure (millions of US dollars),,,1564.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +296,Kiribati,1995,Tourist/visitor arrivals (thousands),TF,,3.9000,Air arrivals. Tarawa and Christmas Island.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +296,Kiribati,2005,Tourist/visitor arrivals (thousands),TF,,4.1000,Air arrivals. Tarawa and Christmas Island.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +296,Kiribati,2010,Tourist/visitor arrivals (thousands),TF,,4.7000,Air arrivals. Tarawa and Christmas Island.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +296,Kiribati,2016,Tourist/visitor arrivals (thousands),TF,,5.7000,Air arrivals. Tarawa and Christmas Island.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +296,Kiribati,2017,Tourist/visitor arrivals (thousands),TF,,5.8000,Air arrivals. Tarawa and Christmas Island.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +296,Kiribati,2018,Tourist/visitor arrivals (thousands),TF,,7.1000,Air arrivals. Tarawa and Christmas Island.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +296,Kiribati,2010,Tourism expenditure (millions of US dollars),,,4.3000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +296,Kiribati,2016,Tourism expenditure (millions of US dollars),,,2.8000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +296,Kiribati,2017,Tourism expenditure (millions of US dollars),,,4.1000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +414,Kuwait,1995,Tourist/visitor arrivals (thousands),VF,,1443.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +414,Kuwait,2005,Tourist/visitor arrivals (thousands),VF,,3474.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +414,Kuwait,2010,Tourist/visitor arrivals (thousands),VF,,5208.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +414,Kuwait,2016,Tourist/visitor arrivals (thousands),VF,,7055.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +414,Kuwait,2017,Tourist/visitor arrivals (thousands),VF,,7407.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +414,Kuwait,2018,Tourist/visitor arrivals (thousands),VF,,8508.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +414,Kuwait,1995,Tourism expenditure (millions of US dollars),,,307.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +414,Kuwait,2005,Tourism expenditure (millions of US dollars),,,413.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +414,Kuwait,2010,Tourism expenditure (millions of US dollars),,,574.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +414,Kuwait,2016,Tourism expenditure (millions of US dollars),,,831.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +414,Kuwait,2017,Tourism expenditure (millions of US dollars),,,643.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +414,Kuwait,2018,Tourism expenditure (millions of US dollars),,,919.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +417,Kyrgyzstan,2005,Tourist/visitor arrivals (thousands),VF,,319.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +417,Kyrgyzstan,2010,Tourist/visitor arrivals (thousands),VF,,1224.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +417,Kyrgyzstan,2016,Tourist/visitor arrivals (thousands),VF,,3853.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +417,Kyrgyzstan,2017,Tourist/visitor arrivals (thousands),VF,,4568.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +417,Kyrgyzstan,2018,Tourist/visitor arrivals (thousands),VF,,6947.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +417,Kyrgyzstan,2005,Tourism expenditure (millions of US dollars),,,94.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +417,Kyrgyzstan,2010,Tourism expenditure (millions of US dollars),,,212.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +417,Kyrgyzstan,2016,Tourism expenditure (millions of US dollars),,,477.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +417,Kyrgyzstan,2017,Tourism expenditure (millions of US dollars),,,480.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +417,Kyrgyzstan,2018,Tourism expenditure (millions of US dollars),,,487.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +418,Lao People's Dem. Rep.,1995,Tourist/visitor arrivals (thousands),TF,,60.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +418,Lao People's Dem. Rep.,2005,Tourist/visitor arrivals (thousands),TF,,672.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +418,Lao People's Dem. Rep.,2010,Tourist/visitor arrivals (thousands),TF,,1670.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +418,Lao People's Dem. Rep.,2016,Tourist/visitor arrivals (thousands),TF,,3315.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +418,Lao People's Dem. Rep.,2017,Tourist/visitor arrivals (thousands),TF,,3257.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +418,Lao People's Dem. Rep.,2018,Tourist/visitor arrivals (thousands),TF,,3770.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +418,Lao People's Dem. Rep.,1995,Tourism expenditure (millions of US dollars),,,52.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +418,Lao People's Dem. Rep.,2005,Tourism expenditure (millions of US dollars),,,143.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +418,Lao People's Dem. Rep.,2010,Tourism expenditure (millions of US dollars),,,385.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +418,Lao People's Dem. Rep.,2016,Tourism expenditure (millions of US dollars),,,717.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +418,Lao People's Dem. Rep.,2017,Tourism expenditure (millions of US dollars),,,655.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +418,Lao People's Dem. Rep.,2018,Tourism expenditure (millions of US dollars),,,757.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +428,Latvia,1995,Tourist/visitor arrivals (thousands),TF,,539.0000,Non-resident departures. Survey of persons crossing the state border.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +428,Latvia,2005,Tourist/visitor arrivals (thousands),TF,,1116.0000,Non-resident departures. Survey of persons crossing the state border.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +428,Latvia,2010,Tourist/visitor arrivals (thousands),TF,,1373.0000,Non-resident departures. Survey of persons crossing the state border.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +428,Latvia,2016,Tourist/visitor arrivals (thousands),TF,,1793.0000,Non-resident departures. Survey of persons crossing the state border.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +428,Latvia,2017,Tourist/visitor arrivals (thousands),TF,,1949.0000,Non-resident departures. Survey of persons crossing the state border.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +428,Latvia,2018,Tourist/visitor arrivals (thousands),TF,,1946.0000,Non-resident departures. Survey of persons crossing the state border.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +428,Latvia,1995,Tourism expenditure (millions of US dollars),,,37.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +428,Latvia,2005,Tourism expenditure (millions of US dollars),,,446.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +422,Lebanon,1995,Tourist/visitor arrivals (thousands),TF,,450.0000,"Excluding the Lebanon, Syria and Palestine nationalities.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +422,Lebanon,2005,Tourist/visitor arrivals (thousands),TF,,1140.0000,"Excluding the Lebanon, Syria and Palestine nationalities.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +422,Lebanon,2010,Tourist/visitor arrivals (thousands),TF,,2168.0000,"Excluding the Lebanon, Syria and Palestine nationalities.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +422,Lebanon,2016,Tourist/visitor arrivals (thousands),TF,,1688.0000,"Excluding the Lebanon, Syria and Palestine nationalities.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +422,Lebanon,2017,Tourist/visitor arrivals (thousands),TF,,1857.0000,"Excluding the Lebanon, Syria and Palestine nationalities.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +422,Lebanon,2018,Tourist/visitor arrivals (thousands),TF,,1964.0000,"Excluding the Lebanon, Syria and Palestine nationalities.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +422,Lebanon,1995,Tourism expenditure (millions of US dollars),,,710.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +422,Lebanon,2005,Tourism expenditure (millions of US dollars),,,5969.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +422,Lebanon,2010,Tourism expenditure (millions of US dollars),,,8026.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +422,Lebanon,2016,Tourism expenditure (millions of US dollars),,,7373.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +422,Lebanon,2017,Tourism expenditure (millions of US dollars),,,8086.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +422,Lebanon,2018,Tourism expenditure (millions of US dollars),,,8694.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +426,Lesotho,1995,Tourist/visitor arrivals (thousands),VF,,209.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +426,Lesotho,2005,Tourist/visitor arrivals (thousands),VF,,304.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +426,Lesotho,2010,Tourist/visitor arrivals (thousands),VF,,426.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +426,Lesotho,2016,Tourist/visitor arrivals (thousands),VF,,1196.0000,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +426,Lesotho,2017,Tourist/visitor arrivals (thousands),VF,,1137.0000,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +426,Lesotho,2018,Tourist/visitor arrivals (thousands),VF,,1173.0000,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +426,Lesotho,1995,Tourism expenditure (millions of US dollars),,,27.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +426,Lesotho,2005,Tourism expenditure (millions of US dollars),,,27.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +426,Lesotho,2010,Tourism expenditure (millions of US dollars),,,23.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +426,Lesotho,2016,Tourism expenditure (millions of US dollars),,,48.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +426,Lesotho,2017,Tourism expenditure (millions of US dollars),,,23.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +426,Lesotho,2018,Tourism expenditure (millions of US dollars),,,24.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +430,Liberia,2005,Tourism expenditure (millions of US dollars),,,67.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +434,Libya,2005,Tourist/visitor arrivals (thousands),THS,,81.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +434,Libya,1995,Tourism expenditure (millions of US dollars),,,4.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +434,Libya,2005,Tourism expenditure (millions of US dollars),,,301.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +434,Libya,2010,Tourism expenditure (millions of US dollars),,,170.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +438,Liechtenstein,2010,Tourist/visitor arrivals (thousands),TCE,,64.3000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +438,Liechtenstein,2016,Tourist/visitor arrivals (thousands),TCE,,69.1000,Excluding long term tourists on campgrounds and in holiday flats.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +438,Liechtenstein,2017,Tourist/visitor arrivals (thousands),TCE,,79.3000,Excluding long term tourists on campgrounds and in holiday flats.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +438,Liechtenstein,2018,Tourist/visitor arrivals (thousands),TCE,,85.3000,Excluding long term tourists on campgrounds and in holiday flats.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +440,Lithuania,1995,Tourist/visitor arrivals (thousands),TF,,650.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +440,Lithuania,2005,Tourist/visitor arrivals (thousands),TF,,2000.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +440,Lithuania,2010,Tourist/visitor arrivals (thousands),TF,,1507.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +440,Lithuania,2016,Tourist/visitor arrivals (thousands),TF,,2296.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +440,Lithuania,2017,Tourist/visitor arrivals (thousands),TF,,2523.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +440,Lithuania,2018,Tourist/visitor arrivals (thousands),TF,,2825.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +440,Lithuania,1995,Tourism expenditure (millions of US dollars),,,77.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +440,Lithuania,2005,Tourism expenditure (millions of US dollars),,,920.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +440,Lithuania,2010,Tourism expenditure (millions of US dollars),,,958.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +440,Lithuania,2016,Tourism expenditure (millions of US dollars),,,1210.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +440,Lithuania,2017,Tourism expenditure (millions of US dollars),,,1325.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +440,Lithuania,2018,Tourism expenditure (millions of US dollars),,,1419.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +442,Luxembourg,1995,Tourist/visitor arrivals (thousands),TCE,,768.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +442,Luxembourg,2005,Tourist/visitor arrivals (thousands),TCE,,913.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +442,Luxembourg,2010,Tourist/visitor arrivals (thousands),TCE,,805.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +442,Luxembourg,2016,Tourist/visitor arrivals (thousands),TCE,,1054.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +442,Luxembourg,2017,Tourist/visitor arrivals (thousands),TCE,,1046.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +442,Luxembourg,2018,Tourist/visitor arrivals (thousands),TCE,,1018.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +442,Luxembourg,2005,Tourism expenditure (millions of US dollars),,,3770.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +442,Luxembourg,2010,Tourism expenditure (millions of US dollars),,,4519.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +442,Luxembourg,2016,Tourism expenditure (millions of US dollars),,,4766.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +442,Luxembourg,2017,Tourism expenditure (millions of US dollars),,,4993.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +442,Luxembourg,2018,Tourism expenditure (millions of US dollars),,,5537.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +450,Madagascar,1995,Tourist/visitor arrivals (thousands),TF,,75.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +450,Madagascar,2005,Tourist/visitor arrivals (thousands),TF,,277.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +450,Madagascar,2010,Tourist/visitor arrivals (thousands),TF,,196.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +450,Madagascar,2016,Tourist/visitor arrivals (thousands),TF,,293.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +450,Madagascar,2017,Tourist/visitor arrivals (thousands),TF,,255.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +450,Madagascar,2018,Tourist/visitor arrivals (thousands),TF,,291.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +450,Madagascar,1995,Tourism expenditure (millions of US dollars),,,106.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +450,Madagascar,2005,Tourism expenditure (millions of US dollars),,,275.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +450,Madagascar,2010,Tourism expenditure (millions of US dollars),,,425.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +450,Madagascar,2016,Tourism expenditure (millions of US dollars),,,913.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +450,Madagascar,2017,Tourism expenditure (millions of US dollars),,,849.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +450,Madagascar,2018,Tourism expenditure (millions of US dollars),,,879.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +454,Malawi,1995,Tourist/visitor arrivals (thousands),TF,,192.0000,Departures.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +454,Malawi,2005,Tourist/visitor arrivals (thousands),TF,,438.0000,Departures.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +454,Malawi,2010,Tourist/visitor arrivals (thousands),TF,,746.0000,Departures.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +454,Malawi,2016,Tourist/visitor arrivals (thousands),TF,,849.0000,Departures.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +454,Malawi,2017,Tourist/visitor arrivals (thousands),TF,,837.0000,Departures.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +454,Malawi,2018,Tourist/visitor arrivals (thousands),TF,,871.0000,Departures.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +454,Malawi,1995,Tourism expenditure (millions of US dollars),,,22.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +454,Malawi,2005,Tourism expenditure (millions of US dollars),,,48.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +454,Malawi,2010,Tourism expenditure (millions of US dollars),,,45.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +454,Malawi,2016,Tourism expenditure (millions of US dollars),,,30.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +454,Malawi,2017,Tourism expenditure (millions of US dollars),,,35.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +454,Malawi,2018,Tourism expenditure (millions of US dollars),,,43.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +458,Malaysia,1995,Tourist/visitor arrivals (thousands),TF,,7469.0000,Including Singapore residents crossing the frontier by road through Johore Causeway.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +458,Malaysia,2005,Tourist/visitor arrivals (thousands),TF,,16431.0000,Including Singapore residents crossing the frontier by road through Johore Causeway.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +458,Malaysia,2010,Tourist/visitor arrivals (thousands),TF,,24577.0000,Including Singapore residents crossing the frontier by road through Johore Causeway.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +458,Malaysia,2016,Tourist/visitor arrivals (thousands),TF,,26757.0000,Including Singapore residents crossing the frontier by road through Johore Causeway.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +458,Malaysia,2017,Tourist/visitor arrivals (thousands),TF,,25948.0000,Including Singapore residents crossing the frontier by road through Johore Causeway.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +458,Malaysia,2018,Tourist/visitor arrivals (thousands),TF,,25832.0000,Including Singapore residents crossing the frontier by road through Johore Causeway.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +458,Malaysia,1995,Tourism expenditure (millions of US dollars),,,5044.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +458,Malaysia,2005,Tourism expenditure (millions of US dollars),,,10389.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +458,Malaysia,2010,Tourism expenditure (millions of US dollars),,,19619.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +458,Malaysia,2016,Tourism expenditure (millions of US dollars),,,19682.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +458,Malaysia,2017,Tourism expenditure (millions of US dollars),,,20311.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +458,Malaysia,2018,Tourism expenditure (millions of US dollars),,,21774.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +462,Maldives,1995,Tourist/visitor arrivals (thousands),TF,,315.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +462,Maldives,2005,Tourist/visitor arrivals (thousands),TF,,395.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +462,Maldives,2010,Tourist/visitor arrivals (thousands),TF,,792.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +462,Maldives,2016,Tourist/visitor arrivals (thousands),TF,,1286.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +462,Maldives,2017,Tourist/visitor arrivals (thousands),TF,,1390.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +462,Maldives,2018,Tourist/visitor arrivals (thousands),TF,,1484.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +462,Maldives,2016,Tourism expenditure (millions of US dollars),,,2640.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +462,Maldives,2017,Tourism expenditure (millions of US dollars),,,2771.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +462,Maldives,2018,Tourism expenditure (millions of US dollars),,,3054.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +466,Mali,2010,Tourist/visitor arrivals (thousands),TF,,169.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +466,Mali,2016,Tourist/visitor arrivals (thousands),TF,,173.2000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +466,Mali,2017,Tourist/visitor arrivals (thousands),TF,,193.3000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +466,Mali,1995,Tourism expenditure (millions of US dollars),,,26.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +466,Mali,2005,Tourism expenditure (millions of US dollars),,,149.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +466,Mali,2010,Tourism expenditure (millions of US dollars),,,208.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +466,Mali,2016,Tourism expenditure (millions of US dollars),,,201.6000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +466,Mali,2017,Tourism expenditure (millions of US dollars),,,206.4000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +470,Malta,1995,Tourist/visitor arrivals (thousands),TF,,1116.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +470,Malta,2005,Tourist/visitor arrivals (thousands),TF,,1171.0000,Departures by air and by sea.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +470,Malta,2010,Tourist/visitor arrivals (thousands),TF,,1339.0000,Departures by air and by sea.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +470,Malta,2016,Tourist/visitor arrivals (thousands),TF,,1966.0000,Departures by air and by sea.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +470,Malta,2017,Tourist/visitor arrivals (thousands),TF,,2274.0000,Departures by air and by sea.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +470,Malta,2018,Tourist/visitor arrivals (thousands),TF,,2599.0000,Departures by air and by sea.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +470,Malta,1995,Tourism expenditure (millions of US dollars),,,656.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +470,Malta,2005,Tourism expenditure (millions of US dollars),,,755.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +470,Malta,2010,Tourism expenditure (millions of US dollars),,,1066.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +470,Malta,2016,Tourism expenditure (millions of US dollars),,,1451.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +470,Malta,2017,Tourism expenditure (millions of US dollars),,,1746.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +470,Malta,2018,Tourism expenditure (millions of US dollars),,,1845.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +584,Marshall Islands,1995,Tourist/visitor arrivals (thousands),TF,,5.5000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +584,Marshall Islands,2005,Tourist/visitor arrivals (thousands),TF,,9.2000,Air and sea arrivals.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +584,Marshall Islands,2010,Tourist/visitor arrivals (thousands),TF,,4.6000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +584,Marshall Islands,2016,Tourist/visitor arrivals (thousands),TF,,5.4000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +584,Marshall Islands,2017,Tourist/visitor arrivals (thousands),TF,,6.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +584,Marshall Islands,2018,Tourist/visitor arrivals (thousands),TF,,6.8000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +584,Marshall Islands,1995,Tourism expenditure (millions of US dollars),,,2.5000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +584,Marshall Islands,2005,Tourism expenditure (millions of US dollars),,,3.6900,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +584,Marshall Islands,2010,Tourism expenditure (millions of US dollars),,,3.7000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +584,Marshall Islands,2016,Tourism expenditure (millions of US dollars),,,30.4000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +584,Marshall Islands,2017,Tourism expenditure (millions of US dollars),,,18.1000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +584,Marshall Islands,2018,Tourism expenditure (millions of US dollars),,,20.1000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +474,Martinique,1995,Tourist/visitor arrivals (thousands),TF,,457.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +474,Martinique,2005,Tourist/visitor arrivals (thousands),TF,,484.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +474,Martinique,2010,Tourist/visitor arrivals (thousands),TF,,478.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +474,Martinique,2016,Tourist/visitor arrivals (thousands),TF,,519.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +474,Martinique,2017,Tourist/visitor arrivals (thousands),TF,,536.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +474,Martinique,2018,Tourist/visitor arrivals (thousands),TF,,537.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +474,Martinique,1995,Tourism expenditure (millions of US dollars),,,384.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +474,Martinique,2005,Tourism expenditure (millions of US dollars),,,280.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +474,Martinique,2010,Tourism expenditure (millions of US dollars),,,472.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +474,Martinique,2016,Tourism expenditure (millions of US dollars),,,348.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +474,Martinique,2017,Tourism expenditure (millions of US dollars),,,510.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +474,Martinique,2018,Tourism expenditure (millions of US dollars),,,530.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +478,Mauritania,2016,Tourism expenditure (millions of US dollars),,,33.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +478,Mauritania,2017,Tourism expenditure (millions of US dollars),,,24.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +478,Mauritania,2018,Tourism expenditure (millions of US dollars),,,6.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +480,Mauritius,1995,Tourist/visitor arrivals (thousands),TF,,422.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +480,Mauritius,2005,Tourist/visitor arrivals (thousands),TF,,761.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +480,Mauritius,2010,Tourist/visitor arrivals (thousands),TF,,935.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +480,Mauritius,2016,Tourist/visitor arrivals (thousands),TF,,1275.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +480,Mauritius,2017,Tourist/visitor arrivals (thousands),TF,,1342.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +480,Mauritius,2018,Tourist/visitor arrivals (thousands),TF,,1399.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +480,Mauritius,1995,Tourism expenditure (millions of US dollars),,,616.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +480,Mauritius,2005,Tourism expenditure (millions of US dollars),,,1189.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +480,Mauritius,2010,Tourism expenditure (millions of US dollars),,,1585.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +480,Mauritius,2016,Tourism expenditure (millions of US dollars),,,1824.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +480,Mauritius,2017,Tourism expenditure (millions of US dollars),,,2005.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +480,Mauritius,2018,Tourism expenditure (millions of US dollars),,,2161.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +484,Mexico,1995,Tourist/visitor arrivals (thousands),TF,,20241.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +484,Mexico,2005,Tourist/visitor arrivals (thousands),TF,,21915.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +484,Mexico,2010,Tourist/visitor arrivals (thousands),TF,,23290.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +484,Mexico,2016,Tourist/visitor arrivals (thousands),TF,,35079.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +484,Mexico,2017,Tourist/visitor arrivals (thousands),TF,,39291.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +484,Mexico,2018,Tourist/visitor arrivals (thousands),TF,,41313.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +484,Mexico,1995,Tourism expenditure (millions of US dollars),,,6847.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +484,Mexico,2005,Tourism expenditure (millions of US dollars),,,12801.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +484,Mexico,2010,Tourism expenditure (millions of US dollars),,,12628.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +484,Mexico,2016,Tourism expenditure (millions of US dollars),,,20619.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +484,Mexico,2017,Tourism expenditure (millions of US dollars),,,22467.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +484,Mexico,2018,Tourism expenditure (millions of US dollars),,,23802.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +583,Micronesia (Fed. States of),2005,Tourist/visitor arrivals (thousands),TF,,19.0000,"Arrivals in the States of Kosrae, Chuuk, Pohnpei and Yap; excluding FSM citizens.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +583,Micronesia (Fed. States of),2010,Tourist/visitor arrivals (thousands),TF,,44.7000,"Arrivals in the States of Kosrae, Chuuk, Pohnpei and Yap; excluding FSM citizens.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +583,Micronesia (Fed. States of),2016,Tourist/visitor arrivals (thousands),TF,,29.6000,"Arrivals in the States of Kosrae, Chuuk, Pohnpei and Yap; excluding FSM citizens.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +583,Micronesia (Fed. States of),2018,Tourist/visitor arrivals (thousands),TF,,19.2000,"Arrivals in the States of Kosrae, Chuuk, Pohnpei and Yap; excluding FSM citizens.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +583,Micronesia (Fed. States of),2010,Tourism expenditure (millions of US dollars),,,24.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +492,Monaco,1995,Tourist/visitor arrivals (thousands),THS,,233.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +492,Monaco,2005,Tourist/visitor arrivals (thousands),THS,,286.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +492,Monaco,2010,Tourist/visitor arrivals (thousands),THS,,279.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +492,Monaco,2016,Tourist/visitor arrivals (thousands),THS,,336.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +492,Monaco,2017,Tourist/visitor arrivals (thousands),THS,,355.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +492,Monaco,2018,Tourist/visitor arrivals (thousands),THS,,347.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +496,Mongolia,2005,Tourist/visitor arrivals (thousands),TF,,339.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +496,Mongolia,2010,Tourist/visitor arrivals (thousands),TF,,456.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +496,Mongolia,2016,Tourist/visitor arrivals (thousands),TF,,404.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +496,Mongolia,2017,Tourist/visitor arrivals (thousands),TF,,469.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +496,Mongolia,2018,Tourist/visitor arrivals (thousands),TF,,529.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +496,Mongolia,1995,Tourism expenditure (millions of US dollars),,,33.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +496,Mongolia,2005,Tourism expenditure (millions of US dollars),,,203.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +496,Mongolia,2010,Tourism expenditure (millions of US dollars),,,288.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +496,Mongolia,2016,Tourism expenditure (millions of US dollars),,,379.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +496,Mongolia,2017,Tourism expenditure (millions of US dollars),,,462.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +496,Mongolia,2018,Tourism expenditure (millions of US dollars),,,526.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +499,Montenegro,2005,Tourist/visitor arrivals (thousands),TCE,,272.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +499,Montenegro,2010,Tourist/visitor arrivals (thousands),TCE,,1088.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +499,Montenegro,2016,Tourist/visitor arrivals (thousands),TCE,,1662.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +499,Montenegro,2017,Tourist/visitor arrivals (thousands),TCE,,1877.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +499,Montenegro,2018,Tourist/visitor arrivals (thousands),TCE,,2077.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +499,Montenegro,2010,Tourism expenditure (millions of US dollars),,,765.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +499,Montenegro,2016,Tourism expenditure (millions of US dollars),,,978.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +499,Montenegro,2017,Tourism expenditure (millions of US dollars),,,1110.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +499,Montenegro,2018,Tourism expenditure (millions of US dollars),,,1224.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +500,Montserrat,1995,Tourist/visitor arrivals (thousands),TF,,17.7000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +500,Montserrat,2005,Tourist/visitor arrivals (thousands),TF,,9.7000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +500,Montserrat,2010,Tourist/visitor arrivals (thousands),TF,,6.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +500,Montserrat,2016,Tourist/visitor arrivals (thousands),TF,,8.8000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +500,Montserrat,2017,Tourist/visitor arrivals (thousands),TF,,8.8000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +500,Montserrat,2018,Tourist/visitor arrivals (thousands),TF,,8.8000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +500,Montserrat,1995,Tourism expenditure (millions of US dollars),,,17.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +500,Montserrat,2005,Tourism expenditure (millions of US dollars),,,9.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +500,Montserrat,2010,Tourism expenditure (millions of US dollars),,,5.9000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +500,Montserrat,2016,Tourism expenditure (millions of US dollars),,,8.6000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +500,Montserrat,2017,Tourism expenditure (millions of US dollars),,,8.4000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +500,Montserrat,2018,Tourism expenditure (millions of US dollars),,,11.1000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +504,Morocco,1995,Tourist/visitor arrivals (thousands),TF,,2602.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +504,Morocco,2005,Tourist/visitor arrivals (thousands),TF,,5843.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +504,Morocco,2010,Tourist/visitor arrivals (thousands),TF,,9288.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +504,Morocco,2016,Tourist/visitor arrivals (thousands),TF,,10332.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +504,Morocco,2017,Tourist/visitor arrivals (thousands),TF,,11349.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +504,Morocco,2018,Tourist/visitor arrivals (thousands),TF,,12289.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +504,Morocco,1995,Tourism expenditure (millions of US dollars),,,1469.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +504,Morocco,2005,Tourism expenditure (millions of US dollars),,,5426.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +504,Morocco,2010,Tourism expenditure (millions of US dollars),,,8176.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +504,Morocco,2016,Tourism expenditure (millions of US dollars),,,7922.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +504,Morocco,2017,Tourism expenditure (millions of US dollars),,,9086.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +504,Morocco,2018,Tourism expenditure (millions of US dollars),,,9523.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +508,Mozambique,2005,Tourist/visitor arrivals (thousands),TF,,578.0000,The data correspond only to 12 border posts.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +508,Mozambique,2010,Tourist/visitor arrivals (thousands),TF,,1718.0000,Break in the time series.;The data of all the border posts of the country are used.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +508,Mozambique,2016,Tourist/visitor arrivals (thousands),TF,,1639.0000,The data of all the border posts of the country are used.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +508,Mozambique,2017,Tourist/visitor arrivals (thousands),TF,,1447.0000,The data of all the border posts of the country are used.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +508,Mozambique,2018,Tourist/visitor arrivals (thousands),TF,,2743.0000,The data of all the border posts of the country are used.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +508,Mozambique,2005,Tourism expenditure (millions of US dollars),,,138.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +508,Mozambique,2010,Tourism expenditure (millions of US dollars),,,135.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +508,Mozambique,2016,Tourism expenditure (millions of US dollars),,,114.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +508,Mozambique,2017,Tourism expenditure (millions of US dollars),,,164.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +508,Mozambique,2018,Tourism expenditure (millions of US dollars),,,331.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +104,Myanmar,1995,Tourist/visitor arrivals (thousands),TF,,194.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +104,Myanmar,2005,Tourist/visitor arrivals (thousands),TF,,660.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +104,Myanmar,2010,Tourist/visitor arrivals (thousands),TF,,792.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +104,Myanmar,2016,Tourist/visitor arrivals (thousands),TF,,2907.0000,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +104,Myanmar,2017,Tourist/visitor arrivals (thousands),TF,,3443.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +104,Myanmar,2018,Tourist/visitor arrivals (thousands),TF,,3551.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +104,Myanmar,1995,Tourism expenditure (millions of US dollars),,,169.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +104,Myanmar,2005,Tourism expenditure (millions of US dollars),,,83.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +104,Myanmar,2010,Tourism expenditure (millions of US dollars),,,91.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +104,Myanmar,2016,Tourism expenditure (millions of US dollars),,,2289.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +104,Myanmar,2017,Tourism expenditure (millions of US dollars),,,1988.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +104,Myanmar,2018,Tourism expenditure (millions of US dollars),,,1670.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +516,Namibia,1995,Tourist/visitor arrivals (thousands),TF,,272.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +516,Namibia,2005,Tourist/visitor arrivals (thousands),TF,,778.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +516,Namibia,2010,Tourist/visitor arrivals (thousands),TF,,984.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +516,Namibia,2016,Tourist/visitor arrivals (thousands),TF,,1469.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +516,Namibia,2017,Tourist/visitor arrivals (thousands),TF,,1499.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +516,Namibia,2005,Tourism expenditure (millions of US dollars),,,363.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +516,Namibia,2010,Tourism expenditure (millions of US dollars),,,473.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +516,Namibia,2016,Tourism expenditure (millions of US dollars),,,349.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +516,Namibia,2017,Tourism expenditure (millions of US dollars),,,449.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +516,Namibia,2018,Tourism expenditure (millions of US dollars),,,488.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +520,Nauru,2010,Tourism expenditure (millions of US dollars),,,0.6000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +520,Nauru,2016,Tourism expenditure (millions of US dollars),,,3.4000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +520,Nauru,2017,Tourism expenditure (millions of US dollars),,,3.9000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +520,Nauru,2018,Tourism expenditure (millions of US dollars),,,1.6000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +524,Nepal,1995,Tourist/visitor arrivals (thousands),TF,,363.0000,Including arrivals from India.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +524,Nepal,2005,Tourist/visitor arrivals (thousands),TF,,375.0000,Including arrivals from India.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +524,Nepal,2010,Tourist/visitor arrivals (thousands),TF,,603.0000,Including arrivals from India.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +524,Nepal,2016,Tourist/visitor arrivals (thousands),TF,,753.0000,Including arrivals from India.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +524,Nepal,2017,Tourist/visitor arrivals (thousands),TF,,940.0000,Including arrivals from India.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +524,Nepal,2018,Tourist/visitor arrivals (thousands),TF,,1173.0000,Including arrivals from India.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +524,Nepal,1995,Tourism expenditure (millions of US dollars),,,232.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +524,Nepal,2005,Tourism expenditure (millions of US dollars),,,160.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +524,Nepal,2010,Tourism expenditure (millions of US dollars),,,378.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +524,Nepal,2016,Tourism expenditure (millions of US dollars),,,498.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +524,Nepal,2017,Tourism expenditure (millions of US dollars),,,712.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +524,Nepal,2018,Tourism expenditure (millions of US dollars),,,744.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +528,Netherlands,1995,Tourist/visitor arrivals (thousands),TCE,,6574.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +528,Netherlands,2005,Tourist/visitor arrivals (thousands),TCE,,10012.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +528,Netherlands,2010,Tourist/visitor arrivals (thousands),TCE,,10883.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +528,Netherlands,2016,Tourist/visitor arrivals (thousands),TCE,,15828.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +528,Netherlands,2017,Tourist/visitor arrivals (thousands),TCE,,17924.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +528,Netherlands,2018,Tourist/visitor arrivals (thousands),TCE,,18780.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +528,Netherlands,1995,Tourism expenditure (millions of US dollars),,,10611.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +528,Netherlands,2016,Tourism expenditure (millions of US dollars),,,21151.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +528,Netherlands,2017,Tourism expenditure (millions of US dollars),,,23414.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +528,Netherlands,2018,Tourism expenditure (millions of US dollars),,,25850.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +540,New Caledonia,1995,Tourist/visitor arrivals (thousands),TF,,86.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +540,New Caledonia,2005,Tourist/visitor arrivals (thousands),TF,,101.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +540,New Caledonia,2010,Tourist/visitor arrivals (thousands),TF,,99.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +540,New Caledonia,2016,Tourist/visitor arrivals (thousands),TF,,116.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +540,New Caledonia,2017,Tourist/visitor arrivals (thousands),TF,,121.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +540,New Caledonia,2018,Tourist/visitor arrivals (thousands),TF,,120.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +540,New Caledonia,1995,Tourism expenditure (millions of US dollars),,,108.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +540,New Caledonia,2005,Tourism expenditure (millions of US dollars),,,149.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +540,New Caledonia,2010,Tourism expenditure (millions of US dollars),,,129.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +540,New Caledonia,2016,Tourism expenditure (millions of US dollars),,,159.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +554,New Zealand,2005,Tourist/visitor arrivals (thousands),TF,,2353.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +554,New Zealand,2010,Tourist/visitor arrivals (thousands),TF,,2435.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +554,New Zealand,2016,Tourist/visitor arrivals (thousands),TF,,3370.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +554,New Zealand,2017,Tourist/visitor arrivals (thousands),TF,,3555.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +554,New Zealand,2018,Tourist/visitor arrivals (thousands),TF,,3686.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +554,New Zealand,1995,Tourism expenditure (millions of US dollars),,,2318.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +554,New Zealand,2005,Tourism expenditure (millions of US dollars),,,6486.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +554,New Zealand,2010,Tourism expenditure (millions of US dollars),,,6523.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +554,New Zealand,2016,Tourism expenditure (millions of US dollars),,,9773.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +554,New Zealand,2017,Tourism expenditure (millions of US dollars),,,10594.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +554,New Zealand,2018,Tourism expenditure (millions of US dollars),,,10961.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +558,Nicaragua,1995,Tourist/visitor arrivals (thousands),TF,,281.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +558,Nicaragua,2005,Tourist/visitor arrivals (thousands),TF,,712.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +558,Nicaragua,2010,Tourist/visitor arrivals (thousands),TF,,1011.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +558,Nicaragua,2016,Tourist/visitor arrivals (thousands),TF,,1504.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +558,Nicaragua,2017,Tourist/visitor arrivals (thousands),TF,,1787.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +558,Nicaragua,2018,Tourist/visitor arrivals (thousands),TF,,1256.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +558,Nicaragua,1995,Tourism expenditure (millions of US dollars),,,50.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +558,Nicaragua,2005,Tourism expenditure (millions of US dollars),,,206.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +558,Nicaragua,2010,Tourism expenditure (millions of US dollars),,,314.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +558,Nicaragua,2016,Tourism expenditure (millions of US dollars),,,642.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +558,Nicaragua,2017,Tourism expenditure (millions of US dollars),,,841.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +558,Nicaragua,2018,Tourism expenditure (millions of US dollars),,,544.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +562,Niger,1995,Tourist/visitor arrivals (thousands),TF,,35.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +562,Niger,2005,Tourist/visitor arrivals (thousands),TF,,58.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +562,Niger,2010,Tourist/visitor arrivals (thousands),TF,,74.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +562,Niger,2016,Tourist/visitor arrivals (thousands),TF,,152.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +562,Niger,2017,Tourist/visitor arrivals (thousands),TF,,164.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +562,Niger,2018,Tourist/visitor arrivals (thousands),TF,,157.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +562,Niger,2005,Tourism expenditure (millions of US dollars),,,43.9000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +562,Niger,2010,Tourism expenditure (millions of US dollars),,,105.5000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +562,Niger,2016,Tourism expenditure (millions of US dollars),,,84.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +562,Niger,2017,Tourism expenditure (millions of US dollars),,,91.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +566,Nigeria,1995,Tourist/visitor arrivals (thousands),TF,,656.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +566,Nigeria,2005,Tourist/visitor arrivals (thousands),TF,,1010.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +566,Nigeria,2010,Tourist/visitor arrivals (thousands),TF,,1555.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +566,Nigeria,2016,Tourist/visitor arrivals (thousands),TF,,1889.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +566,Nigeria,1995,Tourism expenditure (millions of US dollars),,,47.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +566,Nigeria,2005,Tourism expenditure (millions of US dollars),,,139.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +566,Nigeria,2010,Tourism expenditure (millions of US dollars),,,736.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +566,Nigeria,2016,Tourism expenditure (millions of US dollars),,,1088.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +566,Nigeria,2017,Tourism expenditure (millions of US dollars),,,2615.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +566,Nigeria,2018,Tourism expenditure (millions of US dollars),,,1977.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +570,Niue,1995,Tourist/visitor arrivals (thousands),TF,,2.2000,Including Niueans residing usually in New Zealand.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +570,Niue,2005,Tourist/visitor arrivals (thousands),TF,,2.8000,Including Niueans residing usually in New Zealand.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +570,Niue,2010,Tourist/visitor arrivals (thousands),TF,,6.2000,Including Niueans residing usually in New Zealand.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +570,Niue,2016,Tourist/visitor arrivals (thousands),TF,,8.9000,Including Niueans residing usually in New Zealand.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +570,Niue,2017,Tourist/visitor arrivals (thousands),TF,,9.8000,Including Niueans residing usually in New Zealand.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +570,Niue,1995,Tourism expenditure (millions of US dollars),,,2.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +570,Niue,2005,Tourism expenditure (millions of US dollars),,,1.2000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +570,Niue,2010,Tourism expenditure (millions of US dollars),,,2.2000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +807,North Macedonia,1995,Tourist/visitor arrivals (thousands),TCE,,147.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +807,North Macedonia,2005,Tourist/visitor arrivals (thousands),TCE,,197.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +807,North Macedonia,2010,Tourist/visitor arrivals (thousands),TCE,,262.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +807,North Macedonia,2016,Tourist/visitor arrivals (thousands),TCE,,510.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +807,North Macedonia,2017,Tourist/visitor arrivals (thousands),TCE,,631.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +807,North Macedonia,2018,Tourist/visitor arrivals (thousands),TCE,,707.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +807,North Macedonia,2005,Tourism expenditure (millions of US dollars),,,116.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +807,North Macedonia,2010,Tourism expenditure (millions of US dollars),,,199.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +807,North Macedonia,2016,Tourism expenditure (millions of US dollars),,,283.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +807,North Macedonia,2017,Tourism expenditure (millions of US dollars),,,331.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +807,North Macedonia,2018,Tourism expenditure (millions of US dollars),,,387.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +580,Northern Mariana Islands,1995,Tourist/visitor arrivals (thousands),TF,,669.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +580,Northern Mariana Islands,2005,Tourist/visitor arrivals (thousands),TF,,498.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +580,Northern Mariana Islands,2010,Tourist/visitor arrivals (thousands),TF,,375.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +580,Northern Mariana Islands,2016,Tourist/visitor arrivals (thousands),TF,,526.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +580,Northern Mariana Islands,2017,Tourist/visitor arrivals (thousands),TF,,656.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +580,Northern Mariana Islands,2018,Tourist/visitor arrivals (thousands),TF,,517.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +580,Northern Mariana Islands,1995,Tourism expenditure (millions of US dollars),,,655.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +578,Norway,1995,Tourist/visitor arrivals (thousands),TF,,2880.0000,Non-resident tourists staying in registered hotels.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +578,Norway,2005,Tourist/visitor arrivals (thousands),TF,,3824.0000,Arrivals of non-resident tourists at national borders.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +578,Norway,2010,Tourist/visitor arrivals (thousands),TF,,4767.0000,Arrivals of non-resident tourists at national borders.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +578,Norway,2016,Tourist/visitor arrivals (thousands),TF,,5960.0000,Non-resident tourists staying in all types of accommodation establishments.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +578,Norway,2017,Tourist/visitor arrivals (thousands),TF,,6252.0000,Non-resident tourists staying in all types of accommodation establishments.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +578,Norway,2018,Tourist/visitor arrivals (thousands),TF,,5688.0000,Non-resident tourists staying in all types of accommodation establishments.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +578,Norway,1995,Tourism expenditure (millions of US dollars),,,2730.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +578,Norway,2005,Tourism expenditure (millions of US dollars),,,4243.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +578,Norway,2010,Tourism expenditure (millions of US dollars),,,5299.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +578,Norway,2016,Tourism expenditure (millions of US dollars),,,6285.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +578,Norway,2017,Tourism expenditure (millions of US dollars),,,6840.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +578,Norway,2018,Tourism expenditure (millions of US dollars),,,7096.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +512,Oman,2005,Tourist/visitor arrivals (thousands),TF,,891.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +512,Oman,2010,Tourist/visitor arrivals (thousands),TF,,1441.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +512,Oman,2016,Tourist/visitor arrivals (thousands),TF,,2335.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +512,Oman,2017,Tourist/visitor arrivals (thousands),TF,,2316.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +512,Oman,2018,Tourist/visitor arrivals (thousands),TF,,2301.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +512,Oman,2005,Tourism expenditure (millions of US dollars),,,627.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +512,Oman,2010,Tourism expenditure (millions of US dollars),,,1072.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +512,Oman,2016,Tourism expenditure (millions of US dollars),,,2390.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +512,Oman,2017,Tourism expenditure (millions of US dollars),,,2717.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +512,Oman,2018,Tourism expenditure (millions of US dollars),,,2975.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +158,Other non-specified areas,1995,Tourist/visitor arrivals (thousands),VF,,2332.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +158,Other non-specified areas,2005,Tourist/visitor arrivals (thousands),VF,,3378.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +158,Other non-specified areas,2010,Tourist/visitor arrivals (thousands),VF,,5567.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +158,Other non-specified areas,2016,Tourist/visitor arrivals (thousands),VF,,10690.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +158,Other non-specified areas,2017,Tourist/visitor arrivals (thousands),VF,,10740.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +158,Other non-specified areas,2018,Tourist/visitor arrivals (thousands),VF,,11067.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +158,Other non-specified areas,1995,Tourism expenditure (millions of US dollars),,,3985.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +158,Other non-specified areas,2005,Tourism expenditure (millions of US dollars),,,5740.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +158,Other non-specified areas,2010,Tourism expenditure (millions of US dollars),,,10387.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +158,Other non-specified areas,2016,Tourism expenditure (millions of US dollars),,,15825.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +158,Other non-specified areas,2017,Tourism expenditure (millions of US dollars),,,14847.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +158,Other non-specified areas,2018,Tourism expenditure (millions of US dollars),,,16366.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +586,Pakistan,1995,Tourist/visitor arrivals (thousands),TF,,378.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +586,Pakistan,2005,Tourist/visitor arrivals (thousands),TF,,798.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +586,Pakistan,2010,Tourist/visitor arrivals (thousands),TF,,907.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +586,Pakistan,1995,Tourism expenditure (millions of US dollars),,,582.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +586,Pakistan,2005,Tourism expenditure (millions of US dollars),,,828.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +586,Pakistan,2010,Tourism expenditure (millions of US dollars),,,998.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +586,Pakistan,2016,Tourism expenditure (millions of US dollars),,,791.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +586,Pakistan,2017,Tourism expenditure (millions of US dollars),,,866.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +586,Pakistan,2018,Tourism expenditure (millions of US dollars),,,818.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +585,Palau,1995,Tourist/visitor arrivals (thousands),TF,,53.0000,Air arrivals (Palau International Airport).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +585,Palau,2005,Tourist/visitor arrivals (thousands),TF,,81.0000,Air arrivals (Palau International Airport).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +585,Palau,2010,Tourist/visitor arrivals (thousands),TF,,85.0000,Air arrivals (Palau International Airport).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +585,Palau,2016,Tourist/visitor arrivals (thousands),TF,,138.0000,Air arrivals (Palau International Airport).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +585,Palau,2017,Tourist/visitor arrivals (thousands),TF,,123.0000,Air arrivals (Palau International Airport).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +585,Palau,2018,Tourist/visitor arrivals (thousands),TF,,106.0000,Air arrivals (Palau International Airport).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +585,Palau,2005,Tourism expenditure (millions of US dollars),,,63.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +585,Palau,2010,Tourism expenditure (millions of US dollars),,,76.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +585,Palau,2016,Tourism expenditure (millions of US dollars),,,148.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +585,Palau,2017,Tourism expenditure (millions of US dollars),,,123.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +591,Panama,1995,Tourist/visitor arrivals (thousands),TF,,345.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +591,Panama,2005,Tourist/visitor arrivals (thousands),TF,,702.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +591,Panama,2010,Tourist/visitor arrivals (thousands),TF,,1324.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +591,Panama,2016,Tourist/visitor arrivals (thousands),TF,,1921.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +591,Panama,2017,Tourist/visitor arrivals (thousands),TF,,1843.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +591,Panama,2018,Tourist/visitor arrivals (thousands),TF,,1785.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +591,Panama,1995,Tourism expenditure (millions of US dollars),,,372.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +591,Panama,2005,Tourism expenditure (millions of US dollars),,,1108.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +591,Panama,2010,Tourism expenditure (millions of US dollars),,,2621.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +591,Panama,2016,Tourism expenditure (millions of US dollars),,,6280.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +591,Panama,2017,Tourism expenditure (millions of US dollars),,,6824.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +591,Panama,2018,Tourism expenditure (millions of US dollars),,,5615.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +598,Papua New Guinea,1995,Tourist/visitor arrivals (thousands),TF,,42.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +598,Papua New Guinea,2005,Tourist/visitor arrivals (thousands),TF,,69.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +598,Papua New Guinea,2010,Tourist/visitor arrivals (thousands),TF,,140.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +598,Papua New Guinea,2016,Tourist/visitor arrivals (thousands),TF,,179.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +598,Papua New Guinea,2017,Tourist/visitor arrivals (thousands),TF,,139.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +598,Papua New Guinea,2018,Tourist/visitor arrivals (thousands),TF,,140.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +598,Papua New Guinea,2005,Tourism expenditure (millions of US dollars),,,9.4000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +598,Papua New Guinea,2010,Tourism expenditure (millions of US dollars),,,2.4000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +598,Papua New Guinea,2016,Tourism expenditure (millions of US dollars),,,1.6000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +598,Papua New Guinea,2017,Tourism expenditure (millions of US dollars),,,15.3000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +600,Paraguay,1995,Tourist/visitor arrivals (thousands),TF,,438.0000,Excluding nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +600,Paraguay,2005,Tourist/visitor arrivals (thousands),TF,,341.0000,Excluding nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +600,Paraguay,2010,Tourist/visitor arrivals (thousands),TF,,465.0000,Excluding nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +600,Paraguay,2016,Tourist/visitor arrivals (thousands),TF,,1308.0000,Excluding nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +600,Paraguay,2017,Tourist/visitor arrivals (thousands),TF,,1584.0000,Excluding nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +600,Paraguay,2018,Tourist/visitor arrivals (thousands),TF,,1181.0000,Excluding nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +600,Paraguay,1995,Tourism expenditure (millions of US dollars),,,162.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +600,Paraguay,2005,Tourism expenditure (millions of US dollars),,,96.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +600,Paraguay,2010,Tourism expenditure (millions of US dollars),,,243.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +600,Paraguay,2016,Tourism expenditure (millions of US dollars),,,356.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +600,Paraguay,2017,Tourism expenditure (millions of US dollars),,,399.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +600,Paraguay,2018,Tourism expenditure (millions of US dollars),,,393.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +604,Peru,1995,Tourist/visitor arrivals (thousands),TF,,479.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +604,Peru,2005,Tourist/visitor arrivals (thousands),TF,,1571.0000,Including nationals residing abroad.;Including tourists with identity document other than a passport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +604,Peru,2010,Tourist/visitor arrivals (thousands),TF,,2299.0000,Including nationals residing abroad.;Including tourists with identity document other than a passport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +604,Peru,2016,Tourist/visitor arrivals (thousands),TF,,3744.0000,Including nationals residing abroad.;Including tourists with identity document other than a passport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +604,Peru,2017,Tourist/visitor arrivals (thousands),TF,,4032.0000,Including nationals residing abroad.;Including tourists with identity document other than a passport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +604,Peru,2018,Tourist/visitor arrivals (thousands),TF,,4419.0000,Including nationals residing abroad.;Including tourists with identity document other than a passport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +604,Peru,1995,Tourism expenditure (millions of US dollars),,,521.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +604,Peru,2005,Tourism expenditure (millions of US dollars),,,1438.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +604,Peru,2010,Tourism expenditure (millions of US dollars),,,2475.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +604,Peru,2016,Tourism expenditure (millions of US dollars),,,4288.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +604,Peru,2017,Tourism expenditure (millions of US dollars),,,4573.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +604,Peru,2018,Tourism expenditure (millions of US dollars),,,4894.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +608,Philippines,1995,Tourist/visitor arrivals (thousands),TF,,1760.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +608,Philippines,2005,Tourist/visitor arrivals (thousands),TF,,2623.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +608,Philippines,2010,Tourist/visitor arrivals (thousands),TF,,3520.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +608,Philippines,2016,Tourist/visitor arrivals (thousands),TF,,5967.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +608,Philippines,2017,Tourist/visitor arrivals (thousands),TF,,6621.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +608,Philippines,2018,Tourist/visitor arrivals (thousands),TF,,7168.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +608,Philippines,1995,Tourism expenditure (millions of US dollars),,,1141.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +608,Philippines,2005,Tourism expenditure (millions of US dollars),,,2863.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +608,Philippines,2010,Tourism expenditure (millions of US dollars),,,3441.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +608,Philippines,2016,Tourism expenditure (millions of US dollars),,,6289.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +608,Philippines,2017,Tourism expenditure (millions of US dollars),,,8349.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +608,Philippines,2018,Tourism expenditure (millions of US dollars),,,9730.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +616,Poland,1995,Tourist/visitor arrivals (thousands),TF,,19215.0000,"Border statistics are not collected any more, surveys used instead.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +616,Poland,2005,Tourist/visitor arrivals (thousands),TF,,15200.0000,"Border statistics are not collected any more, surveys used instead.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +616,Poland,2010,Tourist/visitor arrivals (thousands),TF,,12470.0000,"Border statistics are not collected any more, surveys used instead.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +616,Poland,2016,Tourist/visitor arrivals (thousands),TF,,17471.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +616,Poland,2017,Tourist/visitor arrivals (thousands),TF,,18258.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +616,Poland,2018,Tourist/visitor arrivals (thousands),TF,,19622.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +616,Poland,1995,Tourism expenditure (millions of US dollars),,,6927.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +616,Poland,2005,Tourism expenditure (millions of US dollars),,,7161.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +616,Poland,2010,Tourism expenditure (millions of US dollars),,,10036.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +616,Poland,2016,Tourism expenditure (millions of US dollars),,,12052.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +616,Poland,2017,Tourism expenditure (millions of US dollars),,,14083.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +616,Poland,2018,Tourism expenditure (millions of US dollars),,,15748.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +620,Portugal,1995,Tourist/visitor arrivals (thousands),TCE,,4572.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +620,Portugal,2005,Tourist/visitor arrivals (thousands),TCE,,5769.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +620,Portugal,2010,Tourist/visitor arrivals (thousands),TCE,,6756.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +620,Portugal,2016,Tourist/visitor arrivals (thousands),TCE,,13359.0000,"Include hotels, apartment hotels, “pousadas”, tourist apartments, tourist villages, camping sites, recreation centres, tourism in rural areas and local accommodation.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +620,Portugal,2017,Tourist/visitor arrivals (thousands),TCE,,15432.0000,"Include hotels, apartment hotels, “pousadas”, tourist apartments, tourist villages, camping sites, recreation centres, tourism in rural areas and local accommodation.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +620,Portugal,2018,Tourist/visitor arrivals (thousands),TCE,,16186.0000,"Include hotels, apartment hotels, “pousadas”, tourist apartments, tourist villages, camping sites, recreation centres, tourism in rural areas and local accommodation.","World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +620,Portugal,1995,Tourism expenditure (millions of US dollars),,,5646.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +620,Portugal,2005,Tourism expenditure (millions of US dollars),,,9038.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +620,Portugal,2010,Tourism expenditure (millions of US dollars),,,12984.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +620,Portugal,2016,Tourism expenditure (millions of US dollars),,,17347.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +620,Portugal,2017,Tourism expenditure (millions of US dollars),,,21586.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +620,Portugal,2018,Tourism expenditure (millions of US dollars),,,24105.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +630,Puerto Rico,1995,Tourist/visitor arrivals (thousands),TF,,3131.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +630,Puerto Rico,2005,Tourist/visitor arrivals (thousands),TF,,3686.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +630,Puerto Rico,2010,Tourist/visitor arrivals (thousands),TF,,3186.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +630,Puerto Rico,2016,Tourist/visitor arrivals (thousands),TF,,3736.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +630,Puerto Rico,2017,Tourist/visitor arrivals (thousands),TF,,3513.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +630,Puerto Rico,2018,Tourist/visitor arrivals (thousands),TF,,3068.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +630,Puerto Rico,1995,Tourism expenditure (millions of US dollars),,,1828.0000,Data refer to fiscal years beginning 1 July.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +630,Puerto Rico,2005,Tourism expenditure (millions of US dollars),,,3239.0000,Data refer to fiscal years beginning 1 July.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +630,Puerto Rico,2010,Tourism expenditure (millions of US dollars),,,3211.0000,Data refer to fiscal years beginning 1 July.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +630,Puerto Rico,2016,Tourism expenditure (millions of US dollars),,,3974.0000,Data refer to fiscal years beginning 1 July.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +630,Puerto Rico,2017,Tourism expenditure (millions of US dollars),,,3848.0000,Data refer to fiscal years beginning 1 July.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +630,Puerto Rico,2018,Tourism expenditure (millions of US dollars),,,3282.0000,Data refer to fiscal years beginning 1 July.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +634,Qatar,2010,Tourist/visitor arrivals (thousands),TF,,1699.5000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +634,Qatar,2016,Tourist/visitor arrivals (thousands),TF,,2938.2000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +634,Qatar,2017,Tourist/visitor arrivals (thousands),TF,,2256.5000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +634,Qatar,2018,Tourist/visitor arrivals (thousands),TF,,1819.3000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +634,Qatar,2016,Tourism expenditure (millions of US dollars),,,12593.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +634,Qatar,2017,Tourism expenditure (millions of US dollars),,,15757.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +634,Qatar,2018,Tourism expenditure (millions of US dollars),,,15239.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +410,Republic of Korea,1995,Tourist/visitor arrivals (thousands),VF,,3753.0000,Including nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +410,Republic of Korea,2005,Tourist/visitor arrivals (thousands),VF,,6023.0000,Including nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +410,Republic of Korea,2010,Tourist/visitor arrivals (thousands),VF,,8798.0000,Including nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +410,Republic of Korea,2016,Tourist/visitor arrivals (thousands),VF,,17242.0000,Including nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +410,Republic of Korea,2017,Tourist/visitor arrivals (thousands),VF,,13336.0000,Including nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +410,Republic of Korea,2018,Tourist/visitor arrivals (thousands),VF,,15347.0000,Including nationals residing abroad and crew members.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +410,Republic of Korea,1995,Tourism expenditure (millions of US dollars),,,6670.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +410,Republic of Korea,2005,Tourism expenditure (millions of US dollars),,,8282.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +410,Republic of Korea,2010,Tourism expenditure (millions of US dollars),,,14315.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +410,Republic of Korea,2016,Tourism expenditure (millions of US dollars),,,20924.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +410,Republic of Korea,2017,Tourism expenditure (millions of US dollars),,,17173.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +410,Republic of Korea,2018,Tourism expenditure (millions of US dollars),,,19856.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +498,Republic of Moldova,2005,Tourist/visitor arrivals (thousands),TCE,,67.0000,Excluding the left side of the river Nistru and the municipality of Bender.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +498,Republic of Moldova,2010,Tourist/visitor arrivals (thousands),TCE,,64.0000,Excluding the left side of the river Nistru and the municipality of Bender.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +498,Republic of Moldova,2016,Tourist/visitor arrivals (thousands),TCE,,121.0000,Excluding the left side of the river Nistru and the municipality of Bender.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +498,Republic of Moldova,2017,Tourist/visitor arrivals (thousands),TCE,,145.0000,Excluding the left side of the river Nistru and the municipality of Bender.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +498,Republic of Moldova,2018,Tourist/visitor arrivals (thousands),TCE,,160.0000,Excluding the left side of the river Nistru and the municipality of Bender.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +498,Republic of Moldova,1995,Tourism expenditure (millions of US dollars),,,71.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +498,Republic of Moldova,2005,Tourism expenditure (millions of US dollars),,,138.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +498,Republic of Moldova,2010,Tourism expenditure (millions of US dollars),,,222.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +498,Republic of Moldova,2016,Tourism expenditure (millions of US dollars),,,344.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +498,Republic of Moldova,2017,Tourism expenditure (millions of US dollars),,,443.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +498,Republic of Moldova,2018,Tourism expenditure (millions of US dollars),,,500.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +638,Réunion,1995,Tourist/visitor arrivals (thousands),TF,,304.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +638,Réunion,2005,Tourist/visitor arrivals (thousands),TF,,409.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +638,Réunion,2010,Tourist/visitor arrivals (thousands),TF,,420.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +638,Réunion,2016,Tourist/visitor arrivals (thousands),TF,,458.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +638,Réunion,2017,Tourist/visitor arrivals (thousands),TF,,508.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +638,Réunion,2018,Tourist/visitor arrivals (thousands),TF,,535.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +638,Réunion,1995,Tourism expenditure (millions of US dollars),,,216.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +638,Réunion,2005,Tourism expenditure (millions of US dollars),,,364.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +638,Réunion,2010,Tourism expenditure (millions of US dollars),,,392.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +638,Réunion,2016,Tourism expenditure (millions of US dollars),,,343.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +638,Réunion,2017,Tourism expenditure (millions of US dollars),,,427.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +638,Réunion,2018,Tourism expenditure (millions of US dollars),,,495.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +642,Romania,1995,Tourist/visitor arrivals (thousands),VF,,5445.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +642,Romania,2005,Tourist/visitor arrivals (thousands),VF,,5839.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +642,Romania,2010,Tourist/visitor arrivals (thousands),VF,,7498.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +642,Romania,2016,Tourist/visitor arrivals (thousands),VF,,10223.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +642,Romania,2017,Tourist/visitor arrivals (thousands),VF,,10926.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +642,Romania,2018,Tourist/visitor arrivals (thousands),VF,,11720.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +642,Romania,1995,Tourism expenditure (millions of US dollars),,,689.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +642,Romania,2005,Tourism expenditure (millions of US dollars),,,1324.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +642,Romania,2010,Tourism expenditure (millions of US dollars),,,1631.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +642,Romania,2016,Tourism expenditure (millions of US dollars),,,2172.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +642,Romania,2017,Tourism expenditure (millions of US dollars),,,3008.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +642,Romania,2018,Tourism expenditure (millions of US dollars),,,3261.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +643,Russian Federation,1995,Tourist/visitor arrivals (thousands),VF,,10290.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +643,Russian Federation,2005,Tourist/visitor arrivals (thousands),VF,,22201.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +643,Russian Federation,2010,Tourist/visitor arrivals (thousands),VF,,22281.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +643,Russian Federation,2016,Tourist/visitor arrivals (thousands),VF,,24571.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +643,Russian Federation,2017,Tourist/visitor arrivals (thousands),VF,,24390.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +643,Russian Federation,2018,Tourist/visitor arrivals (thousands),VF,,24551.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +643,Russian Federation,2005,Tourism expenditure (millions of US dollars),,,7805.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +643,Russian Federation,2010,Tourism expenditure (millions of US dollars),,,13239.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +643,Russian Federation,2016,Tourism expenditure (millions of US dollars),,,12822.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +643,Russian Federation,2017,Tourism expenditure (millions of US dollars),,,14983.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +643,Russian Federation,2018,Tourism expenditure (millions of US dollars),,,18670.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +646,Rwanda,2010,Tourist/visitor arrivals (thousands),TF,,504.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +646,Rwanda,2016,Tourist/visitor arrivals (thousands),TF,,932.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +646,Rwanda,1995,Tourism expenditure (millions of US dollars),,,4.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +646,Rwanda,2005,Tourism expenditure (millions of US dollars),,,67.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +646,Rwanda,2010,Tourism expenditure (millions of US dollars),,,224.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +646,Rwanda,2016,Tourism expenditure (millions of US dollars),,,443.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +646,Rwanda,2017,Tourism expenditure (millions of US dollars),,,548.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +646,Rwanda,2018,Tourism expenditure (millions of US dollars),,,528.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +667,Saba,1995,Tourist/visitor arrivals (thousands),TF,,10.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +667,Saba,2005,Tourist/visitor arrivals (thousands),TF,,11.5000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +667,Saba,2010,Tourist/visitor arrivals (thousands),TF,,12.3000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +659,Saint Kitts and Nevis,1995,Tourist/visitor arrivals (thousands),TF,,79.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +659,Saint Kitts and Nevis,2005,Tourist/visitor arrivals (thousands),TF,,141.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +659,Saint Kitts and Nevis,2010,Tourist/visitor arrivals (thousands),TF,,98.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +659,Saint Kitts and Nevis,2016,Tourist/visitor arrivals (thousands),TF,,116.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +659,Saint Kitts and Nevis,2017,Tourist/visitor arrivals (thousands),TF,,115.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +659,Saint Kitts and Nevis,2018,Tourist/visitor arrivals (thousands),TF,,125.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +659,Saint Kitts and Nevis,1995,Tourism expenditure (millions of US dollars),,,63.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +659,Saint Kitts and Nevis,2005,Tourism expenditure (millions of US dollars),,,121.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +659,Saint Kitts and Nevis,2010,Tourism expenditure (millions of US dollars),,,90.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +659,Saint Kitts and Nevis,2016,Tourism expenditure (millions of US dollars),,,332.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +659,Saint Kitts and Nevis,2017,Tourism expenditure (millions of US dollars),,,355.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +659,Saint Kitts and Nevis,2018,Tourism expenditure (millions of US dollars),,,367.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +662,Saint Lucia,1995,Tourist/visitor arrivals (thousands),TF,,231.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +662,Saint Lucia,2005,Tourist/visitor arrivals (thousands),TF,,318.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +662,Saint Lucia,2010,Tourist/visitor arrivals (thousands),TF,,306.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +662,Saint Lucia,2016,Tourist/visitor arrivals (thousands),TF,,348.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +662,Saint Lucia,2017,Tourist/visitor arrivals (thousands),TF,,386.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +662,Saint Lucia,2018,Tourist/visitor arrivals (thousands),TF,,395.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +662,Saint Lucia,1995,Tourism expenditure (millions of US dollars),,,230.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +662,Saint Lucia,2005,Tourism expenditure (millions of US dollars),,,382.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +662,Saint Lucia,2010,Tourism expenditure (millions of US dollars),,,309.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +662,Saint Lucia,2016,Tourism expenditure (millions of US dollars),,,776.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +662,Saint Lucia,2017,Tourism expenditure (millions of US dollars),,,875.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +662,Saint Lucia,2018,Tourism expenditure (millions of US dollars),,,989.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +670,Saint Vincent & Grenadines,1995,Tourist/visitor arrivals (thousands),TF,,60.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +670,Saint Vincent & Grenadines,2005,Tourist/visitor arrivals (thousands),TF,,96.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +670,Saint Vincent & Grenadines,2010,Tourist/visitor arrivals (thousands),TF,,72.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +670,Saint Vincent & Grenadines,2016,Tourist/visitor arrivals (thousands),TF,,79.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +670,Saint Vincent & Grenadines,2017,Tourist/visitor arrivals (thousands),TF,,76.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +670,Saint Vincent & Grenadines,2018,Tourist/visitor arrivals (thousands),TF,,80.0000,Arrivals of non-resident tourists by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +670,Saint Vincent & Grenadines,1995,Tourism expenditure (millions of US dollars),,,53.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +670,Saint Vincent & Grenadines,2005,Tourism expenditure (millions of US dollars),,,104.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +670,Saint Vincent & Grenadines,2010,Tourism expenditure (millions of US dollars),,,86.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +670,Saint Vincent & Grenadines,2016,Tourism expenditure (millions of US dollars),,,216.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +670,Saint Vincent & Grenadines,2017,Tourism expenditure (millions of US dollars),,,211.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +670,Saint Vincent & Grenadines,2018,Tourism expenditure (millions of US dollars),,,235.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +882,Samoa,1995,Tourist/visitor arrivals (thousands),TF,,68.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +882,Samoa,2005,Tourist/visitor arrivals (thousands),TF,,102.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +882,Samoa,2010,Tourist/visitor arrivals (thousands),TF,,122.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +882,Samoa,2016,Tourist/visitor arrivals (thousands),TF,,134.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +882,Samoa,2017,Tourist/visitor arrivals (thousands),TF,,146.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +882,Samoa,2018,Tourist/visitor arrivals (thousands),TF,,164.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +882,Samoa,1995,Tourism expenditure (millions of US dollars),,,35.6994,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +882,Samoa,2005,Tourism expenditure (millions of US dollars),,,73.8000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +882,Samoa,2010,Tourism expenditure (millions of US dollars),,,123.7000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +882,Samoa,2016,Tourism expenditure (millions of US dollars),,,148.7000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +882,Samoa,2017,Tourism expenditure (millions of US dollars),,,167.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +882,Samoa,2018,Tourism expenditure (millions of US dollars),,,191.3000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +674,San Marino,1995,Tourist/visitor arrivals (thousands),THS,,28.0000,Including Italian tourists.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +674,San Marino,2005,Tourist/visitor arrivals (thousands),THS,,50.0000,Including Italian tourists.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +674,San Marino,2010,Tourist/visitor arrivals (thousands),THS,,120.0000,Including Italian tourists.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +674,San Marino,2016,Tourist/visitor arrivals (thousands),THS,,60.0000,Including Italian tourists.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +674,San Marino,2017,Tourist/visitor arrivals (thousands),THS,,78.0000,Including Italian tourists.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +674,San Marino,2018,Tourist/visitor arrivals (thousands),THS,,84.0000,Including Italian tourists.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +678,Sao Tome and Principe,1995,Tourist/visitor arrivals (thousands),TF,,6.2000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +678,Sao Tome and Principe,2005,Tourist/visitor arrivals (thousands),TF,,15.8000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +678,Sao Tome and Principe,2010,Tourist/visitor arrivals (thousands),TF,,8.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +678,Sao Tome and Principe,2016,Tourist/visitor arrivals (thousands),TF,,28.9000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +678,Sao Tome and Principe,2017,Tourist/visitor arrivals (thousands),TF,,28.9000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +678,Sao Tome and Principe,2018,Tourist/visitor arrivals (thousands),TF,,33.4000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +678,Sao Tome and Principe,2016,Tourism expenditure (millions of US dollars),,,69.1000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +678,Sao Tome and Principe,2017,Tourism expenditure (millions of US dollars),,,65.9000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +678,Sao Tome and Principe,2018,Tourism expenditure (millions of US dollars),,,71.9000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +682,Saudi Arabia,1995,Tourist/visitor arrivals (thousands),TF,,3325.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +682,Saudi Arabia,2005,Tourist/visitor arrivals (thousands),TF,,8037.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +682,Saudi Arabia,2010,Tourist/visitor arrivals (thousands),TF,,10850.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +682,Saudi Arabia,2016,Tourist/visitor arrivals (thousands),TF,,18044.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +682,Saudi Arabia,2017,Tourist/visitor arrivals (thousands),TF,,16109.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +682,Saudi Arabia,2018,Tourist/visitor arrivals (thousands),TF,,15334.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +682,Saudi Arabia,2010,Tourism expenditure (millions of US dollars),,,7536.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +682,Saudi Arabia,2016,Tourism expenditure (millions of US dollars),,,13438.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +682,Saudi Arabia,2017,Tourism expenditure (millions of US dollars),,,15020.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +682,Saudi Arabia,2018,Tourism expenditure (millions of US dollars),,,16975.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +686,Senegal,2005,Tourist/visitor arrivals (thousands),TF,,769.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +686,Senegal,2010,Tourist/visitor arrivals (thousands),TF,,900.0000,Estimate.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +686,Senegal,2016,Tourist/visitor arrivals (thousands),TF,,1210.0000,Estimate.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +686,Senegal,2017,Tourist/visitor arrivals (thousands),TF,,1365.0000,Estimate.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +686,Senegal,1995,Tourism expenditure (millions of US dollars),,,168.1803,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +686,Senegal,2005,Tourism expenditure (millions of US dollars),,,334.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +686,Senegal,2010,Tourism expenditure (millions of US dollars),,,464.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +686,Senegal,2016,Tourism expenditure (millions of US dollars),,,438.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +686,Senegal,2017,Tourism expenditure (millions of US dollars),,,468.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +688,Serbia,2005,Tourist/visitor arrivals (thousands),TCE,,453.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +688,Serbia,2010,Tourist/visitor arrivals (thousands),TCE,,683.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +688,Serbia,2016,Tourist/visitor arrivals (thousands),TCE,,1281.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +688,Serbia,2017,Tourist/visitor arrivals (thousands),TCE,,1497.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +688,Serbia,2018,Tourist/visitor arrivals (thousands),TCE,,1711.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +688,Serbia,2005,Tourism expenditure (millions of US dollars),,,308.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +688,Serbia,2010,Tourism expenditure (millions of US dollars),,,950.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +688,Serbia,2016,Tourism expenditure (millions of US dollars),,,1461.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +688,Serbia,2017,Tourism expenditure (millions of US dollars),,,1706.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +688,Serbia,2018,Tourism expenditure (millions of US dollars),,,1921.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +690,Seychelles,1995,Tourist/visitor arrivals (thousands),TF,,121.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +690,Seychelles,2005,Tourist/visitor arrivals (thousands),TF,,129.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +690,Seychelles,2010,Tourist/visitor arrivals (thousands),TF,,175.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +690,Seychelles,2016,Tourist/visitor arrivals (thousands),TF,,303.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +690,Seychelles,2017,Tourist/visitor arrivals (thousands),TF,,350.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +690,Seychelles,2018,Tourist/visitor arrivals (thousands),TF,,362.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +690,Seychelles,1995,Tourism expenditure (millions of US dollars),,,224.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +690,Seychelles,2005,Tourism expenditure (millions of US dollars),,,269.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +690,Seychelles,2010,Tourism expenditure (millions of US dollars),,,352.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +690,Seychelles,2016,Tourism expenditure (millions of US dollars),,,505.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +690,Seychelles,2017,Tourism expenditure (millions of US dollars),,,585.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +690,Seychelles,2018,Tourism expenditure (millions of US dollars),,,611.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +694,Sierra Leone,1995,Tourist/visitor arrivals (thousands),TF,,13.8000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +694,Sierra Leone,2005,Tourist/visitor arrivals (thousands),TF,,40.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +694,Sierra Leone,2010,Tourist/visitor arrivals (thousands),TF,,39.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +694,Sierra Leone,2016,Tourist/visitor arrivals (thousands),TF,,55.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +694,Sierra Leone,2017,Tourist/visitor arrivals (thousands),TF,,51.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +694,Sierra Leone,2018,Tourist/visitor arrivals (thousands),TF,,57.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +694,Sierra Leone,1995,Tourism expenditure (millions of US dollars),,,57.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +694,Sierra Leone,2005,Tourism expenditure (millions of US dollars),,,64.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +694,Sierra Leone,2010,Tourism expenditure (millions of US dollars),,,26.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +694,Sierra Leone,2016,Tourism expenditure (millions of US dollars),,,41.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +694,Sierra Leone,2017,Tourism expenditure (millions of US dollars),,,39.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +694,Sierra Leone,2018,Tourism expenditure (millions of US dollars),,,39.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +702,Singapore,1995,Tourist/visitor arrivals (thousands),TF,,6070.0000,Excluding Malaysian citizens arriving by land.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +702,Singapore,2005,Tourist/visitor arrivals (thousands),TF,,7079.0000,Excluding Malaysian citizens arriving by land.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +702,Singapore,2010,Tourist/visitor arrivals (thousands),TF,,9161.0000,Excluding Malaysian citizens arriving by land.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +702,Singapore,2016,Tourist/visitor arrivals (thousands),TF,,12913.0000,Excluding Malaysian citizens arriving by land.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +702,Singapore,2017,Tourist/visitor arrivals (thousands),TF,,13903.0000,Excluding Malaysian citizens arriving by land.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +702,Singapore,2018,Tourist/visitor arrivals (thousands),TF,,14673.0000,Excluding Malaysian citizens arriving by land.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +702,Singapore,1995,Tourism expenditure (millions of US dollars),,,7611.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +702,Singapore,2005,Tourism expenditure (millions of US dollars),,,6209.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +702,Singapore,2010,Tourism expenditure (millions of US dollars),,,14178.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +702,Singapore,2016,Tourism expenditure (millions of US dollars),,,18944.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +702,Singapore,2017,Tourism expenditure (millions of US dollars),,,19891.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +702,Singapore,2018,Tourism expenditure (millions of US dollars),,,20416.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +668,Sint Eustatius,1995,Tourist/visitor arrivals (thousands),TF,,8.8000,Excluding Netherlands Antillean residents.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +668,Sint Eustatius,2005,Tourist/visitor arrivals (thousands),TF,,10.4000,Excluding Netherlands Antillean residents.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +668,Sint Eustatius,2010,Tourist/visitor arrivals (thousands),TF,,11.4000,Excluding Netherlands Antillean residents.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +534,Sint Maarten (Dutch part),1995,Tourist/visitor arrivals (thousands),TF,,460.0000,Arrivals by air. Including arrivals to Saint Martin (French part).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +534,Sint Maarten (Dutch part),2005,Tourist/visitor arrivals (thousands),TF,,468.0000,Arrivals by air. Including arrivals to Saint Martin (French part).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +534,Sint Maarten (Dutch part),2010,Tourist/visitor arrivals (thousands),TF,,443.0000,Arrivals by air. Including arrivals to Saint Martin (French part).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +534,Sint Maarten (Dutch part),2016,Tourist/visitor arrivals (thousands),TF,,528.0000,Arrivals by air. Including arrivals to Saint Martin (French part).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +534,Sint Maarten (Dutch part),2017,Tourist/visitor arrivals (thousands),TF,,402.0000,Arrivals by air. Including arrivals to Saint Martin (French part).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +534,Sint Maarten (Dutch part),2018,Tourist/visitor arrivals (thousands),TF,,178.0000,Arrivals by air. Including arrivals to Saint Martin (French part).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +534,Sint Maarten (Dutch part),2010,Tourism expenditure (millions of US dollars),,,681.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +534,Sint Maarten (Dutch part),2016,Tourism expenditure (millions of US dollars),,,871.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +534,Sint Maarten (Dutch part),2017,Tourism expenditure (millions of US dollars),,,646.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +534,Sint Maarten (Dutch part),2018,Tourism expenditure (millions of US dollars),,,468.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +703,Slovakia,1995,Tourist/visitor arrivals (thousands),TCE,,903.0000,Non-resident tourists staying in commercial accommodation only (representing approximately 25% of all tourists).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +703,Slovakia,2005,Tourist/visitor arrivals (thousands),TCE,,1515.0000,Non-resident tourists staying in commercial accommodation only (representing approximately 25% of all tourists).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +703,Slovakia,2010,Tourist/visitor arrivals (thousands),TCE,,1327.0000,Non-resident tourists staying in commercial accommodation only (representing approximately 25% of all tourists).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +703,Slovakia,2016,Tourist/visitor arrivals (thousands),TCE,,2027.0000,Non-resident tourists staying in commercial accommodation only (representing approximately 25% of all tourists).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +703,Slovakia,2017,Tourist/visitor arrivals (thousands),TCE,,2162.0000,Non-resident tourists staying in commercial accommodation only (representing approximately 25% of all tourists).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +703,Slovakia,2018,Tourist/visitor arrivals (thousands),TCE,,2256.0000,Non-resident tourists staying in commercial accommodation only (representing approximately 25% of all tourists).,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +703,Slovakia,1995,Tourism expenditure (millions of US dollars),,,630.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +703,Slovakia,2005,Tourism expenditure (millions of US dollars),,,1282.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +703,Slovakia,2010,Tourism expenditure (millions of US dollars),,,2334.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +703,Slovakia,2016,Tourism expenditure (millions of US dollars),,,2812.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +703,Slovakia,2017,Tourism expenditure (millions of US dollars),,,3024.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +703,Slovakia,2018,Tourism expenditure (millions of US dollars),,,3318.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +705,Slovenia,1995,Tourist/visitor arrivals (thousands),TCE,,732.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +705,Slovenia,2005,Tourist/visitor arrivals (thousands),TCE,,1555.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +705,Slovenia,2010,Tourist/visitor arrivals (thousands),TCE,,2049.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +705,Slovenia,2016,Tourist/visitor arrivals (thousands),TCE,,3397.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +705,Slovenia,2017,Tourist/visitor arrivals (thousands),TCE,,3991.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +705,Slovenia,2018,Tourist/visitor arrivals (thousands),TCE,,4425.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +705,Slovenia,1995,Tourism expenditure (millions of US dollars),,,1128.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +705,Slovenia,2005,Tourism expenditure (millions of US dollars),,,1894.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +705,Slovenia,2010,Tourism expenditure (millions of US dollars),,,2808.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +705,Slovenia,2016,Tourism expenditure (millions of US dollars),,,2717.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +705,Slovenia,2017,Tourism expenditure (millions of US dollars),,,3057.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +705,Slovenia,2018,Tourism expenditure (millions of US dollars),,,3378.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +90,Solomon Islands,1995,Tourist/visitor arrivals (thousands),TF,,11.8000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +90,Solomon Islands,2005,Tourist/visitor arrivals (thousands),TF,,9.4000,Without first quarter.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +90,Solomon Islands,2010,Tourist/visitor arrivals (thousands),TF,,20.5000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +90,Solomon Islands,2016,Tourist/visitor arrivals (thousands),TF,,23.2000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +90,Solomon Islands,2017,Tourist/visitor arrivals (thousands),TF,,25.7000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +90,Solomon Islands,2018,Tourist/visitor arrivals (thousands),TF,,27.9000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +90,Solomon Islands,1995,Tourism expenditure (millions of US dollars),,,17.1000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +90,Solomon Islands,2005,Tourism expenditure (millions of US dollars),,,6.4000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +90,Solomon Islands,2010,Tourism expenditure (millions of US dollars),,,50.8000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +90,Solomon Islands,2016,Tourism expenditure (millions of US dollars),,,71.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +90,Solomon Islands,2017,Tourism expenditure (millions of US dollars),,,79.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +90,Solomon Islands,2018,Tourism expenditure (millions of US dollars),,,92.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +710,South Africa,1995,Tourist/visitor arrivals (thousands),TF,,4488.0000,Excluding arrivals for work and contract workers.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +710,South Africa,2005,Tourist/visitor arrivals (thousands),TF,,7369.0000,Excluding arrivals for work and contract workers.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +710,South Africa,2010,Tourist/visitor arrivals (thousands),TF,,8074.0000,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +710,South Africa,2016,Tourist/visitor arrivals (thousands),TF,,10044.0000,Break in the time series.;Excluding transit.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +710,South Africa,2017,Tourist/visitor arrivals (thousands),TF,,10285.0000,Excluding transit.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +710,South Africa,2018,Tourist/visitor arrivals (thousands),TF,,10472.0000,Excluding transit.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +710,South Africa,1995,Tourism expenditure (millions of US dollars),,,2654.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +710,South Africa,2005,Tourism expenditure (millions of US dollars),,,8629.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +710,South Africa,2010,Tourism expenditure (millions of US dollars),,,10309.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +710,South Africa,2016,Tourism expenditure (millions of US dollars),,,8807.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +710,South Africa,2017,Tourism expenditure (millions of US dollars),,,9706.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +710,South Africa,2018,Tourism expenditure (millions of US dollars),,,9789.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +728,South Sudan,2016,Tourism expenditure (millions of US dollars),,,23.5000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +728,South Sudan,2017,Tourism expenditure (millions of US dollars),,,26.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +728,South Sudan,2018,Tourism expenditure (millions of US dollars),,,12.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +724,Spain,1995,Tourist/visitor arrivals (thousands),TF,,32971.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +724,Spain,2005,Tourist/visitor arrivals (thousands),TF,,55914.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +724,Spain,2010,Tourist/visitor arrivals (thousands),TF,,52677.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +724,Spain,2016,Tourist/visitor arrivals (thousands),TF,,75315.0000,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +724,Spain,2017,Tourist/visitor arrivals (thousands),TF,,81869.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +724,Spain,2018,Tourist/visitor arrivals (thousands),TF,,82773.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +724,Spain,1995,Tourism expenditure (millions of US dollars),,,25368.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +724,Spain,2005,Tourism expenditure (millions of US dollars),,,51959.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +724,Spain,2010,Tourism expenditure (millions of US dollars),,,58348.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +724,Spain,2016,Tourism expenditure (millions of US dollars),,,66982.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +724,Spain,2017,Tourism expenditure (millions of US dollars),,,75906.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +724,Spain,2018,Tourism expenditure (millions of US dollars),,,81250.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +144,Sri Lanka,1995,Tourist/visitor arrivals (thousands),TF,,403.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +144,Sri Lanka,2005,Tourist/visitor arrivals (thousands),TF,,549.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +144,Sri Lanka,2010,Tourist/visitor arrivals (thousands),TF,,654.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +144,Sri Lanka,2016,Tourist/visitor arrivals (thousands),TF,,2051.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +144,Sri Lanka,2017,Tourist/visitor arrivals (thousands),TF,,2116.4000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +144,Sri Lanka,2018,Tourist/visitor arrivals (thousands),TF,,2334.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +144,Sri Lanka,1995,Tourism expenditure (millions of US dollars),,,367.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +144,Sri Lanka,2005,Tourism expenditure (millions of US dollars),,,729.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +144,Sri Lanka,2010,Tourism expenditure (millions of US dollars),,,1044.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +144,Sri Lanka,2016,Tourism expenditure (millions of US dollars),,,4591.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +144,Sri Lanka,2017,Tourism expenditure (millions of US dollars),,,5083.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +144,Sri Lanka,2018,Tourism expenditure (millions of US dollars),,,5608.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +275,State of Palestine,2005,Tourist/visitor arrivals (thousands),THS,,88.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +275,State of Palestine,2010,Tourist/visitor arrivals (thousands),THS,,522.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +275,State of Palestine,2016,Tourist/visitor arrivals (thousands),THS,,400.0000,West Bank only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +275,State of Palestine,2017,Tourist/visitor arrivals (thousands),THS,,503.0000,West Bank only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +275,State of Palestine,2018,Tourist/visitor arrivals (thousands),THS,,606.0000,West Bank only.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +275,State of Palestine,1995,Tourism expenditure (millions of US dollars),,,255.0000,Excluding passenger transport.;West Bank and Gaza.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +275,State of Palestine,2005,Tourism expenditure (millions of US dollars),,,52.0000,Excluding passenger transport.;West Bank and Gaza.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +275,State of Palestine,2010,Tourism expenditure (millions of US dollars),,,409.0000,Excluding passenger transport.;West Bank and Gaza.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +275,State of Palestine,2016,Tourism expenditure (millions of US dollars),,,235.0000,Excluding passenger transport.;West Bank and Gaza.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +275,State of Palestine,2017,Tourism expenditure (millions of US dollars),,,225.0000,Excluding passenger transport.;West Bank and Gaza.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +275,State of Palestine,2018,Tourism expenditure (millions of US dollars),,,245.0000,Excluding passenger transport.;West Bank and Gaza.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +729,Sudan,1995,Tourist/visitor arrivals (thousands),TF,,29.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +729,Sudan,2005,Tourist/visitor arrivals (thousands),TF,,246.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +729,Sudan,2010,Tourist/visitor arrivals (thousands),TF,,495.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +729,Sudan,2016,Tourist/visitor arrivals (thousands),TF,,800.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +729,Sudan,2017,Tourist/visitor arrivals (thousands),TF,,813.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +729,Sudan,2018,Tourist/visitor arrivals (thousands),TF,,836.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +729,Sudan,1995,Tourism expenditure (millions of US dollars),,,8.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +729,Sudan,2005,Tourism expenditure (millions of US dollars),,,114.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +729,Sudan,2010,Tourism expenditure (millions of US dollars),,,82.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +729,Sudan,2016,Tourism expenditure (millions of US dollars),,,1009.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +729,Sudan,2017,Tourism expenditure (millions of US dollars),,,1029.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +729,Sudan,2018,Tourism expenditure (millions of US dollars),,,1043.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +740,Suriname,1995,Tourist/visitor arrivals (thousands),TF,,43.0000,Arrivals at Zanderij Airport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +740,Suriname,2005,Tourist/visitor arrivals (thousands),TF,,161.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +740,Suriname,2010,Tourist/visitor arrivals (thousands),TF,,205.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +740,Suriname,2016,Tourist/visitor arrivals (thousands),TF,,256.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +740,Suriname,2017,Tourist/visitor arrivals (thousands),TF,,278.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +740,Suriname,1995,Tourism expenditure (millions of US dollars),,,52.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +740,Suriname,2005,Tourism expenditure (millions of US dollars),,,96.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +740,Suriname,2010,Tourism expenditure (millions of US dollars),,,69.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +740,Suriname,2016,Tourism expenditure (millions of US dollars),,,74.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +740,Suriname,2017,Tourism expenditure (millions of US dollars),,,61.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +740,Suriname,2018,Tourism expenditure (millions of US dollars),,,73.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +752,Sweden,1995,Tourist/visitor arrivals (thousands),TCE,,2310.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +752,Sweden,2005,Tourist/visitor arrivals (thousands),TCE,,4883.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +752,Sweden,2010,Tourist/visitor arrivals (thousands),TCE,,5183.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +752,Sweden,2016,Tourist/visitor arrivals (thousands),TCE,,6782.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +752,Sweden,2017,Tourist/visitor arrivals (thousands),TCE,,7054.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +752,Sweden,2018,Tourist/visitor arrivals (thousands),TCE,,7440.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +752,Sweden,1995,Tourism expenditure (millions of US dollars),,,3471.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +752,Sweden,2005,Tourism expenditure (millions of US dollars),,,6554.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +752,Sweden,2010,Tourism expenditure (millions of US dollars),,,8336.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +752,Sweden,2016,Tourism expenditure (millions of US dollars),,,12764.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +752,Sweden,2017,Tourism expenditure (millions of US dollars),,,14168.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +752,Sweden,2018,Tourism expenditure (millions of US dollars),,,14926.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +756,Switzerland,1995,Tourist/visitor arrivals (thousands),THS,,6946.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +756,Switzerland,2005,Tourist/visitor arrivals (thousands),THS,,7229.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +756,Switzerland,2010,Tourist/visitor arrivals (thousands),THS,,8628.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +756,Switzerland,2016,Tourist/visitor arrivals (thousands),THS,,9205.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +756,Switzerland,2017,Tourist/visitor arrivals (thousands),THS,,9889.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +756,Switzerland,2018,Tourist/visitor arrivals (thousands),THS,,10362.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +756,Switzerland,1995,Tourism expenditure (millions of US dollars),,,11354.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +756,Switzerland,2005,Tourism expenditure (millions of US dollars),,,11952.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +756,Switzerland,2010,Tourism expenditure (millions of US dollars),,,17614.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +756,Switzerland,2016,Tourism expenditure (millions of US dollars),,,19042.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +756,Switzerland,2017,Tourism expenditure (millions of US dollars),,,19654.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +756,Switzerland,2018,Tourism expenditure (millions of US dollars),,,20276.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +760,Syrian Arab Republic,1995,Tourist/visitor arrivals (thousands),TCE,,815.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +760,Syrian Arab Republic,2005,Tourist/visitor arrivals (thousands),TCE,,3571.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +760,Syrian Arab Republic,2010,Tourist/visitor arrivals (thousands),TCE,,8546.0000,Including nationals residing abroad.;Including Iraqi nationals.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +760,Syrian Arab Republic,2005,Tourism expenditure (millions of US dollars),,,2035.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +760,Syrian Arab Republic,2010,Tourism expenditure (millions of US dollars),,,6308.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +762,Tajikistan,2010,Tourist/visitor arrivals (thousands),VF,,160.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +762,Tajikistan,2016,Tourist/visitor arrivals (thousands),VF,,344.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +762,Tajikistan,2017,Tourist/visitor arrivals (thousands),VF,,431.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +762,Tajikistan,2018,Tourist/visitor arrivals (thousands),VF,,1035.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +762,Tajikistan,2005,Tourism expenditure (millions of US dollars),,,9.1000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +762,Tajikistan,2010,Tourism expenditure (millions of US dollars),,,141.5000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +762,Tajikistan,2016,Tourism expenditure (millions of US dollars),,,149.6000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +762,Tajikistan,2017,Tourism expenditure (millions of US dollars),,,171.6000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +762,Tajikistan,2018,Tourism expenditure (millions of US dollars),,,170.9000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +764,Thailand,1995,Tourist/visitor arrivals (thousands),TF,,6952.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +764,Thailand,2005,Tourist/visitor arrivals (thousands),TF,,11567.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +764,Thailand,2010,Tourist/visitor arrivals (thousands),TF,,15936.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +764,Thailand,2016,Tourist/visitor arrivals (thousands),TF,,32530.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +764,Thailand,2017,Tourist/visitor arrivals (thousands),TF,,35592.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +764,Thailand,2018,Tourist/visitor arrivals (thousands),TF,,38178.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +764,Thailand,1995,Tourism expenditure (millions of US dollars),,,9257.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +764,Thailand,2005,Tourism expenditure (millions of US dollars),,,12103.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +764,Thailand,2010,Tourism expenditure (millions of US dollars),,,23796.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +764,Thailand,2016,Tourism expenditure (millions of US dollars),,,48459.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +764,Thailand,2017,Tourism expenditure (millions of US dollars),,,57057.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +764,Thailand,2018,Tourism expenditure (millions of US dollars),,,65242.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +626,Timor-Leste,2010,Tourist/visitor arrivals (thousands),TF,,40.0000,Arrivals by air at Dili Airport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +626,Timor-Leste,2016,Tourist/visitor arrivals (thousands),TF,,66.0000,Arrivals by air at Dili Airport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +626,Timor-Leste,2017,Tourist/visitor arrivals (thousands),TF,,74.0000,Arrivals by air at Dili Airport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +626,Timor-Leste,2018,Tourist/visitor arrivals (thousands),TF,,75.0000,Arrivals by air at Dili Airport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +626,Timor-Leste,2010,Tourism expenditure (millions of US dollars),,,24.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +626,Timor-Leste,2016,Tourism expenditure (millions of US dollars),,,58.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +626,Timor-Leste,2017,Tourism expenditure (millions of US dollars),,,73.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +626,Timor-Leste,2018,Tourism expenditure (millions of US dollars),,,78.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +768,Togo,1995,Tourist/visitor arrivals (thousands),THS,,53.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +768,Togo,2005,Tourist/visitor arrivals (thousands),THS,,81.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +768,Togo,2010,Tourist/visitor arrivals (thousands),THS,,202.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +768,Togo,2016,Tourist/visitor arrivals (thousands),THS,,338.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +768,Togo,2017,Tourist/visitor arrivals (thousands),THS,,514.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +768,Togo,2018,Tourist/visitor arrivals (thousands),THS,,573.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +768,Togo,2005,Tourism expenditure (millions of US dollars),,,27.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +768,Togo,2010,Tourism expenditure (millions of US dollars),,,105.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +768,Togo,2016,Tourism expenditure (millions of US dollars),,,223.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +768,Togo,2017,Tourism expenditure (millions of US dollars),,,245.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +776,Tonga,1995,Tourist/visitor arrivals (thousands),TF,,29.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +776,Tonga,2005,Tourist/visitor arrivals (thousands),TF,,42.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +776,Tonga,2010,Tourist/visitor arrivals (thousands),TF,,47.1000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +776,Tonga,2016,Tourist/visitor arrivals (thousands),TF,,59.1000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +776,Tonga,2017,Tourist/visitor arrivals (thousands),TF,,62.5000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +776,Tonga,2018,Tourist/visitor arrivals (thousands),TF,,54.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +776,Tonga,2005,Tourism expenditure (millions of US dollars),,,15.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +776,Tonga,2010,Tourism expenditure (millions of US dollars),,,17.3000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +776,Tonga,2016,Tourism expenditure (millions of US dollars),,,52.7000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +776,Tonga,2017,Tourism expenditure (millions of US dollars),,,48.5000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +776,Tonga,2018,Tourism expenditure (millions of US dollars),,,48.1000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +780,Trinidad and Tobago,1995,Tourist/visitor arrivals (thousands),TF,,260.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +780,Trinidad and Tobago,2005,Tourist/visitor arrivals (thousands),TF,,463.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +780,Trinidad and Tobago,2010,Tourist/visitor arrivals (thousands),TF,,388.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +780,Trinidad and Tobago,2016,Tourist/visitor arrivals (thousands),TF,,409.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +780,Trinidad and Tobago,2017,Tourist/visitor arrivals (thousands),TF,,395.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +780,Trinidad and Tobago,2018,Tourist/visitor arrivals (thousands),TF,,375.0000,Arrivals by air.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +780,Trinidad and Tobago,1995,Tourism expenditure (millions of US dollars),,,232.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +780,Trinidad and Tobago,2005,Tourism expenditure (millions of US dollars),,,593.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +780,Trinidad and Tobago,2010,Tourism expenditure (millions of US dollars),,,630.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +780,Trinidad and Tobago,2016,Tourism expenditure (millions of US dollars),,,708.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +780,Trinidad and Tobago,2017,Tourism expenditure (millions of US dollars),,,717.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +780,Trinidad and Tobago,2018,Tourism expenditure (millions of US dollars),,,541.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +788,Tunisia,1995,Tourist/visitor arrivals (thousands),TF,,4120.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +788,Tunisia,2005,Tourist/visitor arrivals (thousands),TF,,6378.0000,Excluding nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +788,Tunisia,2010,Tourist/visitor arrivals (thousands),TF,,7828.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +788,Tunisia,2016,Tourist/visitor arrivals (thousands),TF,,5724.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +788,Tunisia,2017,Tourist/visitor arrivals (thousands),TF,,7052.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +788,Tunisia,2018,Tourist/visitor arrivals (thousands),TF,,8299.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +788,Tunisia,1995,Tourism expenditure (millions of US dollars),,,1838.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +788,Tunisia,2005,Tourism expenditure (millions of US dollars),,,2800.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +788,Tunisia,2010,Tourism expenditure (millions of US dollars),,,3477.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +788,Tunisia,2016,Tourism expenditure (millions of US dollars),,,1706.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +788,Tunisia,2017,Tourism expenditure (millions of US dollars),,,1782.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +788,Tunisia,2018,Tourism expenditure (millions of US dollars),,,2320.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +792,Turkey,1995,Tourist/visitor arrivals (thousands),TF,,7083.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +792,Turkey,2005,Tourist/visitor arrivals (thousands),TF,,20273.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +792,Turkey,2010,Tourist/visitor arrivals (thousands),TF,,31364.0000,Turkish citizens resident abroad are included.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +792,Turkey,2016,Tourist/visitor arrivals (thousands),TF,,30289.0000,Turkish citizens resident abroad are included.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +792,Turkey,2017,Tourist/visitor arrivals (thousands),TF,,37601.0000,Turkish citizens resident abroad are included.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +792,Turkey,2018,Tourist/visitor arrivals (thousands),TF,,45768.0000,Turkish citizens resident abroad are included.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +792,Turkey,2005,Tourism expenditure (millions of US dollars),,,20760.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +792,Turkey,2010,Tourism expenditure (millions of US dollars),,,26318.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +792,Turkey,2016,Tourism expenditure (millions of US dollars),,,26788.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +792,Turkey,2017,Tourism expenditure (millions of US dollars),,,31870.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +792,Turkey,2018,Tourism expenditure (millions of US dollars),,,37140.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +795,Turkmenistan,1995,Tourist/visitor arrivals (thousands),TF,,218.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +795,Turkmenistan,2005,Tourist/visitor arrivals (thousands),TF,,11.6000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +796,Turks and Caicos Islands,1995,Tourist/visitor arrivals (thousands),TF,,79.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +796,Turks and Caicos Islands,2005,Tourist/visitor arrivals (thousands),TF,,176.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +796,Turks and Caicos Islands,2010,Tourist/visitor arrivals (thousands),TF,,281.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +796,Turks and Caicos Islands,2016,Tourist/visitor arrivals (thousands),TF,,449.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +796,Turks and Caicos Islands,2017,Tourist/visitor arrivals (thousands),TF,,416.4000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +796,Turks and Caicos Islands,2018,Tourist/visitor arrivals (thousands),TF,,441.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +796,Turks and Caicos Islands,1995,Tourism expenditure (millions of US dollars),,,53.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +798,Tuvalu,1995,Tourist/visitor arrivals (thousands),TF,,0.9000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +798,Tuvalu,2005,Tourist/visitor arrivals (thousands),TF,,1.1000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +798,Tuvalu,2010,Tourist/visitor arrivals (thousands),TF,,1.7000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +798,Tuvalu,2016,Tourist/visitor arrivals (thousands),TF,,2.5000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +798,Tuvalu,2017,Tourist/visitor arrivals (thousands),TF,,2.5000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +798,Tuvalu,2018,Tourist/visitor arrivals (thousands),TF,,2.7000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +798,Tuvalu,2005,Tourism expenditure (millions of US dollars),,,1.2000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +798,Tuvalu,2010,Tourism expenditure (millions of US dollars),,,2.4000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +800,Uganda,1995,Tourist/visitor arrivals (thousands),TF,,160.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +800,Uganda,2005,Tourist/visitor arrivals (thousands),TF,,468.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +800,Uganda,2010,Tourist/visitor arrivals (thousands),TF,,946.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +800,Uganda,2016,Tourist/visitor arrivals (thousands),TF,,1323.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +800,Uganda,2017,Tourist/visitor arrivals (thousands),TF,,1402.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +800,Uganda,2005,Tourism expenditure (millions of US dollars),,,382.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +800,Uganda,2010,Tourism expenditure (millions of US dollars),,,802.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +800,Uganda,2016,Tourism expenditure (millions of US dollars),,,1118.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +800,Uganda,2017,Tourism expenditure (millions of US dollars),,,957.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +800,Uganda,2018,Tourism expenditure (millions of US dollars),,,1044.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +804,Ukraine,1995,Tourist/visitor arrivals (thousands),TF,,3716.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +804,Ukraine,2005,Tourist/visitor arrivals (thousands),TF,,17631.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +804,Ukraine,2010,Tourist/visitor arrivals (thousands),TF,,21203.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +804,Ukraine,2016,Tourist/visitor arrivals (thousands),TF,,13333.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +804,Ukraine,2017,Tourist/visitor arrivals (thousands),TF,,14230.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +804,Ukraine,2018,Tourist/visitor arrivals (thousands),TF,,14104.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +804,Ukraine,2005,Tourism expenditure (millions of US dollars),,,3542.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +804,Ukraine,2010,Tourism expenditure (millions of US dollars),,,4696.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +804,Ukraine,2016,Tourism expenditure (millions of US dollars),,,1723.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +804,Ukraine,2017,Tourism expenditure (millions of US dollars),,,2019.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +804,Ukraine,2018,Tourism expenditure (millions of US dollars),,,2269.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +784,United Arab Emirates,1995,Tourist/visitor arrivals (thousands),THS,,2315.0000,Arrivals in hotels only. Including domestic tourism and nationals of the country residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +784,United Arab Emirates,2005,Tourist/visitor arrivals (thousands),THS,,7126.0000,Arrivals in hotels only. Including domestic tourism and nationals of the country residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +784,United Arab Emirates,2016,Tourist/visitor arrivals (thousands),THS,,18967.0000,Arrivals in hotels only. Including domestic tourism and nationals of the country residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +784,United Arab Emirates,2017,Tourist/visitor arrivals (thousands),THS,,20394.0000,Arrivals in hotels only. Including domestic tourism and nationals of the country residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +784,United Arab Emirates,2018,Tourist/visitor arrivals (thousands),THS,,21286.0000,Arrivals in hotels only. Including domestic tourism and nationals of the country residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +784,United Arab Emirates,1995,Tourism expenditure (millions of US dollars),,,632.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +784,United Arab Emirates,2005,Tourism expenditure (millions of US dollars),,,3218.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +784,United Arab Emirates,2010,Tourism expenditure (millions of US dollars),,,8577.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +784,United Arab Emirates,2016,Tourism expenditure (millions of US dollars),,,19496.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +784,United Arab Emirates,2017,Tourism expenditure (millions of US dollars),,,21048.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +784,United Arab Emirates,2018,Tourism expenditure (millions of US dollars),,,21390.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +826,United Kingdom,1995,Tourist/visitor arrivals (thousands),TF,,21719.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +826,United Kingdom,2005,Tourist/visitor arrivals (thousands),TF,,28039.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +826,United Kingdom,2010,Tourist/visitor arrivals (thousands),TF,,28295.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +826,United Kingdom,2016,Tourist/visitor arrivals (thousands),TF,,35814.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +826,United Kingdom,2017,Tourist/visitor arrivals (thousands),TF,,37651.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +826,United Kingdom,2018,Tourist/visitor arrivals (thousands),TF,,36316.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +826,United Kingdom,1995,Tourism expenditure (millions of US dollars),,,27577.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +826,United Kingdom,2005,Tourism expenditure (millions of US dollars),,,32948.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +826,United Kingdom,2010,Tourism expenditure (millions of US dollars),,,34715.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +826,United Kingdom,2016,Tourism expenditure (millions of US dollars),,,47777.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +826,United Kingdom,2017,Tourism expenditure (millions of US dollars),,,47719.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +826,United Kingdom,2018,Tourism expenditure (millions of US dollars),,,48515.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +834,United Rep. of Tanzania,1995,Tourist/visitor arrivals (thousands),TF,,285.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +834,United Rep. of Tanzania,2005,Tourist/visitor arrivals (thousands),TF,,590.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +834,United Rep. of Tanzania,2010,Tourist/visitor arrivals (thousands),TF,,754.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +834,United Rep. of Tanzania,2016,Tourist/visitor arrivals (thousands),TF,,1233.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +834,United Rep. of Tanzania,2017,Tourist/visitor arrivals (thousands),TF,,1275.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +834,United Rep. of Tanzania,2018,Tourist/visitor arrivals (thousands),TF,,1378.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +834,United Rep. of Tanzania,2005,Tourism expenditure (millions of US dollars),,,835.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +834,United Rep. of Tanzania,2010,Tourism expenditure (millions of US dollars),,,1279.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +834,United Rep. of Tanzania,2016,Tourism expenditure (millions of US dollars),,,2149.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +834,United Rep. of Tanzania,2017,Tourism expenditure (millions of US dollars),,,2265.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +834,United Rep. of Tanzania,2018,Tourism expenditure (millions of US dollars),,,2465.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +840,United States of America,1995,Tourist/visitor arrivals (thousands),TF,,43318.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +840,United States of America,2005,Tourist/visitor arrivals (thousands),TF,,49206.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +840,United States of America,2010,Tourist/visitor arrivals (thousands),TF,,60010.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +840,United States of America,2016,Tourist/visitor arrivals (thousands),TF,,76407.4880,Break in the time series.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +840,United States of America,2017,Tourist/visitor arrivals (thousands),TF,,77186.7460,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +840,United States of America,2018,Tourist/visitor arrivals (thousands),TF,,79745.9180,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +840,United States of America,1995,Tourism expenditure (millions of US dollars),,,93743.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +840,United States of America,2005,Tourism expenditure (millions of US dollars),,,122077.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +840,United States of America,2010,Tourism expenditure (millions of US dollars),,,167996.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +840,United States of America,2016,Tourism expenditure (millions of US dollars),,,245991.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +840,United States of America,2017,Tourism expenditure (millions of US dollars),,,251544.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +840,United States of America,2018,Tourism expenditure (millions of US dollars),,,256145.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +850,United States Virgin Islands,1995,Tourist/visitor arrivals (thousands),TF,,454.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +850,United States Virgin Islands,2005,Tourist/visitor arrivals (thousands),TF,,594.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +850,United States Virgin Islands,2010,Tourist/visitor arrivals (thousands),TF,,572.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +850,United States Virgin Islands,2016,Tourist/visitor arrivals (thousands),TF,,667.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +850,United States Virgin Islands,2017,Tourist/visitor arrivals (thousands),TF,,535.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +850,United States Virgin Islands,2018,Tourist/visitor arrivals (thousands),TF,,381.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +850,United States Virgin Islands,1995,Tourism expenditure (millions of US dollars),,,822.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +850,United States Virgin Islands,2005,Tourism expenditure (millions of US dollars),,,1432.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +850,United States Virgin Islands,2010,Tourism expenditure (millions of US dollars),,,1223.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +850,United States Virgin Islands,2016,Tourism expenditure (millions of US dollars),,,1343.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +850,United States Virgin Islands,2017,Tourism expenditure (millions of US dollars),,,1202.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +850,United States Virgin Islands,2018,Tourism expenditure (millions of US dollars),,,1046.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +858,Uruguay,1995,Tourist/visitor arrivals (thousands),TF,,2022.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +858,Uruguay,2005,Tourist/visitor arrivals (thousands),TF,,1808.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +858,Uruguay,2010,Tourist/visitor arrivals (thousands),TF,,2353.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +858,Uruguay,2016,Tourist/visitor arrivals (thousands),TF,,3037.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +858,Uruguay,2017,Tourist/visitor arrivals (thousands),TF,,3674.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +858,Uruguay,2018,Tourist/visitor arrivals (thousands),TF,,3469.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +858,Uruguay,1995,Tourism expenditure (millions of US dollars),,,725.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +858,Uruguay,2005,Tourism expenditure (millions of US dollars),,,699.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +858,Uruguay,2010,Tourism expenditure (millions of US dollars),,,1669.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +858,Uruguay,2016,Tourism expenditure (millions of US dollars),,,2182.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +858,Uruguay,2017,Tourism expenditure (millions of US dollars),,,2660.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +858,Uruguay,2018,Tourism expenditure (millions of US dollars),,,2439.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +860,Uzbekistan,1995,Tourist/visitor arrivals (thousands),TF,,92.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +860,Uzbekistan,2005,Tourist/visitor arrivals (thousands),TF,,242.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +860,Uzbekistan,2010,Tourist/visitor arrivals (thousands),TF,,975.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +860,Uzbekistan,2016,Tourist/visitor arrivals (thousands),TF,,2027.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +860,Uzbekistan,2017,Tourist/visitor arrivals (thousands),TF,,2690.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +860,Uzbekistan,2018,Tourist/visitor arrivals (thousands),TF,,5346.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +860,Uzbekistan,2005,Tourism expenditure (millions of US dollars),,,28.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +860,Uzbekistan,2010,Tourism expenditure (millions of US dollars),,,121.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +860,Uzbekistan,2016,Tourism expenditure (millions of US dollars),,,458.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +860,Uzbekistan,2017,Tourism expenditure (millions of US dollars),,,689.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +860,Uzbekistan,2018,Tourism expenditure (millions of US dollars),,,1144.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +548,Vanuatu,1995,Tourist/visitor arrivals (thousands),TF,,44.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +548,Vanuatu,2005,Tourist/visitor arrivals (thousands),TF,,62.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +548,Vanuatu,2010,Tourist/visitor arrivals (thousands),TF,,97.2000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +548,Vanuatu,2016,Tourist/visitor arrivals (thousands),TF,,95.1000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +548,Vanuatu,2017,Tourist/visitor arrivals (thousands),TF,,109.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +548,Vanuatu,2018,Tourist/visitor arrivals (thousands),TF,,116.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +548,Vanuatu,2005,Tourism expenditure (millions of US dollars),,,104.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +548,Vanuatu,2010,Tourism expenditure (millions of US dollars),,,242.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +548,Vanuatu,2016,Tourism expenditure (millions of US dollars),,,275.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +548,Vanuatu,2017,Tourism expenditure (millions of US dollars),,,289.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +548,Vanuatu,2018,Tourism expenditure (millions of US dollars),,,325.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +862,Venezuela (Boliv. Rep. of),1995,Tourist/visitor arrivals (thousands),TF,,700.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +862,Venezuela (Boliv. Rep. of),2005,Tourist/visitor arrivals (thousands),TF,,706.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +862,Venezuela (Boliv. Rep. of),2010,Tourist/visitor arrivals (thousands),TF,,526.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +862,Venezuela (Boliv. Rep. of),2016,Tourist/visitor arrivals (thousands),TF,,601.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +862,Venezuela (Boliv. Rep. of),2017,Tourist/visitor arrivals (thousands),TF,,427.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +862,Venezuela (Boliv. Rep. of),1995,Tourism expenditure (millions of US dollars),,,995.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +862,Venezuela (Boliv. Rep. of),2005,Tourism expenditure (millions of US dollars),,,722.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +862,Venezuela (Boliv. Rep. of),2010,Tourism expenditure (millions of US dollars),,,885.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +862,Venezuela (Boliv. Rep. of),2016,Tourism expenditure (millions of US dollars),,,546.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +704,Viet Nam,1995,Tourist/visitor arrivals (thousands),VF,,1351.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +704,Viet Nam,2005,Tourist/visitor arrivals (thousands),VF,,3477.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +704,Viet Nam,2010,Tourist/visitor arrivals (thousands),VF,,5050.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +704,Viet Nam,2016,Tourist/visitor arrivals (thousands),VF,,10013.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +704,Viet Nam,2017,Tourist/visitor arrivals (thousands),VF,,12922.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +704,Viet Nam,2018,Tourist/visitor arrivals (thousands),VF,,15498.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +704,Viet Nam,2005,Tourism expenditure (millions of US dollars),,,2300.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +704,Viet Nam,2010,Tourism expenditure (millions of US dollars),,,4450.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +704,Viet Nam,2016,Tourism expenditure (millions of US dollars),,,8500.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +704,Viet Nam,2017,Tourism expenditure (millions of US dollars),,,8890.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +704,Viet Nam,2018,Tourism expenditure (millions of US dollars),,,10080.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +887,Yemen,1995,Tourist/visitor arrivals (thousands),TF,,61.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +887,Yemen,2005,Tourist/visitor arrivals (thousands),TF,,336.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +887,Yemen,2010,Tourist/visitor arrivals (thousands),TF,,1025.0000,Including nationals residing abroad.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +887,Yemen,2010,Tourism expenditure (millions of US dollars),,,1291.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +887,Yemen,2016,Tourism expenditure (millions of US dollars),,,116.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +894,Zambia,1995,Tourist/visitor arrivals (thousands),TF,,163.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +894,Zambia,2005,Tourist/visitor arrivals (thousands),TF,,669.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +894,Zambia,2010,Tourist/visitor arrivals (thousands),TF,,815.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +894,Zambia,2016,Tourist/visitor arrivals (thousands),TF,,956.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +894,Zambia,2017,Tourist/visitor arrivals (thousands),TF,,1083.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +894,Zambia,2018,Tourist/visitor arrivals (thousands),TF,,1072.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +894,Zambia,2005,Tourism expenditure (millions of US dollars),,,447.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +894,Zambia,2010,Tourism expenditure (millions of US dollars),,,492.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +894,Zambia,2016,Tourism expenditure (millions of US dollars),,,683.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +894,Zambia,2017,Tourism expenditure (millions of US dollars),,,653.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +894,Zambia,2018,Tourism expenditure (millions of US dollars),,,742.0000,Excluding passenger transport.,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +716,Zimbabwe,1995,Tourist/visitor arrivals (thousands),VF,,1416.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +716,Zimbabwe,2005,Tourist/visitor arrivals (thousands),VF,,1559.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +716,Zimbabwe,2010,Tourist/visitor arrivals (thousands),VF,,2239.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +716,Zimbabwe,2016,Tourist/visitor arrivals (thousands),VF,,2168.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +716,Zimbabwe,2017,Tourist/visitor arrivals (thousands),VF,,2423.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +716,Zimbabwe,2018,Tourist/visitor arrivals (thousands),VF,,2580.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +716,Zimbabwe,1995,Tourism expenditure (millions of US dollars),,,145.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +716,Zimbabwe,2005,Tourism expenditure (millions of US dollars),,,99.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +716,Zimbabwe,2010,Tourism expenditure (millions of US dollars),,,135.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +716,Zimbabwe,2016,Tourism expenditure (millions of US dollars),,,194.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." +716,Zimbabwe,2017,Tourism expenditure (millions of US dollars),,,158.0000,,"World Tourism Organization (UNWTO), Madrid, the UNWTO Statistics Database, last accessed January 2020." diff --git a/apache-spark/src/main/java/com/baeldung/differences/dataframe/dataset/rdd/TouristData.java b/apache-spark/src/main/java/com/baeldung/differences/dataframe/dataset/rdd/TouristData.java new file mode 100644 index 0000000000..fbeef4283a --- /dev/null +++ b/apache-spark/src/main/java/com/baeldung/differences/dataframe/dataset/rdd/TouristData.java @@ -0,0 +1,75 @@ +package com.baeldung.differences.dataframe.dataset.rdd; + + +public class TouristData { + + private String region; + private String country; + private String year; + private String series; + private Double value; + private String footnotes; + private String source; + + public String getRegion() { + return region; + } + + public void setRegion(String region) { + this.region = region; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getYear() { + return year; + } + + public void setYear(String year) { + this.year = year; + } + + public String getSeries() { + return series; + } + + public void setSeries(String series) { + this.series = series; + } + + public Double getValue() { + return value; + } + + public void setValue(Double value) { + this.value = value; + } + + public String getFootnotes() { + return footnotes; + } + + public void setFootnotes(String footnotes) { + this.footnotes = footnotes; + } + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + @Override + public String toString() { + return "TouristData [region=" + region + ", country=" + country + ", year=" + year + ", series=" + series + ", value=" + value + ", footnotes=" + footnotes + ", source=" + source + "]"; + } + +} diff --git a/apache-spark/src/test/java/com/baeldung/differences/rdd/ActionsUnitTest.java b/apache-spark/src/test/java/com/baeldung/differences/rdd/ActionsUnitTest.java new file mode 100644 index 0000000000..a3e1811e6f --- /dev/null +++ b/apache-spark/src/test/java/com/baeldung/differences/rdd/ActionsUnitTest.java @@ -0,0 +1,67 @@ +package com.baeldung.differences.rdd; + +import static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.apache.spark.SparkConf; +import org.apache.spark.api.java.JavaPairRDD; +import org.apache.spark.api.java.JavaRDD; +import org.apache.spark.api.java.JavaSparkContext; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import scala.Tuple2; + +public class ActionsUnitTest { + private static JavaRDD tourists; + private static JavaSparkContext sc; + public static final String COMMA_DELIMITER = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)"; + + @BeforeClass + public static void init() { + SparkConf conf = new SparkConf().setAppName("reduce") + .setMaster("local[*]"); + sc = new JavaSparkContext(conf); + tourists = sc.textFile("data/Tourist.csv").filter(line -> !line.startsWith("Region")); + } + + @AfterClass + public static void cleanup() { + sc.close(); + } + + @Test + public void whenDistinctCount_thenReturnDistinctNumRecords() { + JavaRDD countries = tourists.map(line -> { + String[] columns = line.split(COMMA_DELIMITER); + return columns[1]; + }) + .distinct(); + Long numberOfCountries = countries.count(); + System.out.println("Count: " + numberOfCountries); + + assertEquals(Long.valueOf(220), numberOfCountries); + } + + @Test + public void whenReduceByKeySum_thenTotalValuePerKey() { + JavaRDD touristsExpenditure = tourists.filter(line -> line.split(COMMA_DELIMITER)[3].contains("expenditure")); + + JavaPairRDD expenditurePairRdd = touristsExpenditure.mapToPair(line -> { + String[] columns = line.split(COMMA_DELIMITER); + return new Tuple2<>(columns[1], Double.valueOf(columns[6])); + }); + List> totalByCountry = expenditurePairRdd.reduceByKey((x, y) -> x + y) + .collect(); + System.out.println("Total per Country: " + totalByCountry); + + for(Tuple2 tuple : totalByCountry) { + if (tuple._1.equals("Mexico")) { + assertEquals(Double.valueOf(99164), tuple._2); + } + } + } + +} diff --git a/apache-spark/src/test/java/com/baeldung/differences/rdd/DataFrameUnitTest.java b/apache-spark/src/test/java/com/baeldung/differences/rdd/DataFrameUnitTest.java new file mode 100644 index 0000000000..f294e5bc66 --- /dev/null +++ b/apache-spark/src/test/java/com/baeldung/differences/rdd/DataFrameUnitTest.java @@ -0,0 +1,74 @@ +package com.baeldung.differences.rdd; + +import static org.apache.spark.sql.functions.col; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.List; + +import org.apache.spark.sql.DataFrameReader; +import org.apache.spark.sql.Dataset; +import org.apache.spark.sql.Row; +import org.apache.spark.sql.SparkSession; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class DataFrameUnitTest { + private static SparkSession session; + private static Dataset data; + + @BeforeClass + public static void init() { + session = SparkSession.builder() + .appName("TouristDataFrameExample") + .master("local[*]") + .getOrCreate(); + DataFrameReader dataFrameReader = session.read(); + data = dataFrameReader.option("header", "true") + .csv("data/Tourist.csv"); + } + + @AfterClass + public static void cleanup() { + session.stop(); + } + + @Test + public void whenSelectSpecificColumns_thenColumnsFiltered() { + Dataset selectedData = data.select(col("country"), col("year"), col("value")); + selectedData.show(); + + List resultList = Arrays.asList(selectedData.columns()); + assertTrue(resultList.contains("country")); + assertTrue(resultList.contains("year")); + assertTrue(resultList.contains("value")); + assertFalse(resultList.contains("Series")); + + } + + @Test + public void whenFilteringByCountry_thenCountryRecordsSelected() { + Dataset filteredData = data.filter(col("country").equalTo("Mexico")); + filteredData.show(); + + filteredData.foreach(record -> { + assertEquals("Mexico", record.get(1)); + }); + + } + + @Test + public void whenGroupCountByCountry_thenContryTotalRecords() { + Dataset recordsPerCountry = data.groupBy(col("country")) + .count(); + recordsPerCountry.show(); + + Dataset filteredData = recordsPerCountry.filter(col("country").equalTo("Sweden")); + assertEquals(new Long(12), filteredData.first() + .get(1)); + } + +} diff --git a/apache-spark/src/test/java/com/baeldung/differences/rdd/DatasetUnitTest.java b/apache-spark/src/test/java/com/baeldung/differences/rdd/DatasetUnitTest.java new file mode 100644 index 0000000000..1d83505812 --- /dev/null +++ b/apache-spark/src/test/java/com/baeldung/differences/rdd/DatasetUnitTest.java @@ -0,0 +1,83 @@ +package com.baeldung.differences.rdd; + +import static org.apache.spark.sql.functions.col; +import static org.apache.spark.sql.functions.sum; +import static org.junit.Assert.assertEquals; + +import org.apache.spark.api.java.function.FilterFunction; +import org.apache.spark.sql.DataFrameReader; +import org.apache.spark.sql.Dataset; +import org.apache.spark.sql.Encoders; +import org.apache.spark.sql.Row; +import org.apache.spark.sql.SparkSession; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.baeldung.differences.dataframe.dataset.rdd.TouristData; + +public class DatasetUnitTest { + private static SparkSession session; + private static Dataset typedDataset; + + @BeforeClass + public static void init() { + session = SparkSession.builder() + .appName("TouristDatasetExample") + .master("local[*]") + .getOrCreate(); + DataFrameReader dataFrameReader = session.read(); + Dataset data = dataFrameReader.option("header", "true") + .csv("data/Tourist.csv"); + Dataset responseWithSelectedColumns = data.select(col("region"), + col("country"), col("year"), col("series"), col("value").cast("double"), + col("footnotes"), col("source")); + typedDataset = responseWithSelectedColumns.as(Encoders.bean(TouristData.class)); + } + + @AfterClass + public static void cleanup() { + session.stop(); + } + + @Test + public void whenFilteringByCountry_thenCountryRecordsSelected() { + Dataset selectedData = typedDataset + .filter((FilterFunction) record -> record.getCountry() + .equals("Norway")); + selectedData.show(); + + selectedData.foreach(record -> { + assertEquals("Norway", record.getCountry()); + }); + } + + @Test + public void whenGroupCountByCountry_thenContryTotalRecords() { + Dataset countriesCount = typedDataset.groupBy(typedDataset.col("country")) + .count(); + countriesCount.show(); + + assertEquals(Long.valueOf(220), Long.valueOf(countriesCount.count())); + } + + @Test + public void whenFilteredByPropertyRange_thenRetreiveValidRecords() { + // Filter records with existing data for years between 2010 and 2017 + typedDataset.filter((FilterFunction) record -> record.getYear() != null + && (Long.valueOf(record.getYear()) > 2010 && Long.valueOf(record.getYear()) < 2017)) + .show(); + } + + @Test + public void whenSumValue_thenRetreiveTotalValue() { + // Total tourist expenditure by country + typedDataset.filter((FilterFunction) record -> record.getValue() != null + && record.getSeries() + .contains("expenditure")) + .groupBy("country") + .agg(sum("value")) + .show(); + } + +} diff --git a/apache-spark/src/test/java/com/baeldung/differences/rdd/TransformationsUnitTest.java b/apache-spark/src/test/java/com/baeldung/differences/rdd/TransformationsUnitTest.java new file mode 100644 index 0000000000..4b2d9e1127 --- /dev/null +++ b/apache-spark/src/test/java/com/baeldung/differences/rdd/TransformationsUnitTest.java @@ -0,0 +1,63 @@ +package com.baeldung.differences.rdd; + + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.apache.commons.lang3.StringUtils; +import org.apache.spark.SparkConf; +import org.apache.spark.api.java.JavaRDD; +import org.apache.spark.api.java.JavaSparkContext; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TransformationsUnitTest { + + public static final String COMMA_DELIMITER = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)"; + private static JavaSparkContext sc; + private static JavaRDD tourists; + + @BeforeClass + public static void init() { + SparkConf conf = new SparkConf().setAppName("uppercaseCountries") + .setMaster("local[*]"); + sc = new JavaSparkContext(conf); + tourists = sc.textFile("data/Tourist.csv") + .filter(line -> !line.startsWith("Region")); //filter header row + } + + @AfterClass + public static void cleanup() { + sc.close(); + } + + @Test + public void whenMapUpperCase_thenCountryNameUppercased() { + JavaRDD upperCaseCountries = tourists.map(line -> { + String[] columns = line.split(COMMA_DELIMITER); + return columns[1].toUpperCase(); + }) + .distinct(); + + upperCaseCountries.saveAsTextFile("data/output/uppercase.txt"); + + upperCaseCountries.foreach(country -> { + //replace non alphanumerical characters + country = country.replaceAll("[^a-zA-Z]", ""); + assertTrue(StringUtils.isAllUpperCase(country)); + }); + } + + @Test + public void whenFilterByCountry_thenShowRequestedCountryRecords() { + JavaRDD touristsInMexico = tourists.filter(line -> line.split(COMMA_DELIMITER)[1].equals("Mexico")); + + touristsInMexico.saveAsTextFile("data/output/touristInMexico.txt"); + + touristsInMexico.foreach(record -> { + assertEquals("Mexico", record.split(COMMA_DELIMITER)[1]); + }); + } + +} diff --git a/atomikos/pom.xml b/atomikos/pom.xml index d680a3ca77..8918de7b77 100644 --- a/atomikos/pom.xml +++ b/atomikos/pom.xml @@ -51,7 +51,7 @@ org.hibernate - hibernate-entitymanager + hibernate-core ${hibernate.version} provided diff --git a/aws-lambda/lambda/pom.xml b/aws-lambda/lambda/pom.xml index 2d903aabc5..1f446e04c0 100644 --- a/aws-lambda/lambda/pom.xml +++ b/aws-lambda/lambda/pom.xml @@ -89,7 +89,6 @@ 1.1.1 - 2.5 1.3.0 1.2.0 2.8.2 diff --git a/aws-lambda/shipping-tracker/ShippingFunction/src/main/java/com/baeldung/lambda/shipping/App.java b/aws-lambda/shipping-tracker/ShippingFunction/src/main/java/com/baeldung/lambda/shipping/App.java index 719725598c..95fd058667 100644 --- a/aws-lambda/shipping-tracker/ShippingFunction/src/main/java/com/baeldung/lambda/shipping/App.java +++ b/aws-lambda/shipping-tracker/ShippingFunction/src/main/java/com/baeldung/lambda/shipping/App.java @@ -6,10 +6,12 @@ import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.zaxxer.hikari.HikariDataSource; import org.hibernate.SessionFactory; import org.hibernate.boot.MetadataSources; import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; import java.util.HashMap; import java.util.Map; @@ -22,11 +24,14 @@ import static org.hibernate.cfg.AvailableSettings.PASS; */ public class App implements RequestHandler { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private SessionFactory sessionFactory = createSessionFactory(); public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) { - try (SessionFactory sessionFactory = createSessionFactory()) { + try { ShippingService service = new ShippingService(sessionFactory, new ShippingDao()); return routeRequest(input, service); + } finally { + flushConnectionPool(); } } @@ -105,4 +110,12 @@ private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); .buildMetadata() .buildSessionFactory(); } + + private void flushConnectionPool() { + ConnectionProvider connectionProvider = sessionFactory.getSessionFactoryOptions() + .getServiceRegistry() + .getService(ConnectionProvider.class); + HikariDataSource hikariDataSource = connectionProvider.unwrap(HikariDataSource.class); + hikariDataSource.getHikariPoolMXBean().softEvictConnections(); + } } diff --git a/blade/pom.xml b/blade/pom.xml index 178d1afb52..458ec40051 100644 --- a/blade/pom.xml +++ b/blade/pom.xml @@ -154,7 +154,6 @@ 2.0.14.RELEASE 4.2.1 - 3.8.1 1.18.4 4.5.6 4.5.6 diff --git a/core-java-modules/core-java-10/README.md b/core-java-modules/core-java-10/README.md index 23f598b902..11c2051816 100644 --- a/core-java-modules/core-java-10/README.md +++ b/core-java-modules/core-java-10/README.md @@ -5,8 +5,9 @@ This module contains articles about Java 10 core features ### Relevant Articles: - [Java 10 LocalVariable Type-Inference](http://www.baeldung.com/java-10-local-variable-type-inference) -- [Guide to Java 10](http://www.baeldung.com/java-10-overview) +- [New Features in Java 10](https://www.baeldung.com/java-10-overview) - [Copy a List to Another List in Java](http://www.baeldung.com/java-copy-list-to-another) - [Deep Dive Into the New Java JIT Compiler – Graal](https://www.baeldung.com/graal-java-jit-compiler) - [Copying Sets in Java](https://www.baeldung.com/java-copy-sets) - [Converting between a List and a Set in Java](https://www.baeldung.com/convert-list-to-set-and-set-to-list) +- [Java IndexOutOfBoundsException “Source Does Not Fit in Dest”](https://www.baeldung.com/java-indexoutofboundsexception) diff --git a/core-java-modules/core-java-11-2/README.md b/core-java-modules/core-java-11-2/README.md index 834f310fce..c87936b07d 100644 --- a/core-java-modules/core-java-11-2/README.md +++ b/core-java-modules/core-java-11-2/README.md @@ -6,3 +6,4 @@ This module contains articles about Java 11 core features - [Guide to Java 8 Optional](https://www.baeldung.com/java-optional) - [Guide to Java Reflection](http://www.baeldung.com/java-reflection) - [Guide to Java 8’s Collectors](https://www.baeldung.com/java-8-collectors) +- [New Features in Java 11](https://www.baeldung.com/java-11-new-features) diff --git a/core-java-modules/core-java-11-2/pom.xml b/core-java-modules/core-java-11-2/pom.xml index e2b129ae00..b92963a5c8 100644 --- a/core-java-modules/core-java-11-2/pom.xml +++ b/core-java-modules/core-java-11-2/pom.xml @@ -28,6 +28,29 @@ ${assertj.version} test + + org.mock-server + mockserver-junit-jupiter + ${mockserver.version} + + + org.junit.jupiter + junit-jupiter-engine + ${junit.jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-params + ${junit.jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.version} + test + @@ -48,7 +71,9 @@ 11 11 29.0-jre + 5.7.0 3.17.2 + 5.11.1 diff --git a/core-java-modules/core-java-11-2/src/main/java/com/baeldung/features/MainClass.java b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/features/MainClass.java new file mode 100644 index 0000000000..b00c56fcd7 --- /dev/null +++ b/core-java-modules/core-java-11-2/src/main/java/com/baeldung/features/MainClass.java @@ -0,0 +1,17 @@ +package com.baeldung.features; + +public class MainClass { + + private static boolean mainPrivateMethod() { + return true; + } + + public static class NestedClass { + + boolean nestedPublicMethod() { + return mainPrivateMethod(); + } + + } + +} diff --git a/core-java-modules/core-java-11-2/src/test/java/com/baeldung/features/HttpClientIntegrationTest.java b/core-java-modules/core-java-11-2/src/test/java/com/baeldung/features/HttpClientIntegrationTest.java new file mode 100644 index 0000000000..1d49f5dbd1 --- /dev/null +++ b/core-java-modules/core-java-11-2/src/test/java/com/baeldung/features/HttpClientIntegrationTest.java @@ -0,0 +1,54 @@ +package com.baeldung.features; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.HttpStatusCode; +import org.mockserver.socket.PortFactory; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.time.Duration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockserver.integration.ClientAndServer.startClientAndServer; + +class HttpClientIntegrationTest { + + private static ClientAndServer mockServer; + private static int port; + + @BeforeAll + static void startServer() { + port = PortFactory.findFreePort(); + mockServer = startClientAndServer(port); + mockServer.when(new org.mockserver.model.HttpRequest().withMethod("GET")) + .respond(new org.mockserver.model.HttpResponse() + .withStatusCode(HttpStatusCode.OK_200.code()) + .withBody("Hello from the server!")); + } + + @AfterAll + static void stopServer() { + mockServer.stop(); + } + + @Test + void givenSampleHttpRequest_whenRequestIsSent_thenServerResponseIsReceived() throws IOException, InterruptedException { + HttpClient httpClient = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .connectTimeout(Duration.ofSeconds(20)) + .build(); + HttpRequest httpRequest = HttpRequest.newBuilder() + .GET() + .uri(URI.create("http://localhost:" + port)) + .build(); + HttpResponse httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()); + assertThat(httpResponse.body()).isEqualTo("Hello from the server!"); + } + +} diff --git a/core-java-modules/core-java-11-2/src/test/java/com/baeldung/features/JavaElevenFeaturesUnitTest.java b/core-java-modules/core-java-11-2/src/test/java/com/baeldung/features/JavaElevenFeaturesUnitTest.java new file mode 100644 index 0000000000..61ce9c7c13 --- /dev/null +++ b/core-java-modules/core-java-11-2/src/test/java/com/baeldung/features/JavaElevenFeaturesUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.features; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +class JavaElevenFeaturesUnitTest { + + @Test + void givenMultilineString_whenExtractingNonBlankStrippedLines_thenLinesAreReturned() { + String multilineString = "Baeldung helps \n \n developers \n explore Java."; + List lines = multilineString.lines() + .filter(line -> !line.isBlank()) + .map(String::strip) + .collect(Collectors.toList()); + assertThat(lines).containsExactly("Baeldung helps", "developers", "explore Java."); + } + + @Test + void givenTemporaryFile_whenReadingStringContent_thenContentIsReturned(@TempDir Path tempDir) throws IOException { + Path filePath = Files.writeString(Files.createTempFile(tempDir, "demo", ".txt"), "Sample text"); + String fileContent = Files.readString(filePath); + assertThat(fileContent).isEqualTo("Sample text"); + } + + @Test + void givenSampleList_whenConvertingToArray_thenItemsRemainUnchanged() { + List sampleList = Arrays.asList("Java", "Kotlin"); + String[] sampleArray = sampleList.toArray(String[]::new); + assertThat(sampleArray).containsExactly("Java", "Kotlin"); + } + + @Test + void givenSampleList_whenConvertingToUppercaseString_thenUppercaseIsReturned() { + List sampleList = Arrays.asList("Java", "Kotlin"); + String resultString = sampleList.stream() + .map((@Nonnull var x) -> x.toUpperCase()) + .collect(Collectors.joining(", ")); + assertThat(resultString).isEqualTo("JAVA, KOTLIN"); + } + + @Test + void givenSampleList_whenExtractingNonBlankValues_thenOnlyNonBlanksAreReturned() { + List sampleList = Arrays.asList("Java", "\n \n", "Kotlin", " "); + List withoutBlanks = sampleList.stream() + .filter(Predicate.not(String::isBlank)) + .collect(Collectors.toList()); + assertThat(withoutBlanks).containsExactly("Java", "Kotlin"); + } + +} diff --git a/core-java-modules/core-java-11-2/src/test/java/com/baeldung/features/NestedClassesUnitTest.java b/core-java-modules/core-java-11-2/src/test/java/com/baeldung/features/NestedClassesUnitTest.java new file mode 100644 index 0000000000..902ad9c6f8 --- /dev/null +++ b/core-java-modules/core-java-11-2/src/test/java/com/baeldung/features/NestedClassesUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.features; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; + +class NestedClassesUnitTest { + + @Test + public void giveNestedClass_whenCallingMainClassPrivateMethod_thenNoExceptionIsThrown() { + MainClass.NestedClass nestedInstance = new MainClass.NestedClass(); + assertThat(nestedInstance.nestedPublicMethod()).isTrue(); + } + + @Test + public void giveNestedClass_whenCheckingNestmate_thenNestedClassIsReturned() { + assertThat(MainClass.class.isNestmateOf(MainClass.NestedClass.class)).isTrue(); + } + + @Test + public void giveNestedClass_whenCheckingNestHost_thenMainClassIsReturned() { + assertThat(MainClass.NestedClass.class.getNestHost()).isEqualTo(MainClass.class); + } + + @Test + public void giveNestedClass_whenCheckingNestMembers_thenNestMembersAreReturned() { + Set nestedMembers = Arrays.stream(MainClass.NestedClass.class.getNestMembers()) + .map(Class::getName) + .collect(Collectors.toSet()); + assertThat(nestedMembers).contains(MainClass.class.getName(), MainClass.NestedClass.class.getName()); + } + +} diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientUnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientUnitTest.java index 42f56838c4..2a2540a517 100644 --- a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientUnitTest.java +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpClientUnitTest.java @@ -64,7 +64,7 @@ public class HttpClientUnitTest { .send(request, HttpResponse.BodyHandlers.ofString()); assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_MOVED_PERM)); - assertThat(response.body(), containsString("https://stackoverflow.com/")); + assertTrue(response.headers().map().get("location").stream().anyMatch("https://stackoverflow.com/"::equals)); } @Test diff --git a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestUnitTest.java b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestUnitTest.java index b87e6b3c6e..a3a5592cd9 100644 --- a/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestUnitTest.java +++ b/core-java-modules/core-java-11/src/test/java/com/baeldung/java11/httpclient/test/HttpRequestUnitTest.java @@ -18,6 +18,7 @@ import java.security.NoSuchAlgorithmException; import java.time.Duration; import org.junit.Test; +import org.junit.jupiter.api.Disabled; public class HttpRequestUnitTest { @@ -48,7 +49,12 @@ public class HttpRequestUnitTest { assertThat(response.version(), equalTo(HttpClient.Version.HTTP_2)); } - @Test + /* + * This test will fail as soon as the given URL returns a HTTP 2 response. + * Therefore, let's leave it commented out. + * */ + @Test + @Disabled public void shouldFallbackToHttp1_1WhenWebsiteDoesNotUseHttp2() throws IOException, InterruptedException, URISyntaxException, NoSuchAlgorithmException { HttpRequest request = HttpRequest.newBuilder() .uri(new URI("https://postman-echo.com/get")) diff --git a/core-java-modules/core-java-12/README.md b/core-java-modules/core-java-12/README.md index 6c603e4dea..b509be876c 100644 --- a/core-java-modules/core-java-12/README.md +++ b/core-java-modules/core-java-12/README.md @@ -1,4 +1,4 @@ ## Relevant Articles: - - [String API Updates in Java 12](https://www.baeldung.com/java12-string-api) +- [New Features in Java 12](https://www.baeldung.com/java-12-new-features) diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/CompactNumbersUnitTest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/CompactNumbersUnitTest.java new file mode 100644 index 0000000000..08a6d58d72 --- /dev/null +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/CompactNumbersUnitTest.java @@ -0,0 +1,21 @@ +package java.com.baeldung.newfeatures; + +import org.junit.Test; + +import java.text.NumberFormat; +import java.util.Locale; + +import static org.junit.Assert.assertEquals; + +public class CompactNumbersUnitTest { + + @Test + public void givenNumber_thenCompactValues() { + NumberFormat likesShort = NumberFormat.getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.SHORT); + likesShort.setMaximumFractionDigits(2); + assertEquals("2.59K", likesShort.format(2592)); + NumberFormat likesLong = NumberFormat.getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.LONG); + likesLong.setMaximumFractionDigits(2); + assertEquals("2.59 thousand", likesShort.format(2592)); + } +} diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/FileMismatchUnitTest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/FileMismatchUnitTest.java new file mode 100644 index 0000000000..7f081fe399 --- /dev/null +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/FileMismatchUnitTest.java @@ -0,0 +1,32 @@ +package java.com.baeldung.newfeatures; + +import org.junit.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.Assert.assertEquals; + +public class FileMismatchUnitTest { + + @Test + public void givenIdenticalFiles_thenShouldNotFindMismatch() throws IOException { + Path filePath1 = Files.createTempFile("file1", ".txt"); + Path filePath2 = Files.createTempFile("file2", ".txt"); + Files.writeString(filePath1, "Java 12 Article"); + Files.writeString(filePath2, "Java 12 Article"); + long mismatch = Files.mismatch(filePath1, filePath2); + assertEquals(-1, mismatch); + } + + @Test + public void givenDifferentFiles_thenShouldFindMismatch() throws IOException { + Path filePath3 = Files.createTempFile("file3", ".txt"); + Path filePath4 = Files.createTempFile("file4", ".txt"); + Files.writeString(filePath3, "Java 12 Article"); + Files.writeString(filePath4, "Java 12 Tutorial"); + long mismatch = Files.mismatch(filePath3, filePath4); + assertEquals(8, mismatch); + } +} diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/StringUnitTest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/StringUnitTest.java new file mode 100644 index 0000000000..5ae51bd960 --- /dev/null +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/StringUnitTest.java @@ -0,0 +1,15 @@ +package java.com.baeldung.newfeatures; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class StringUnitTest { + + @Test + public void givenString_thenRevertValue() { + String text = "Baeldung"; + String transformed = text.transform(value -> new StringBuilder(value).reverse().toString()); + assertEquals("gnudleaB", transformed); + } +} diff --git a/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/TeeingCollectorUnitTest.java b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/TeeingCollectorUnitTest.java new file mode 100644 index 0000000000..30a5cb40a7 --- /dev/null +++ b/core-java-modules/core-java-12/src/test/java/com/baeldung/newfeatures/TeeingCollectorUnitTest.java @@ -0,0 +1,18 @@ +package java.com.baeldung.newfeatures; + +import org.junit.Test; + +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; + +public class TeeingCollectorUnitTest { + + @Test + public void givenSetOfNumbers_thenCalculateAverage() { + double mean = Stream.of(1, 2, 3, 4, 5) + .collect(Collectors.teeing(Collectors.summingDouble(i -> i), Collectors.counting(), (sum, count) -> sum / count)); + assertEquals(3.0, mean); + } +} diff --git a/core-java-modules/core-java-13/README.md b/core-java-modules/core-java-13/README.md index 697f89c362..9215139dd4 100644 --- a/core-java-modules/core-java-13/README.md +++ b/core-java-modules/core-java-13/README.md @@ -1,4 +1,4 @@ ### Relevant articles: - [Java Switch Statement](https://www.baeldung.com/java-switch) -- [New Java 13 Features](https://www.baeldung.com/java-13-new-features) +- [New Features in Java 13](https://www.baeldung.com/java-13-new-features) diff --git a/core-java-modules/core-java-14/README.md b/core-java-modules/core-java-14/README.md index d382c4814a..07cdf9859c 100644 --- a/core-java-modules/core-java-14/README.md +++ b/core-java-modules/core-java-14/README.md @@ -10,3 +10,4 @@ This module contains articles about Java 14. - [Helpful NullPointerExceptions in Java 14](https://www.baeldung.com/java-14-nullpointerexception) - [Foreign Memory Access API in Java 14](https://www.baeldung.com/java-foreign-memory-access) - [Java 14 Record Keyword](https://www.baeldung.com/java-record-keyword) +- [New Features in Java 14](https://www.baeldung.com/java-14-new-features) diff --git a/core-java-modules/core-java-14/pom.xml b/core-java-modules/core-java-14/pom.xml index 96cb6b37e7..e977f39e9d 100644 --- a/core-java-modules/core-java-14/pom.xml +++ b/core-java-modules/core-java-14/pom.xml @@ -44,6 +44,8 @@ ${maven.compiler.release} --enable-preview + 14 + 14 diff --git a/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/character/IsLetterOrAlphabetUnitTest.java b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/character/IsLetterOrAlphabetUnitTest.java new file mode 100644 index 0000000000..44c712a17f --- /dev/null +++ b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/character/IsLetterOrAlphabetUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.java14.character; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +public class IsLetterOrAlphabetUnitTest { + + @Test + public void givenACharacter_whenLetter_thenAssertIsLetterTrue() { + assertTrue(Character.isLetter(65)); + } + + @Test + public void givenACharacter_whenLetter_thenAssertIsAlphabeticTrue() { + assertTrue(Character.isAlphabetic(65)); + } + + @Test + public void givenACharacter_whenAlphabeticAndNotLetter_thenAssertIsLetterFalse() { + assertFalse(Character.isLetter(837)); + } + + @Test + public void givenACharacter_whenAlphabeticAndNotLetter_thenAssertIsAlphabeticTrue() { + assertTrue(Character.isAlphabetic(837)); + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/newfeatues/MultilineUnitTest.java b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/newfeatues/MultilineUnitTest.java new file mode 100644 index 0000000000..4efd1ff362 --- /dev/null +++ b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/newfeatues/MultilineUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.java14.newfeatues; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class MultilineUnitTest { + + @SuppressWarnings("preview") + String multiline = """ + A quick brown fox jumps over a lazy dog; \ + the lazy dog howls loudly."""; + + @SuppressWarnings("preview") + String anotherMultiline = """ + A quick brown fox jumps over a lazy dog; + the lazy dog howls loudly."""; + + @Test + public void givenMultilineString_whenSlashUsed_thenNoNewLine() { + assertFalse(multiline.contains("\n")); + assertTrue(anotherMultiline.contains("\n")); + } + +} diff --git a/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/newfeatues/RecordUnitTest.java b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/newfeatues/RecordUnitTest.java new file mode 100644 index 0000000000..3d7a55d3e6 --- /dev/null +++ b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/newfeatues/RecordUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.java14.newfeatues; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class RecordUnitTest { + + @SuppressWarnings("preview") + public record User(int id, String password) { + }; + + private User user1 = new User(0, "UserOne"); + + @Test + public void givenRecord_whenObjInitialized_thenValuesCanBeFetchedWithGetters() { + + assertEquals(0, user1.id()); + assertEquals("UserOne", user1.password()); + } + + @Test + public void whenRecord_thenEqualsImplemented() { + + User user2 = user1; + + assertEquals(user1, user2); + } + + @Test + public void whenRecord_thenToStringImplemented() { + + assertTrue(user1.toString() + .contains("UserOne")); + } + +} diff --git a/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/newfeatues/SwitchExprUnitTest.java b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/newfeatues/SwitchExprUnitTest.java new file mode 100644 index 0000000000..896b3ec7de --- /dev/null +++ b/core-java-modules/core-java-14/src/test/java/com/baeldung/java14/newfeatues/SwitchExprUnitTest.java @@ -0,0 +1,50 @@ +package com.baeldung.java14.newfeatues; + +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class SwitchExprUnitTest { + + @Test + public void givenDay_whenSunday_thenWeekend() { + assertTrue(isTodayHolidayInJava8("SUNDAY")); + + assertTrue(isTodayHolidayInJava14("SUNDAY")); + + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> isTodayHolidayInJava8("SOMEDAY")); + + assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> isTodayHolidayInJava14("SOMEDAY")); + } + + private boolean isTodayHolidayInJava8(String day) { + + boolean isTodayHoliday; + switch (day) { + case "MONDAY": + case "TUESDAY": + case "WEDNESDAY": + case "THURSDAY": + case "FRIDAY": + isTodayHoliday = false; + break; + case "SATURDAY": + case "SUNDAY": + isTodayHoliday = true; + break; + default: + throw new IllegalArgumentException("What's a " + day); + } + return isTodayHoliday; + } + + private boolean isTodayHolidayInJava14(String day) { + return switch (day) { + case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> false; + case "SATURDAY", "SUNDAY" -> true; + default -> throw new IllegalArgumentException("What's a " + day); + }; + } + +} diff --git a/core-java-modules/core-java-15/.mvn/jvm.config b/core-java-modules/core-java-15/.mvn/jvm.config new file mode 100644 index 0000000000..50f549be0a --- /dev/null +++ b/core-java-modules/core-java-15/.mvn/jvm.config @@ -0,0 +1 @@ +--enable-preview \ No newline at end of file diff --git a/core-java-modules/core-java-15/README.md b/core-java-modules/core-java-15/README.md new file mode 100644 index 0000000000..de503fbb31 --- /dev/null +++ b/core-java-modules/core-java-15/README.md @@ -0,0 +1,7 @@ +## Core Java 15 + +This module contains articles about Java 15. + +### Relevant articles + +- [Sealed Classes and Interfaces in Java 15](https://www.baeldung.com/java-sealed-classes-interfaces) diff --git a/core-java-modules/core-java-15/pom.xml b/core-java-modules/core-java-15/pom.xml new file mode 100644 index 0000000000..3b0d324d10 --- /dev/null +++ b/core-java-modules/core-java-15/pom.xml @@ -0,0 +1,76 @@ + + + 4.0.0 + core-java-15 + core-java-15 + jar + http://maven.apache.org + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + ../../pom.xml + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-api + ${junit-jupiter.version} + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.release} + --enable-preview + 14 + 14 + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.plugin.version} + + --enable-preview + + + + + + + 15 + 3.17.2 + 3.8.1 + 3.0.0-M3 + + + \ No newline at end of file diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/alternative/Vehicles.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/alternative/Vehicles.java new file mode 100644 index 0000000000..091c5841bf --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/alternative/Vehicles.java @@ -0,0 +1,49 @@ +package com.baeldung.sealed.alternative; + +public class Vehicles { + + abstract static class Vehicle { + + private final String registrationNumber; + + public Vehicle(String registrationNumber) { + this.registrationNumber = registrationNumber; + } + + public String getRegistrationNumber() { + return registrationNumber; + } + + } + + public static final class Car extends Vehicle { + + private final int numberOfSeats; + + public Car(int numberOfSeats, String registrationNumber) { + super(registrationNumber); + this.numberOfSeats = numberOfSeats; + } + + public int getNumberOfSeats() { + return numberOfSeats; + } + + } + + public static final class Truck extends Vehicle { + + private final int loadCapacity; + + public Truck(int loadCapacity, String registrationNumber) { + super(registrationNumber); + this.loadCapacity = loadCapacity; + } + + public int getLoadCapacity() { + return loadCapacity; + } + + } + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Car.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Car.java new file mode 100644 index 0000000000..7dce266da7 --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Car.java @@ -0,0 +1,21 @@ +package com.baeldung.sealed.classes; + +public non-sealed class Car extends Vehicle implements Service { + + private final int numberOfSeats; + + public Car(int numberOfSeats, String registrationNumber) { + super(registrationNumber); + this.numberOfSeats = numberOfSeats; + } + + public int getNumberOfSeats() { + return numberOfSeats; + } + + @Override + public int getMaxServiceIntervalInMonths() { + return 12; + } + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Service.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Service.java new file mode 100644 index 0000000000..9486b302f1 --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Service.java @@ -0,0 +1,11 @@ +package com.baeldung.sealed.classes; + +public sealed interface Service permits Car, Truck { + + int getMaxServiceIntervalInMonths(); + + default int getMaxDistanceBetweenServicesInKilometers() { + return 100000; + } + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Truck.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Truck.java new file mode 100644 index 0000000000..8d5234342b --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Truck.java @@ -0,0 +1,21 @@ +package com.baeldung.sealed.classes; + +public final class Truck extends Vehicle implements Service { + + private final int loadCapacity; + + public Truck(int loadCapacity, String registrationNumber) { + super(registrationNumber); + this.loadCapacity = loadCapacity; + } + + public int getLoadCapacity() { + return loadCapacity; + } + + @Override + public int getMaxServiceIntervalInMonths() { + return 18; + } + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Vehicle.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Vehicle.java new file mode 100644 index 0000000000..79eda0c790 --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/classes/Vehicle.java @@ -0,0 +1,15 @@ +package com.baeldung.sealed.classes; + +public abstract sealed class Vehicle permits Car, Truck { + + protected final String registrationNumber; + + public Vehicle(String registrationNumber) { + this.registrationNumber = registrationNumber; + } + + public String getRegistrationNumber() { + return registrationNumber; + } + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Car.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Car.java new file mode 100644 index 0000000000..74b6ed1405 --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Car.java @@ -0,0 +1,14 @@ +package com.baeldung.sealed.records; + +public record Car(int numberOfSeats, String registrationNumber) implements Vehicle { + + @Override + public String getRegistrationNumber() { + return registrationNumber; + } + + public int getNumberOfSeats() { + return numberOfSeats; + } + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Truck.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Truck.java new file mode 100644 index 0000000000..1b887ae014 --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Truck.java @@ -0,0 +1,14 @@ +package com.baeldung.sealed.records; + +public record Truck(int loadCapacity, String registrationNumber) implements Vehicle { + + @Override + public String getRegistrationNumber() { + return registrationNumber; + } + + public int getLoadCapacity() { + return loadCapacity; + } + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Vehicle.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Vehicle.java new file mode 100644 index 0000000000..c51f8e97c6 --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/sealed/records/Vehicle.java @@ -0,0 +1,7 @@ +package com.baeldung.sealed.records; + +public sealed interface Vehicle permits Car, Truck { + + String getRegistrationNumber(); + +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/whatsnew/records/Person.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/whatsnew/records/Person.java new file mode 100644 index 0000000000..74cf5edf9c --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/whatsnew/records/Person.java @@ -0,0 +1,15 @@ +package com.baeldung.whatsnew.records; + +/** + * Java record with a header indicating 2 fields. + */ +public record Person(String name, int age) { + /** + * Public constructor that does some basic validation. + */ + public Person { + if (age < 0) { + throw new IllegalArgumentException("Age cannot be negative"); + } + } +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/whatsnew/sealedclasses/Employee.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/whatsnew/sealedclasses/Employee.java new file mode 100644 index 0000000000..ec85c371b7 --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/whatsnew/sealedclasses/Employee.java @@ -0,0 +1,9 @@ +package com.baeldung.whatsnew.sealedclasses; + +import java.util.Date; + +public non-sealed class Employee extends Person { + public Date getHiredDate() { + return new Date(); + } +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/whatsnew/sealedclasses/Manager.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/whatsnew/sealedclasses/Manager.java new file mode 100644 index 0000000000..79c50b057e --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/whatsnew/sealedclasses/Manager.java @@ -0,0 +1,4 @@ +package com.baeldung.whatsnew.sealedclasses; + +public final class Manager extends Person { +} diff --git a/core-java-modules/core-java-15/src/main/java/com/baeldung/whatsnew/sealedclasses/Person.java b/core-java-modules/core-java-15/src/main/java/com/baeldung/whatsnew/sealedclasses/Person.java new file mode 100644 index 0000000000..2a52bc1a73 --- /dev/null +++ b/core-java-modules/core-java-15/src/main/java/com/baeldung/whatsnew/sealedclasses/Person.java @@ -0,0 +1,21 @@ +package com.baeldung.whatsnew.sealedclasses; + +import java.util.Date; + +public sealed class Person permits Employee, Manager { + /** + * Demonstration of pattern matching for instanceof + * + * @param person A Person object + * @return + */ + public static void patternMatchingDemo(Person person) { + if(person instanceof Employee employee) { + Date hiredDate = employee.getHiredDate(); + } + + if(person instanceof Employee employee && employee.getHiredDate() != null) { + Date hiredDate = employee.getHiredDate(); + } + } +} diff --git a/core-java-modules/core-java-15/src/test/java/com/baeldung/sealed/classes/VehicleUnitTest.java b/core-java-modules/core-java-15/src/test/java/com/baeldung/sealed/classes/VehicleUnitTest.java new file mode 100644 index 0000000000..b614981a43 --- /dev/null +++ b/core-java-modules/core-java-15/src/test/java/com/baeldung/sealed/classes/VehicleUnitTest.java @@ -0,0 +1,76 @@ +package com.baeldung.sealed.classes; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.lang.constant.ClassDesc; + +public class VehicleUnitTest { + + private static Vehicle car; + private static Vehicle truck; + + @BeforeAll + public static void createInstances() { + car = new Car(5, "VZ500DA"); + truck = new Truck(19000, "VZ600TA"); + } + + @Test + public void givenCar_whenUsingReflectionAPI_thenSuperClassIsSealed() { + Assertions.assertThat(car.getClass().isSealed()).isEqualTo(false); + Assertions.assertThat(car.getClass().getSuperclass().isSealed()).isEqualTo(true); + Assertions.assertThat(car.getClass().getSuperclass().permittedSubclasses()) + .contains(ClassDesc.of(car.getClass().getCanonicalName())); + } + + @Test + public void givenTruck_whenUsingReflectionAPI_thenSuperClassIsSealed() { + Assertions.assertThat(truck.getClass().isSealed()).isEqualTo(false); + Assertions.assertThat(truck.getClass().getSuperclass().isSealed()).isEqualTo(true); + Assertions.assertThat(truck.getClass().getSuperclass().permittedSubclasses()) + .contains(ClassDesc.of(truck.getClass().getCanonicalName())); + } + + @Test + public void givenCar_whenGettingPropertyTraditionalWay_thenNumberOfSeatsPropertyIsReturned() { + Assertions.assertThat(getPropertyTraditionalWay(car)).isEqualTo(5); + } + + @Test + public void givenCar_whenGettingPropertyViaPatternMatching_thenNumberOfSeatsPropertyIsReturned() { + Assertions.assertThat(getPropertyViaPatternMatching(car)).isEqualTo(5); + } + + @Test + public void givenTruck_whenGettingPropertyTraditionalWay_thenLoadCapacityIsReturned() { + Assertions.assertThat(getPropertyTraditionalWay(truck)).isEqualTo(19000); + } + + @Test + public void givenTruck_whenGettingPropertyViaPatternMatching_thenLoadCapacityIsReturned() { + Assertions.assertThat(getPropertyViaPatternMatching(truck)).isEqualTo(19000); + } + + private int getPropertyTraditionalWay(Vehicle vehicle) { + if (vehicle instanceof Car) { + return ((Car) vehicle).getNumberOfSeats(); + } else if (vehicle instanceof Truck) { + return ((Truck) vehicle).getLoadCapacity(); + } else { + throw new RuntimeException("Unknown instance of Vehicle"); + } + } + + private int getPropertyViaPatternMatching(Vehicle vehicle) { + if (vehicle instanceof Car car) { + return car.getNumberOfSeats(); + } else if (vehicle instanceof Truck truck) { + return truck.getLoadCapacity(); + } else { + throw new RuntimeException("Unknown instance of Vehicle"); + } + } + +} diff --git a/core-java-modules/core-java-15/src/test/java/com/baeldung/sealed/records/VehicleUnitTest.java b/core-java-modules/core-java-15/src/test/java/com/baeldung/sealed/records/VehicleUnitTest.java new file mode 100644 index 0000000000..ac8a8c953c --- /dev/null +++ b/core-java-modules/core-java-15/src/test/java/com/baeldung/sealed/records/VehicleUnitTest.java @@ -0,0 +1,76 @@ +package com.baeldung.sealed.records; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.lang.constant.ClassDesc; + +public class VehicleUnitTest { + + private static Vehicle car; + private static Vehicle truck; + + @BeforeAll + public static void createInstances() { + car = new Car(4, "VZ500DA"); + truck = new Truck(16000, "VZ600TA"); + } + + @Test + public void givenCar_whenUsingReflectionAPI_thenInterfaceIsSealed() { + Assertions.assertThat(car.getClass().isSealed()).isEqualTo(false); + Assertions.assertThat(car.getClass().getInterfaces()[0].isSealed()).isEqualTo(true); + Assertions.assertThat(car.getClass().getInterfaces()[0].permittedSubclasses()) + .contains(ClassDesc.of(car.getClass().getCanonicalName())); + } + + @Test + public void givenTruck_whenUsingReflectionAPI_thenInterfaceIsSealed() { + Assertions.assertThat(truck.getClass().isSealed()).isEqualTo(false); + Assertions.assertThat(truck.getClass().getInterfaces()[0].isSealed()).isEqualTo(true); + Assertions.assertThat(truck.getClass().getInterfaces()[0].permittedSubclasses()) + .contains(ClassDesc.of(truck.getClass().getCanonicalName())); + } + + @Test + public void givenCar_whenGettingPropertyTraditionalWay_thenNumberOfSeatsPropertyIsReturned() { + Assertions.assertThat(getPropertyTraditionalWay(car)).isEqualTo(4); + } + + @Test + public void givenCar_whenGettingPropertyViaPatternMatching_thenNumberOfSeatsPropertyIsReturned() { + Assertions.assertThat(getPropertyViaPatternMatching(car)).isEqualTo(4); + } + + @Test + public void givenTruck_whenGettingPropertyTraditionalWay_thenLoadCapacityIsReturned() { + Assertions.assertThat(getPropertyTraditionalWay(truck)).isEqualTo(16000); + } + + @Test + public void givenTruck_whenGettingPropertyViaPatternMatching_thenLoadCapacityIsReturned() { + Assertions.assertThat(getPropertyViaPatternMatching(truck)).isEqualTo(16000); + } + + private int getPropertyTraditionalWay(Vehicle vehicle) { + if (vehicle instanceof Car) { + return ((Car) vehicle).getNumberOfSeats(); + } else if (vehicle instanceof Truck) { + return ((Truck) vehicle).getLoadCapacity(); + } else { + throw new RuntimeException("Unknown instance of Vehicle"); + } + } + + private int getPropertyViaPatternMatching(Vehicle vehicle) { + if (vehicle instanceof Car car) { + return car.getNumberOfSeats(); + } else if (vehicle instanceof Truck truck) { + return truck.getLoadCapacity(); + } else { + throw new RuntimeException("Unknown instance of Vehicle"); + } + } + +} diff --git a/core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java b/core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java index 2519da085b..617a0a7e70 100644 --- a/core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java +++ b/core-java-modules/core-java-9-jigsaw/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java @@ -19,12 +19,12 @@ public class StudentDbService implements StudentService { } public Student update(Student student) { - logger.log(Level.INFO, "Updating sutdent in DB..."); + logger.log(Level.INFO, "Updating student in DB..."); return student; } public String delete(String registrationId) { - logger.log(Level.INFO, "Deleteing sutdent in DB..."); + logger.log(Level.INFO, "Deleting student in DB..."); return registrationId; } } \ No newline at end of file diff --git a/core-java-modules/core-java-9-jigsaw/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java b/core-java-modules/core-java-9-jigsaw/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java index aa2fb34753..b909636b56 100644 --- a/core-java-modules/core-java-9-jigsaw/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java +++ b/core-java-modules/core-java-9-jigsaw/src/test/java/com/baeldung/java9/modules/ModuleAPIUnitTest.java @@ -2,8 +2,7 @@ package com.baeldung.java9.modules; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.*; import static org.hamcrest.collection.IsEmptyCollection.empty; import static org.junit.Assert.*; @@ -74,7 +73,6 @@ public class ModuleAPIUnitTest { ModuleLayer javaBaseModuleLayer = javaBaseModule.getLayer(); assertTrue(javaBaseModuleLayer.configuration().findModule(JAVA_BASE_MODULE_NAME).isPresent()); - assertThat(javaBaseModuleLayer.configuration().modules().size(), is(78)); assertTrue(javaBaseModuleLayer.parents().get(0).configuration().parents().isEmpty()); } @@ -108,8 +106,7 @@ public class ModuleAPIUnitTest { .collect(Collectors.toSet()); assertThat(javaBaseRequires, empty()); - assertThat(javaSqlRequires.size(), is(3)); - assertThat(javaSqlRequiresNames, containsInAnyOrder("java.base", "java.xml", "java.logging")); + assertThat(javaSqlRequiresNames, hasItems("java.base", "java.xml", "java.logging")); } @Test @@ -127,16 +124,13 @@ public class ModuleAPIUnitTest { @Test public void givenModules_whenAccessingModuleDescriptorExports_thenExportsAreReturned() { - Set javaBaseExports = javaBaseModule.getDescriptor().exports(); Set javaSqlExports = javaSqlModule.getDescriptor().exports(); Set javaSqlExportsSource = javaSqlExports.stream() .map(Exports::source) .collect(Collectors.toSet()); - assertThat(javaBaseExports.size(), is(108)); - assertThat(javaSqlExports.size(), is(3)); - assertThat(javaSqlExportsSource, containsInAnyOrder("java.sql", "javax.transaction.xa", "javax.sql")); + assertThat(javaSqlExportsSource, hasItems("java.sql", "javax.sql")); } @Test @@ -144,7 +138,6 @@ public class ModuleAPIUnitTest { Set javaBaseUses = javaBaseModule.getDescriptor().uses(); Set javaSqlUses = javaSqlModule.getDescriptor().uses(); - assertThat(javaBaseUses.size(), is(34)); assertThat(javaSqlUses, contains("java.sql.Driver")); } diff --git a/core-java-modules/core-java-9-new-features/README.md b/core-java-modules/core-java-9-new-features/README.md index 5af069c6f0..4045a37d9d 100644 --- a/core-java-modules/core-java-9-new-features/README.md +++ b/core-java-modules/core-java-9-new-features/README.md @@ -4,7 +4,7 @@ This module contains articles about core Java features that have been introduced ### Relevant Articles: -- [Java 9 New Features](https://www.baeldung.com/new-java-9) +- [New Features in Java 9](https://www.baeldung.com/new-java-9) - [Java 9 Variable Handles Demystified](http://www.baeldung.com/java-variable-handles) - [Exploring the New HTTP Client in Java 9 and 11](http://www.baeldung.com/java-9-http-client) - [Multi-Release Jar Files](https://www.baeldung.com/java-multi-release-jar) diff --git a/core-java-modules/core-java-9/pom.xml b/core-java-modules/core-java-9/pom.xml index d7894934b1..001faf88cb 100644 --- a/core-java-modules/core-java-9/pom.xml +++ b/core-java-modules/core-java-9/pom.xml @@ -47,12 +47,12 @@ org.apache.commons commons-lang3 - 3.11 + ${commons-lang3.version} commons-io commons-io - 2.7 + ${commons-io.version} diff --git a/core-java-modules/core-java-arrays-guides/README.md b/core-java-modules/core-java-arrays-guides/README.md index 934833b31b..7338ff9523 100644 --- a/core-java-modules/core-java-arrays-guides/README.md +++ b/core-java-modules/core-java-arrays-guides/README.md @@ -7,3 +7,4 @@ This module contains complete guides about arrays in Java - [Guide to the java.util.Arrays Class](https://www.baeldung.com/java-util-arrays) - [What is \[Ljava.lang.Object;?](https://www.baeldung.com/java-tostring-array) - [Guide to ArrayStoreException](https://www.baeldung.com/java-arraystoreexception) +- [Creating a Generic Array in Java](https://www.baeldung.com/java-generic-array) diff --git a/core-java-modules/core-java-arrays-guides/src/main/java/com/baeldung/genericarrays/MyStack.java b/core-java-modules/core-java-arrays-guides/src/main/java/com/baeldung/genericarrays/MyStack.java new file mode 100644 index 0000000000..02659f13bc --- /dev/null +++ b/core-java-modules/core-java-arrays-guides/src/main/java/com/baeldung/genericarrays/MyStack.java @@ -0,0 +1,30 @@ +package com.baeldung.genericarrays; + +import java.lang.reflect.Array; + +public class MyStack { + private E[] elements; + private int size = 0; + + public MyStack(Class clazz, int capacity) { + elements = (E[]) Array.newInstance(clazz, capacity); + } + + public void push(E item) { + if (size == elements.length) { + throw new RuntimeException(); + } + elements[size++] = item; + } + + public E pop() { + if (size == 0) { + throw new RuntimeException(); + } + return elements[--size]; + } + + public E[] getAllElements() { + return elements; + } +} diff --git a/core-java-modules/core-java-arrays-guides/src/test/java/com/baeldung/genericarrays/ListToArrayUnitTest.java b/core-java-modules/core-java-arrays-guides/src/test/java/com/baeldung/genericarrays/ListToArrayUnitTest.java new file mode 100644 index 0000000000..5fd0385181 --- /dev/null +++ b/core-java-modules/core-java-arrays-guides/src/test/java/com/baeldung/genericarrays/ListToArrayUnitTest.java @@ -0,0 +1,24 @@ +package com.baeldung.genericarrays; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class ListToArrayUnitTest { + + @Test + public void givenListOfItems_whenToArray_thenReturnArrayOfItems() { + List items = new LinkedList<>(); + items.add("first item"); + items.add("second item"); + + String[] itemsAsArray = items.toArray(new String[0]); + + assertEquals("first item", itemsAsArray[0]); + assertEquals("second item", itemsAsArray[1]); + } +} diff --git a/core-java-modules/core-java-arrays-guides/src/test/java/com/baeldung/genericarrays/MyStackUnitTest.java b/core-java-modules/core-java-arrays-guides/src/test/java/com/baeldung/genericarrays/MyStackUnitTest.java new file mode 100644 index 0000000000..e36c5169a5 --- /dev/null +++ b/core-java-modules/core-java-arrays-guides/src/test/java/com/baeldung/genericarrays/MyStackUnitTest.java @@ -0,0 +1,44 @@ +package com.baeldung.genericarrays; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class MyStackUnitTest { + + @Test + public void givenStackWithTwoItems_whenPop_thenReturnLastAdded() { + MyStack myStack = new MyStack<>(String.class, 2); + myStack.push("hello"); + myStack.push("example"); + + assertEquals("example", myStack.pop()); + } + + @Test (expected = RuntimeException.class) + public void givenStackWithFixedCapacity_whenExceedCapacity_thenThrowException() { + MyStack myStack = new MyStack<>(Integer.class, 2); + myStack.push(100); + myStack.push(200); + myStack.push(300); + } + + @Test(expected = RuntimeException.class) + public void givenStack_whenPopOnEmptyStack_thenThrowException() { + MyStack myStack = new MyStack<>(Integer.class, 1); + myStack.push(100); + myStack.pop(); + myStack.pop(); + } + + @Test + public void givenStackWithItems_whenGetAllElements_thenSizeShouldEqualTotal() { + MyStack myStack = new MyStack<>(String.class, 2); + myStack.push("hello"); + myStack.push("example"); + + String[] items = myStack.getAllElements(); + + assertEquals(2, items.length); + } +} diff --git a/core-java-modules/core-java-arrays-operations-advanced/pom.xml b/core-java-modules/core-java-arrays-operations-advanced/pom.xml index d73fdcee28..c7ea09c616 100644 --- a/core-java-modules/core-java-arrays-operations-advanced/pom.xml +++ b/core-java-modules/core-java-arrays-operations-advanced/pom.xml @@ -29,8 +29,6 @@ - 3.9 - 3.10.0 \ No newline at end of file diff --git a/core-java-modules/core-java-arrays-operations-basic/pom.xml b/core-java-modules/core-java-arrays-operations-basic/pom.xml index 64856d9b39..dcee6547a0 100644 --- a/core-java-modules/core-java-arrays-operations-basic/pom.xml +++ b/core-java-modules/core-java-arrays-operations-basic/pom.xml @@ -68,11 +68,7 @@ 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-sorting/pom.xml b/core-java-modules/core-java-arrays-sorting/pom.xml index 9b307870a1..9b900c3de6 100644 --- a/core-java-modules/core-java-arrays-sorting/pom.xml +++ b/core-java-modules/core-java-arrays-sorting/pom.xml @@ -76,12 +76,8 @@ 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-char/README.md b/core-java-modules/core-java-char/README.md new file mode 100644 index 0000000000..5f33aa6914 --- /dev/null +++ b/core-java-modules/core-java-char/README.md @@ -0,0 +1,6 @@ +## Core Java Character + +This module contains articles about Java Character Class + +### Relevant Articles: +- [Character#isAlphabetic vs. Character#isLetter](https://www.baeldung.com/java-character-isletter-isalphabetic) diff --git a/core-java-modules/core-java-char/pom.xml b/core-java-modules/core-java-char/pom.xml new file mode 100644 index 0000000000..3691079482 --- /dev/null +++ b/core-java-modules/core-java-char/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + core-java-char + 0.1.0-SNAPSHOT + core-java-char + jar + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + ../ + + + + + org.assertj + assertj-core + ${assertj.version} + test + + + org.openjdk.jmh + jmh-core + ${openjdk.jmh.version} + + + org.openjdk.jmh + jmh-generator-annprocess + ${openjdk.jmh.version} + + + + + 1.19 + 3.11.1 + + + diff --git a/core-java-modules/core-java-char/src/test/java/com/baeldung/character/CharacterGeneralCategoryTypeUnitTest.java b/core-java-modules/core-java-char/src/test/java/com/baeldung/character/CharacterGeneralCategoryTypeUnitTest.java new file mode 100644 index 0000000000..9fab13df45 --- /dev/null +++ b/core-java-modules/core-java-char/src/test/java/com/baeldung/character/CharacterGeneralCategoryTypeUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.character; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; + +public class CharacterGeneralCategoryTypeUnitTest { + @Test + public void givenACharacter_whenUpperCaseLetter_thenAssertTrue() { + assertEquals(Character.UPPERCASE_LETTER, Character.getType('U')); + } + + @Test + public void givenACharacter_whenLowerCaseLetter_thenAssertTrue() { + assertEquals(Character.LOWERCASE_LETTER, Character.getType('u')); + } + + @Test + public void givenACharacter_whenTitleCaseLetter_thenAssertTrue() { + assertEquals(Character.TITLECASE_LETTER, Character.getType('\u01f2')); + } + + @Test + public void givenACharacter_whenModifierLetter_thenAssertTrue() { + assertEquals(Character.MODIFIER_LETTER, Character.getType('\u02b0')); + } + + @Test + public void givenACharacter_whenOtherLetter_thenAssertTrue() { + assertEquals(Character.OTHER_LETTER, Character.getType('\u05d0')); + } + + @Test + public void givenACharacter_whenLetterNumber_thenAssertTrue() { + assertEquals(Character.LETTER_NUMBER, Character.getType('\u2164')); + } +} diff --git a/core-java-modules/core-java-char/src/test/java/com/baeldung/character/IsLetterOrAlphabetUnitTest.java b/core-java-modules/core-java-char/src/test/java/com/baeldung/character/IsLetterOrAlphabetUnitTest.java new file mode 100644 index 0000000000..3de3a16e6a --- /dev/null +++ b/core-java-modules/core-java-char/src/test/java/com/baeldung/character/IsLetterOrAlphabetUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung.character; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +public class IsLetterOrAlphabetUnitTest { + + @Test + public void givenACharacter_whenUpperCaseLetter_thenAssertIsAlphabeticTrue() { + assertTrue(Character.isAlphabetic('A')); + } + + @Test + public void givenACharacter_whenTitleCaseLetter_thenAssertIsAlphabeticTrue() { + assertTrue(Character.isAlphabetic('\u01f2')); + } + + @Test + public void givenACharacter_whenLowerCaseLetter_thenAssertIsLetterTrue() { + assertTrue(Character.isAlphabetic('a')); + } + + @Test + public void givenACharacter_whenModifierLetter_thenAssertIsLetterTrue() { + assertTrue(Character.isAlphabetic('\u02b0')); + } + + @Test + public void givenACharacter_whenLetter_thenAssertIsLetterTrue() { + assertTrue(Character.isLetter('a')); + } + + @Test + public void givenACharacter_whenLetter_thenAssertIsAlphabeticTrue() { + assertTrue(Character.isAlphabetic('a')); + } + + @Test + public void givenACharacter_whenAlphabeticAndNotLetter_thenAssertIsLetterFalse() { + assertFalse(Character.isLetter('\u2164')); + } + + @Test + public void givenACharacter_whenAlphabeticAndNotLetter_thenAssertIsAlphabeticTrue() { + assertTrue(Character.isAlphabetic('\u2164')); + } +} diff --git a/core-java-modules/core-java-collections-3/README.md b/core-java-modules/core-java-collections-3/README.md index c80e493767..6bc9139856 100644 --- a/core-java-modules/core-java-collections-3/README.md +++ b/core-java-modules/core-java-collections-3/README.md @@ -13,3 +13,5 @@ - [Quick Guide to the Java Stack](https://www.baeldung.com/java-stack) - [Convert an Array of Primitives to a List](https://www.baeldung.com/java-primitive-array-to-list) - [A Guide to BitSet in Java](https://www.baeldung.com/java-bitset) +- [Get the First Key and Value From a HashMap](https://www.baeldung.com/java-hashmap-get-first-entry) +- [Performance of removeAll() in a HashSet](https://www.baeldung.com/java-hashset-removeall-performance) diff --git a/core-java-modules/core-java-collections-3/pom.xml b/core-java-modules/core-java-collections-3/pom.xml index a9a05f5092..602fcf60f4 100644 --- a/core-java-modules/core-java-collections-3/pom.xml +++ b/core-java-modules/core-java-collections-3/pom.xml @@ -35,7 +35,7 @@ org.apache.commons commons-lang3 - 3.10 + ${commons-lang3.version} diff --git a/core-java-modules/core-java-collections-3/src/main/java/com/baeldung/collections/removeallperformance/HashSetBenchmark.java b/core-java-modules/core-java-collections-3/src/main/java/com/baeldung/collections/removeallperformance/HashSetBenchmark.java index 8ce58c865e..8f784de26d 100644 --- a/core-java-modules/core-java-collections-3/src/main/java/com/baeldung/collections/removeallperformance/HashSetBenchmark.java +++ b/core-java-modules/core-java-collections-3/src/main/java/com/baeldung/collections/removeallperformance/HashSetBenchmark.java @@ -33,11 +33,15 @@ public class HashSetBenchmark { private List employeeList1 = new ArrayList<>(); private Set employeeSet2 = new HashSet<>(); private List employeeList2 = new ArrayList<>(); + private Set employeeSet3 = new HashSet<>(); + private Set employeeSet4 = new HashSet<>(); private long set1Size = 60000; private long list1Size = 50000; private long set2Size = 50000; private long list2Size = 60000; + private long set3Size = 50000; + private long set4Size = 60000; @Setup(Level.Trial) public void setUp() { @@ -57,6 +61,14 @@ public class HashSetBenchmark { for (long i = 0; i < list2Size; i++) { employeeList2.add(new Employee(i, RandomStringUtils.random(7, true, false))); } + + for (long i = 0; i < set3Size; i++) { + employeeSet3.add(new Employee(i, RandomStringUtils.random(7, true, false))); + } + + for (long i = 0; i < set4Size; i++) { + employeeSet4.add(new Employee(i, RandomStringUtils.random(7, true, false))); + } } @@ -71,6 +83,11 @@ public class HashSetBenchmark { public boolean given_SizeOfHashsetSmallerThanSizeOfCollection_When_RemoveAllFromHashSet_Then_BadPerformance(MyState state) { return state.employeeSet2.removeAll(state.employeeList2); } + + @Benchmark + public boolean given_SizeOfHashsetSmallerThanSizeOfAnotherHashSet_When_RemoveAllFromHashSet_Then_GoodPerformance(MyState state) { + return state.employeeSet3.removeAll(state.employeeSet4); + } public static void main(String[] args) throws Exception { Options options = new OptionsBuilder().include(HashSetBenchmark.class.getSimpleName()) diff --git a/core-java-modules/core-java-collections-4/README.md b/core-java-modules/core-java-collections-4/README.md new file mode 100644 index 0000000000..6e117c98b1 --- /dev/null +++ b/core-java-modules/core-java-collections-4/README.md @@ -0,0 +1,7 @@ +========= + +## Core Java Collections Cookbooks and Examples + +### Relevant Articles: + +- [ArrayList vs. LinkedList vs. HashMap in Java](https://www.baeldung.com/java-arraylist-vs-linkedlist-vs-hashmap) diff --git a/core-java-modules/core-java-collections-4/pom.xml b/core-java-modules/core-java-collections-4/pom.xml new file mode 100644 index 0000000000..0e3cabf40e --- /dev/null +++ b/core-java-modules/core-java-collections-4/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + core-java-collections-4 + 0.1.0-SNAPSHOT + core-java-collections-4 + jar + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + ../pom.xml + + + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + 3.18.0 + + + diff --git a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/ArrayListUnitTest.java b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/ArrayListUnitTest.java new file mode 100644 index 0000000000..bc6a07d274 --- /dev/null +++ b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/ArrayListUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.collections.comparation; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ArrayListUnitTest { + + @Test + void givenArrayList_whenItemAddedToSpecificIndex_thenItCanBeRetrieved() { + List list = new ArrayList<>(); + list.add("Daniel"); + list.add(0, "Marko"); + assertThat(list).hasSize(2); + assertThat(list.get(0)).isEqualTo("Marko"); + } + + @Test + void givenArrayList_whenItemRemovedViaIndex_thenListSizeIsReduced() { + List list = new ArrayList<>(Arrays.asList("Daniel", "Marko")); + list.remove(1); + assertThat(list).hasSize(1); + assertThat(list).doesNotContain("Marko"); + } + +} diff --git a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/HashMapUnitTest.java b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/HashMapUnitTest.java new file mode 100644 index 0000000000..3b595472e0 --- /dev/null +++ b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/HashMapUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.collections.comparation; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +public class HashMapUnitTest { + + @Test + void givenHashMap_whenItemAddedByKey_thenItCanBeRetrieved() { + Map map = new HashMap<>(); + map.put("123456", "Daniel"); + map.put("654321", "Marko"); + assertThat(map.get("654321")).isEqualTo("Marko"); + } + + @Test + void givenHashMap_whenItemRemovedByKey_thenMapSizeIsReduced() { + Map map = new HashMap<>(); + map.put("123456", "Daniel"); + map.put("654321", "Marko"); + map.remove("654321"); + assertThat(map).hasSize(1); + } + +} diff --git a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/LinkedListUnitTest.java b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/LinkedListUnitTest.java new file mode 100644 index 0000000000..aa6b7fa923 --- /dev/null +++ b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/LinkedListUnitTest.java @@ -0,0 +1,41 @@ +package com.baeldung.collections.comparation; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +public class LinkedListUnitTest { + + @Test + void givenLinkedList_whenItemIsAppended_thenItCanBeRetrieved() { + LinkedList list = new LinkedList<>(); + list.addLast("Daniel"); + list.addFirst("Marko"); + assertThat(list).hasSize(2); + assertThat(list.getLast()).isEqualTo("Daniel"); + } + + @Test + void givenLinkedList_whenItemIsRemoved_thenListSizeIsReduced() { + LinkedList list = new LinkedList<>(Arrays.asList("Daniel", "Marko", "David")); + list.removeFirst(); + list.removeLast(); + assertThat(list).hasSize(1); + assertThat(list).containsExactly("Marko"); + } + + @Test + void givenLinkedList_whenItemInserted_thenItCanBeRetrievedAndDeleted() { + LinkedList list = new LinkedList<>(); + list.push("Daniel"); + list.push("Marko"); + assertThat(list.poll()).isEqualTo("Marko"); + assertThat(list).hasSize(1); + } + +} diff --git a/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/ListVsMapUnitTest.java b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/ListVsMapUnitTest.java new file mode 100644 index 0000000000..dd6bf760fd --- /dev/null +++ b/core-java-modules/core-java-collections-4/src/test/java/com/baeldung/collections/comparation/ListVsMapUnitTest.java @@ -0,0 +1,32 @@ +package com.baeldung.collections.comparation; + +import static org.assertj.core.api.Assertions.*; +import org.junit.jupiter.api.Test; + +import java.util.*; + +class ListVsMapUnitTest { + + @Test + void givenList_whenIteratingTroughValues_thenEachValueIsPresent() { + List list = new ArrayList<>(); + list.add("Daniel"); + list.add("Marko"); + for (String name : list) { + assertThat(name).isIn(list); + } + assertThat(list).containsExactly("Daniel", "Marko"); + } + + @Test + void givenMap_whenIteratingTroughValues_thenEachValueIsPresent() { + Map map = new HashMap<>(); + map.put(1, "Daniel"); + map.put(2, "Marko"); + for (String name : map.values()) { + assertThat(name).isIn(map.values()); + } + assertThat(map.values()).containsExactlyInAnyOrder("Daniel", "Marko"); + } + +} diff --git a/core-java-modules/core-java-collections-array-list/README.md b/core-java-modules/core-java-collections-array-list/README.md index 3637f835cf..d24f7492bb 100644 --- a/core-java-modules/core-java-collections-array-list/README.md +++ b/core-java-modules/core-java-collections-array-list/README.md @@ -8,4 +8,4 @@ This module contains articles about the Java ArrayList collection - [ClassCastException: Arrays$ArrayList cannot be cast to ArrayList](https://www.baeldung.com/java-classcastexception-arrays-arraylist) - [Multi Dimensional ArrayList in Java](https://www.baeldung.com/java-multi-dimensional-arraylist) - [Removing an Element From an ArrayList](https://www.baeldung.com/java-arraylist-remove-element) - +- [The Capacity of an ArrayList vs the Size of an Array in Java](https://www.baeldung.com/java-list-capacity-array-size) diff --git a/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/listcapacityvsarraysize/ArrayCreatorUnitTest.java b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/listcapacityvsarraysize/ArrayCreatorUnitTest.java new file mode 100644 index 0000000000..74c8b93872 --- /dev/null +++ b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/listcapacityvsarraysize/ArrayCreatorUnitTest.java @@ -0,0 +1,20 @@ +package com.baeldung.listcapacityvsarraysize; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class ArrayCreatorUnitTest { + + @Test + void whenSizeOfAnArrayIsNonZero_thenReturnNewArrayOfGivenSize() { + Integer[] array = new Integer[10]; + assertEquals(10, array.length); + } + + @Test + void whenSizeOfAnArrayIsLessThanZero_thenThrowException() { + assertThrows(NegativeArraySizeException.class, () -> { Integer[] array = new Integer[-1]; }); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/listcapacityvsarraysize/ArrayListCreatorUnitTest.java b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/listcapacityvsarraysize/ArrayListCreatorUnitTest.java new file mode 100644 index 0000000000..62efe43af4 --- /dev/null +++ b/core-java-modules/core-java-collections-array-list/src/test/java/com/baeldung/listcapacityvsarraysize/ArrayListCreatorUnitTest.java @@ -0,0 +1,27 @@ +package com.baeldung.listcapacityvsarraysize; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.*; + +class ArrayListCreatorUnitTest { + + @Test + void givenValidCapacityOfList_whenCreateListInvoked_thenCreateNewArrayListWithGivenCapacity() { + ArrayList list = new ArrayList<>(100); + + assertNotNull(list); + } + + @Test + void givenInvalidCapacityOfList_whenCreateListInvoked_thenThrowException() { + assertThrows(IllegalArgumentException.class, () -> new ArrayList<>(-1)); + } + + @Test + void givenValidCapacityOfList_whenCreateListInvoked_thenCreateNewArrayListWithSizeZero() { + assertEquals(0, new ArrayList(100).size()); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-list/pom.xml b/core-java-modules/core-java-collections-list/pom.xml index 509f58ea61..76ca66fe70 100644 --- a/core-java-modules/core-java-collections-list/pom.xml +++ b/core-java-modules/core-java-collections-list/pom.xml @@ -36,7 +36,6 @@ 4.1 - 3.8.1 3.11.1 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 index 5559895730..09b1a8847d 100644 --- 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 @@ -26,7 +26,7 @@ public class Product { return tags; } - public Product addTagsOfOtherProdcut(Product product) { + public Product addTagsOfOtherProduct(Product product) { this.tags.addAll(product.getTags()); return this; } @@ -100,11 +100,11 @@ public class Product { 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); + productsByName.merge("E-Bike", eBike2, Product::addTagsOfOtherProduct); //Prior to Java 8: if(productsByName.containsKey("E-Bike")) { - productsByName.get("E-Bike").addTagsOfOtherProdcut(eBike2); + productsByName.get("E-Bike").addTagsOfOtherProduct(eBike2); } else { productsByName.put("E-Bike", eBike2); } @@ -117,7 +117,7 @@ public class Product { productsByName.compute("E-Bike", (k,v) -> { if(v != null) { - return v.addTagsOfOtherProdcut(eBike2); + return v.addTagsOfOtherProduct(eBike2); } else { return eBike2; } @@ -125,7 +125,7 @@ public class Product { //Prior to Java 8: if(productsByName.containsKey("E-Bike")) { - productsByName.get("E-Bike").addTagsOfOtherProdcut(eBike2); + productsByName.get("E-Bike").addTagsOfOtherProduct(eBike2); } else { productsByName.put("E-Bike", eBike2); } 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 7386f7e9b7..8b84ecbf81 100644 --- a/core-java-modules/core-java-collections-maps-3/README.md +++ b/core-java-modules/core-java-collections-maps-3/README.md @@ -6,4 +6,6 @@ This module contains articles about Map data structures in Java. - [Java TreeMap vs HashMap](https://www.baeldung.com/java-treemap-vs-hashmap) - [Comparing Two HashMaps in Java](https://www.baeldung.com/java-compare-hashmaps) - [The Map.computeIfAbsent() Method](https://www.baeldung.com/java-map-computeifabsent) +- [Collections.synchronizedMap vs. ConcurrentHashMap](https://www.baeldung.com/java-synchronizedmap-vs-concurrenthashmap) +- [Java HashMap Load Factor](https://www.baeldung.com/java-hashmap-load-factor) - More articles: [[<-- prev]](/core-java-modules/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 index f547968b22..c9fda26fc3 100644 --- a/core-java-modules/core-java-collections-maps-3/pom.xml +++ b/core-java-modules/core-java-collections-maps-3/pom.xml @@ -15,7 +15,16 @@ - + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + + + com.google.guava + guava + ${guava.version} + diff --git a/core-java-modules/core-java-collections-maps-3/src/main/java/com/baeldung/map/concurrenthashmap/MapPerformanceComparison.java b/core-java-modules/core-java-collections-maps-3/src/main/java/com/baeldung/map/concurrenthashmap/MapPerformanceComparison.java new file mode 100644 index 0000000000..c788dbc27d --- /dev/null +++ b/core-java-modules/core-java-collections-maps-3/src/main/java/com/baeldung/map/concurrenthashmap/MapPerformanceComparison.java @@ -0,0 +1,96 @@ +package com.baeldung.map.concurrenthashmap; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Threads; +import org.openjdk.jmh.annotations.Warmup; + +@Fork(5) +@Threads(10) +@Warmup(iterations = 5) +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class MapPerformanceComparison { + + private int TEST_NO_ITEMS; + + public static void main(String[] args) throws Exception { + org.openjdk.jmh.Main.main(args); + } + + @Setup + public void setup() { + TEST_NO_ITEMS = 1000; + } + + @Benchmark + public void randomReadAndWriteSynchronizedMap() { + Map map = Collections.synchronizedMap(new HashMap()); + performReadAndWriteTest(map); + } + + @Benchmark + public void randomReadAndWriteConcurrentHashMap() { + Map map = new ConcurrentHashMap<>(); + performReadAndWriteTest(map); + } + + private void performReadAndWriteTest(final Map map) { + for (int i = 0; i < TEST_NO_ITEMS; i++) { + Integer randNumber = (int) Math.ceil(Math.random() * TEST_NO_ITEMS); + map.get(String.valueOf(randNumber)); + map.put(String.valueOf(randNumber), randNumber); + } + } + + @Benchmark + public void randomWriteSynchronizedMap() { + Map map = Collections.synchronizedMap(new HashMap()); + performWriteTest(map); + } + + @Benchmark + public void randomWriteConcurrentHashMap() { + Map map = new ConcurrentHashMap<>(); + performWriteTest(map); + } + + private void performWriteTest(final Map map) { + for (int i = 0; i < TEST_NO_ITEMS; i++) { + Integer randNumber = (int) Math.ceil(Math.random() * TEST_NO_ITEMS); + map.put(String.valueOf(randNumber), randNumber); + } + } + + @Benchmark + public void randomReadSynchronizedMap() { + Map map = Collections.synchronizedMap(new HashMap()); + performReadTest(map); + } + + @Benchmark + public void randomReadConcurrentHashMap() { + Map map = new ConcurrentHashMap<>(); + performReadTest(map); + } + + private void performReadTest(final Map map) { + for (int i = 0; i < TEST_NO_ITEMS; i++) { + Integer randNumber = (int) Math.ceil(Math.random() * TEST_NO_ITEMS); + map.get(String.valueOf(randNumber)); + } + } +} diff --git a/core-java-modules/core-java-collections-maps-3/src/main/java/com/baeldung/map/propertieshashmap/PropertiesToHashMapConverter.java b/core-java-modules/core-java-collections-maps-3/src/main/java/com/baeldung/map/propertieshashmap/PropertiesToHashMapConverter.java new file mode 100644 index 0000000000..3472f998f5 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-3/src/main/java/com/baeldung/map/propertieshashmap/PropertiesToHashMapConverter.java @@ -0,0 +1,39 @@ +package com.baeldung.map.propertieshashmap; + +import com.google.common.collect.Maps; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.stream.Collectors; + +public class PropertiesToHashMapConverter { + + @SuppressWarnings({"rawtypes", "unchecked"}) + public static HashMap typeCastConvert(Properties prop) { + Map step1 = prop; + Map step2 = (Map) step1; + return new HashMap<>(step2); + } + + public static HashMap loopConvert(Properties prop) { + HashMap retMap = new HashMap<>(); + for (Map.Entry entry : prop.entrySet()) { + retMap.put(String.valueOf(entry.getKey()), String.valueOf(entry.getValue())); + } + return retMap; + } + + public static HashMap streamConvert(Properties prop) { + return prop.entrySet().stream().collect( + Collectors.toMap( + e -> String.valueOf(e.getKey()), + e -> String.valueOf(e.getValue()), + (prev, next) -> next, HashMap::new + )); + } + + public static HashMap guavaConvert(Properties prop) { + return Maps.newHashMap(Maps.fromProperties(prop)); + } +} diff --git a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/ConcurrentModificationErrorUnitTest.java b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/ConcurrentModificationErrorUnitTest.java new file mode 100644 index 0000000000..4264e613f2 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/ConcurrentModificationErrorUnitTest.java @@ -0,0 +1,70 @@ +package com.baeldung.map.concurrenthashmap; + +import java.util.Collections; +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; + +import org.junit.Assert; +import org.junit.Test; + +public class ConcurrentModificationErrorUnitTest { + + @Test(expected = ConcurrentModificationException.class) + public void whenRemoveAndAddOnHashMap_thenConcurrentModificationError() { + Map map = new HashMap<>(); + map.put(1, "baeldung"); + map.put(2, "HashMap"); + Map synchronizedMap = Collections.synchronizedMap(map); + Iterator> iterator = synchronizedMap.entrySet().iterator(); + while (iterator.hasNext()) { + synchronizedMap.put(3, "Modification"); + iterator.next(); + } + } + + @Test(expected = ConcurrentModificationException.class) + public void whenRemoveAndAddOnTreeMap_thenConcurrentModificationError() { + Map map = new TreeMap<>(); + map.put(1, "baeldung"); + map.put(2, "HashMap"); + Map synchronizedMap = Collections.synchronizedMap(map); + Iterator> iterator = synchronizedMap.entrySet().iterator(); + while (iterator.hasNext()) { + synchronizedMap.put(3, "Modification"); + iterator.next(); + } + } + + @Test(expected = ConcurrentModificationException.class) + public void whenRemoveAndAddOnLinkedHashMap_thenConcurrentModificationError() { + Map map = new LinkedHashMap<>(); + map.put(1, "baeldung"); + map.put(2, "HashMap"); + Map synchronizedMap = Collections.synchronizedMap(map); + Iterator> iterator = synchronizedMap.entrySet().iterator(); + while (iterator.hasNext()) { + synchronizedMap.put(3, "Modification"); + iterator.next(); + } + } + + @Test + public void whenRemoveAndAddOnConcurrentHashMap_thenNoError() { + Map map = new ConcurrentHashMap<>(); + map.put(1, "baeldung"); + map.put(2, "HashMap"); + Iterator> iterator = map.entrySet().iterator(); + while (iterator.hasNext()) { + map.put(3, "Modification"); + iterator.next(); + } + + Assert.assertEquals(3, map.size()); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/NullAllowInMapUnitTest.java b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/NullAllowInMapUnitTest.java new file mode 100644 index 0000000000..594e8ec3b4 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/concurrenthashmap/NullAllowInMapUnitTest.java @@ -0,0 +1,73 @@ +package com.baeldung.map.concurrenthashmap; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.TreeMap; +import java.util.concurrent.ConcurrentHashMap; + +import org.junit.Assert; +import org.junit.Test; + +public class NullAllowInMapUnitTest { + + @Test + public void givenHashMapBackedSynchronizedMap_whenNullAsKey_thenNoError() { + Map map = Collections + .synchronizedMap(new HashMap()); + map.put(null, 1); + Assert.assertTrue(map.get(null).equals(1)); + } + + + @Test(expected = NullPointerException.class) + public void givenTreeMapBackedSynchronizedMap_whenNullAsKey_thenException() { + Map map = Collections.synchronizedMap(new TreeMap()); + map.put(null, 1); + Assert.assertTrue(map.get(null).equals(1)); + } + + @Test + public void givenLinkedHashMapBackedSynchronizedMap_whenNullAsKey_thenNoError() { + Map map = Collections + .synchronizedMap(new LinkedHashMap()); + map.put(null, 1); + Assert.assertTrue(map.get(null).equals(1)); + } + + @Test(expected = NullPointerException.class) + public void givenConcurrentHasMap_whenNullAsKey_thenException() { + Map map = new ConcurrentHashMap<>(); + map.put(null, 1); + } + + @Test + public void givenHashMapBackedSynchronizedMap_whenNullAsValue_thenNoError() { + Map map = Collections.synchronizedMap(new HashMap()); + map.put("1", null); + Assert.assertNull(map.get("1")); + } + + @Test + public void givenTreeMapBackedSynchronizedMap_whenNullAsValue_thenNoError() { + Map map = Collections.synchronizedMap(new TreeMap()); + map.put("1", null); + Assert.assertNull(map.get("1")); + } + + @Test + public void givenLinkedHashMapBackedSynchronizedMap_whenNullAsValue_thenNoError() { + Map map = Collections + .synchronizedMap(new LinkedHashMap()); + map.put("1", null); + Assert.assertNull(map.get("1")); + } + + @Test(expected = NullPointerException.class) + public void givenConcurrentHasMap_whenNullAsValue_thenException() { + Map map = new ConcurrentHashMap<>(); + map.put("1", null); + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/hashmap/loadfactor/HashMapLoadFactorUnitTest.java b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/hashmap/loadfactor/HashMapLoadFactorUnitTest.java new file mode 100644 index 0000000000..94967a4905 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/hashmap/loadfactor/HashMapLoadFactorUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung.map.hashmap.loadfactor; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +public class HashMapLoadFactorUnitTest { + + @Test + public void whenCreateMapWithDefaultParam_thenSucces() { + Map mapWithDefaultParams = new HashMap<>(); + mapWithDefaultParams.put("1", "one"); + mapWithDefaultParams.put("2", "two"); + mapWithDefaultParams.put("3", "three"); + mapWithDefaultParams.put("4", "four"); + mapWithDefaultParams.put("5", "five"); + + Assert.assertEquals(5, mapWithDefaultParams.size()); + } + + @Test + public void whenCreateMapWithInitialCapacity_thenSucces() { + Map mapWithInitialCapacity = new HashMap<>(5); + mapWithInitialCapacity.put("1", "one"); + mapWithInitialCapacity.put("2", "two"); + mapWithInitialCapacity.put("3", "three"); + + Assert.assertEquals(3, mapWithInitialCapacity.size()); + } + + @Test + public void whenCreateMapWithInitialCapacityAndLF_thenSucces() { + Map mapWithInitialCapacityAndLF = new HashMap<>(5, 0.5f); + mapWithInitialCapacityAndLF.put("1", "one"); + mapWithInitialCapacityAndLF.put("2", "two"); + mapWithInitialCapacityAndLF.put("3", "three"); + mapWithInitialCapacityAndLF.put("4", "four"); + mapWithInitialCapacityAndLF.put("5", "five"); + mapWithInitialCapacityAndLF.put("6", "six"); + mapWithInitialCapacityAndLF.put("7", "seven"); + mapWithInitialCapacityAndLF.put("8", "eight"); + mapWithInitialCapacityAndLF.put("9", "nine"); + mapWithInitialCapacityAndLF.put("10", "ten"); + + Assert.assertEquals(10, mapWithInitialCapacityAndLF.size()); + } +} diff --git a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/propertieshashmap/PropertiesToHashMapConverterUnitTest.java b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/propertieshashmap/PropertiesToHashMapConverterUnitTest.java new file mode 100644 index 0000000000..1985fbe673 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/propertieshashmap/PropertiesToHashMapConverterUnitTest.java @@ -0,0 +1,192 @@ +package com.baeldung.map.propertieshashmap; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Properties; + +import static org.junit.jupiter.api.Assertions.*; + +class PropertiesToHashMapConverterUnitTest { + + private Properties properties; + + private final static String propertyFileName = "toHashMap.properties"; + + @BeforeEach + public void setup() throws IOException { + properties = new Properties(); + try (InputStream is = getClass().getClassLoader().getResourceAsStream(propertyFileName)) { + if (is != null) { + properties.load(is); + } + } + } + + @Test + public void havingPropertiesLoaded_whenCheck_thenEquals() { + assertEquals(3, properties.size()); + assertEquals("str_value", properties.get("property1")); + assertEquals("123", properties.get("property2")); + assertEquals("", properties.get("property3")); + } + + @Test + public void whenPropertiesModified_thenTypeSafeIssues() { + compromiseProperties(properties); + + assertEquals(5, properties.size()); + + assertNull(properties.getProperty("property4")); + assertNotEquals(String.class, properties.get("property4").getClass()); + assertEquals(456, properties.get("property4")); + + + assertNull(properties.getProperty("5")); + assertNotEquals(String.class, properties.get(5).getClass()); + assertEquals(10.11, properties.get(5)); + } + + @Test + public void havingNonModifiedProperties_whenTypeCastConvert_thenNoTypeSafeIssues() { + HashMap hMap = PropertiesToHashMapConverter.typeCastConvert(properties); + + assertEquals(3, hMap.size()); + assertEquals(String.class, hMap.get("property1").getClass()); + assertEquals(properties.get("property1"), hMap.get("property1")); + assertEquals(String.class, hMap.get("property2").getClass()); + assertEquals(properties.get("property2"), hMap.get("property2")); + assertEquals(String.class, hMap.get("property3").getClass()); + assertEquals(properties.get("property3"), hMap.get("property3")); + } + + @Test + public void havingModifiedProperties_whenTypeCastConvert_thenClassCastException() { + compromiseProperties(properties); + HashMap hMap = PropertiesToHashMapConverter.typeCastConvert(properties); + assertEquals(5, hMap.size()); + + assertThrows(ClassCastException.class, () -> { + String s = hMap.get("property4"); + }); + assertEquals(Integer.class, ((Object) hMap.get("property4")).getClass()); + + assertNull(hMap.get("5")); + assertNotNull(hMap.get(5)); + assertThrows(ClassCastException.class, () -> { + String s = hMap.get(5); + }); + assertEquals(Double.class, ((Object) hMap.get(5)).getClass()); + } + + @Test + public void havingNonModifiedProperties_whenLoopConvert_thenNoTypeSafeIssues() { + HashMap hMap = PropertiesToHashMapConverter.loopConvert(properties); + + assertEquals(3, hMap.size()); + assertEquals(String.class, hMap.get("property1").getClass()); + assertEquals(properties.get("property1"), hMap.get("property1")); + assertEquals(String.class, hMap.get("property2").getClass()); + assertEquals(properties.get("property2"), hMap.get("property2")); + assertEquals(String.class, hMap.get("property3").getClass()); + assertEquals(properties.get("property3"), hMap.get("property3")); + } + + @Test + public void havingModifiedProperties_whenLoopConvert_thenNoClassCastException() { + compromiseProperties(properties); + HashMap hMap = PropertiesToHashMapConverter.loopConvert(properties); + assertEquals(5, hMap.size()); + + assertDoesNotThrow(() -> { + String s = hMap.get("property4"); + }); + assertEquals(String.class, hMap.get("property4").getClass()); + assertEquals("456", hMap.get("property4")); + + assertDoesNotThrow(() -> { + String s = hMap.get("5"); + }); + assertEquals("10.11", hMap.get("5")); + } + + @Test + public void havingNonModifiedProperties_whenStreamConvert_thenNoTypeSafeIssues() { + HashMap hMap = PropertiesToHashMapConverter.streamConvert(properties); + + assertEquals(3, hMap.size()); + assertEquals(String.class, hMap.get("property1").getClass()); + assertEquals(properties.get("property1"), hMap.get("property1")); + assertEquals(String.class, hMap.get("property2").getClass()); + assertEquals(properties.get("property2"), hMap.get("property2")); + assertEquals(String.class, hMap.get("property3").getClass()); + assertEquals(properties.get("property3"), hMap.get("property3")); + } + + @Test + public void havingModifiedProperties_whenStreamConvert_thenNoClassCastException() { + compromiseProperties(properties); + HashMap hMap = PropertiesToHashMapConverter.streamConvert(properties); + assertEquals(5, hMap.size()); + + assertDoesNotThrow(() -> { + String s = hMap.get("property4"); + }); + assertEquals(String.class, hMap.get("property4").getClass()); + assertEquals("456", hMap.get("property4")); + + assertDoesNotThrow(() -> { + String s = hMap.get("5"); + }); + assertEquals("10.11", hMap.get("5")); + } + + @Test + public void havingModifiedProperties_whenLoopConvertAndStreamConvert_thenHashMapsSame() { + compromiseProperties(properties); + HashMap hMap1 = PropertiesToHashMapConverter.loopConvert(properties); + HashMap hMap2 = PropertiesToHashMapConverter.streamConvert(properties); + + assertEquals(hMap2, hMap1); + } + + @Test + public void havingNonModifiedProperties_whenGuavaConvert_thenNoTypeSafeIssues() { + HashMap hMap = PropertiesToHashMapConverter.guavaConvert(properties); + + assertEquals(3, hMap.size()); + assertEquals(String.class, hMap.get("property1").getClass()); + assertEquals(properties.get("property1"), hMap.get("property1")); + assertEquals(String.class, hMap.get("property2").getClass()); + assertEquals(properties.get("property2"), hMap.get("property2")); + assertEquals(String.class, hMap.get("property3").getClass()); + assertEquals(properties.get("property3"), hMap.get("property3")); + } + + @Test + public void havingModifiedProperties_whenGuavaConvert_thenUnableToConvertAndThrowException() { + compromiseProperties(properties); + assertThrows(Exception.class, () -> PropertiesToHashMapConverter.guavaConvert(properties)); + } + + @Test + public void havingModifiedPropertiesWithNoIntegerValue_whenGuavaConvert_thenNullPointerException() { + properties.put("property4", 456); + assertThrows(NullPointerException.class, () -> PropertiesToHashMapConverter.guavaConvert(properties)); + } + + @Test + public void havingModifiedPropertiesWithNoIntegerKey_whenGuavaConvert_thenClassCastException() { + properties.put(5, 10.11); + assertThrows(ClassCastException.class, () -> PropertiesToHashMapConverter.guavaConvert(properties)); + } + + + private void compromiseProperties(Properties prop) { + prop.put("property4", 456); + prop.put(5, 10.11); + } +} diff --git a/core-java-modules/core-java-collections-maps-3/src/test/resources/toHashMap.properties b/core-java-modules/core-java-collections-maps-3/src/test/resources/toHashMap.properties new file mode 100644 index 0000000000..727e858a8c --- /dev/null +++ b/core-java-modules/core-java-collections-maps-3/src/test/resources/toHashMap.properties @@ -0,0 +1,3 @@ +property1=str_value +property2=123 +property3= diff --git a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterJCStressUnitTest.java b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterJCStressManualTest.java similarity index 74% rename from core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterJCStressUnitTest.java rename to core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterJCStressManualTest.java index 6c76505347..0e6b41d1e9 100644 --- a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterJCStressUnitTest.java +++ b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterJCStressManualTest.java @@ -10,11 +10,17 @@ import org.openjdk.jcstress.annotations.Outcome; import org.openjdk.jcstress.annotations.State; import org.openjdk.jcstress.infra.results.I_Result; +/** + * This is defined as a manual test because it tries to simulate the race conditions + * in a concurrent program that is poorly designed and hence may fail nondeterministically. + * This will help the CI jobs to ignore these tests and a developer to run them manually. + * + */ @JCStressTest @Outcome(id = "1", expect = ACCEPTABLE_INTERESTING, desc = "One update lost.") @Outcome(id = "2", expect = ACCEPTABLE, desc = "Both updates.") @State -public class MyCounterJCStressUnitTest { +public class MyCounterJCStressManualTest { private MyCounter counter; diff --git a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterMultithreadedTCUnitTest.java b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterMultithreadedTCManualTest.java similarity index 59% rename from core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterMultithreadedTCUnitTest.java rename to core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterMultithreadedTCManualTest.java index 8a0bedf6c2..985e316635 100644 --- a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterMultithreadedTCUnitTest.java +++ b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterMultithreadedTCManualTest.java @@ -1,12 +1,17 @@ package com.baeldung.concurrent; -import org.junit.Ignore; import org.junit.Test; import edu.umd.cs.mtc.MultithreadedTestCase; import edu.umd.cs.mtc.TestFramework; -public class MyCounterMultithreadedTCUnitTest extends MultithreadedTestCase { +/** + * This is defined as a manual test because it tries to simulate the race conditions + * in a concurrent program that is poorly designed and hence may fail nondeterministically. + * This will help the CI jobs to ignore these tests and a developer to run them manually. + * + */ +public class MyCounterMultithreadedTCManualTest extends MultithreadedTestCase { private MyCounter counter; @@ -29,9 +34,8 @@ public class MyCounterMultithreadedTCUnitTest extends MultithreadedTestCase { assertEquals(2, counter.getCount()); } - @Ignore @Test public void testCounter() throws Throwable { - TestFramework.runManyTimes(new MyCounterMultithreadedTCUnitTest(), 1000); + TestFramework.runManyTimes(new MyCounterMultithreadedTCManualTest(), 1000); } } diff --git a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterSimpleManualTest.java b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterSimpleManualTest.java new file mode 100644 index 0000000000..cba30da34b --- /dev/null +++ b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterSimpleManualTest.java @@ -0,0 +1,63 @@ +package com.baeldung.concurrent; + +import static org.junit.Assert.assertEquals; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.junit.Test; + +/** + * This is defined as a manual test because it tries to simulate the race conditions + * in a concurrent program that is poorly designed and hence may fail nondeterministically. + * This will help the CI jobs to ignore these tests and a developer to run them manually. + * + */ +public class MyCounterSimpleManualTest { + + @Test + public void testCounter() { + MyCounter counter = new MyCounter(); + for (int i = 0; i < 500; i++) + counter.increment(); + assertEquals(500, counter.getCount()); + } + + @Test + public void testCounterWithConcurrency() throws InterruptedException { + int numberOfThreads = 100; + ExecutorService service = Executors.newFixedThreadPool(10); + CountDownLatch latch = new CountDownLatch(numberOfThreads); + MyCounter counter = new MyCounter(); + for (int i = 0; i < numberOfThreads; i++) { + service.execute(() -> { + counter.increment(); + latch.countDown(); + }); + } + latch.await(); + assertEquals(numberOfThreads, counter.getCount()); + } + + @Test + public void testSummationWithConcurrencyAndWait() throws InterruptedException { + int numberOfThreads = 2; + ExecutorService service = Executors.newFixedThreadPool(10); + CountDownLatch latch = new CountDownLatch(numberOfThreads); + MyCounter counter = new MyCounter(); + for (int i = 0; i < numberOfThreads; i++) { + service.submit(() -> { + try { + counter.incrementWithWait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + latch.countDown(); + }); + } + latch.await(); + assertEquals(numberOfThreads, counter.getCount()); + } + +} diff --git a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterSimpleUnitTest.java b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterSimpleUnitTest.java deleted file mode 100644 index 9a405e7e24..0000000000 --- a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterSimpleUnitTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.baeldung.concurrent; - -import static org.junit.Assert.assertEquals; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import org.junit.Ignore; -import org.junit.Test; - -public class MyCounterSimpleUnitTest { - - @Test - public void testCounter() { - MyCounter counter = new MyCounter(); - for (int i = 0; i < 500; i++) - counter.increment(); - assertEquals(500, counter.getCount()); - } - - @Ignore - @Test - public void testCounterWithConcurrency() throws InterruptedException { - int numberOfThreads = 100; - ExecutorService service = Executors.newFixedThreadPool(10); - CountDownLatch latch = new CountDownLatch(numberOfThreads); - MyCounter counter = new MyCounter(); - for (int i = 0; i < numberOfThreads; i++) { - service.execute(() -> { - counter.increment(); - latch.countDown(); - }); - } - latch.await(); - assertEquals(numberOfThreads, counter.getCount()); - } - - @Ignore - @Test - public void testSummationWithConcurrencyAndWait() throws InterruptedException { - int numberOfThreads = 2; - ExecutorService service = Executors.newFixedThreadPool(10); - CountDownLatch latch = new CountDownLatch(numberOfThreads); - MyCounter counter = new MyCounter(); - for (int i = 0; i < numberOfThreads; i++) { - service.submit(() -> { - try { - counter.incrementWithWait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - latch.countDown(); - }); - } - latch.await(); - assertEquals(numberOfThreads, counter.getCount()); - } - -} diff --git a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterTempusFugitManualTest.java b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterTempusFugitManualTest.java new file mode 100644 index 0000000000..a4ac643f7e --- /dev/null +++ b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterTempusFugitManualTest.java @@ -0,0 +1,41 @@ +package com.baeldung.concurrent; + +import static org.junit.Assert.assertEquals; + +import org.junit.AfterClass; +import org.junit.Rule; +import org.junit.Test; + +import com.google.code.tempusfugit.concurrency.ConcurrentRule; +import com.google.code.tempusfugit.concurrency.RepeatingRule; +import com.google.code.tempusfugit.concurrency.annotations.Concurrent; +import com.google.code.tempusfugit.concurrency.annotations.Repeating; + +/** + * This is defined as a manual test because it tries to simulate the race conditions + * in a concurrent program that is poorly designed and hence may fail nondeterministically. + * This will help the CI jobs to ignore these tests and a developer to run them manually. + * + */ +public class MyCounterTempusFugitManualTest { + + @Rule + public ConcurrentRule concurrently = new ConcurrentRule(); + @Rule + public RepeatingRule rule = new RepeatingRule(); + + private static MyCounter counter = new MyCounter(); + + @Test + @Concurrent(count = 2) + @Repeating(repetition = 10) + public void runsMultipleTimes() { + counter.increment(); + } + + @AfterClass + public static void annotatedTestRunsMultipleTimes() throws InterruptedException { + assertEquals(counter.getCount(), 20); + } + +} diff --git a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterTempusFugitUnitTest.java b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterTempusFugitUnitTest.java deleted file mode 100644 index 36a2031e78..0000000000 --- a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterTempusFugitUnitTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.baeldung.concurrent; - -import static org.junit.Assert.assertEquals; - -import org.junit.AfterClass; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; - -import com.google.code.tempusfugit.concurrency.ConcurrentRule; -import com.google.code.tempusfugit.concurrency.RepeatingRule; -import com.google.code.tempusfugit.concurrency.annotations.Concurrent; -import com.google.code.tempusfugit.concurrency.annotations.Repeating; - -public class MyCounterTempusFugitUnitTest { - - @Rule - public ConcurrentRule concurrently = new ConcurrentRule(); - @Rule - public RepeatingRule rule = new RepeatingRule(); - - private static MyCounter counter = new MyCounter(); - - @Ignore - @Test - @Concurrent(count = 2) - @Repeating(repetition = 10) - public void runsMultipleTimes() { - counter.increment(); - } - - @AfterClass - public static void annotatedTestRunsMultipleTimes() throws InterruptedException { - assertEquals(counter.getCount(), 20); - } - -} diff --git a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterThreadWeaverManualTest.java b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterThreadWeaverManualTest.java new file mode 100644 index 0000000000..2acfc4ee71 --- /dev/null +++ b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterThreadWeaverManualTest.java @@ -0,0 +1,48 @@ +package com.baeldung.concurrent; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.google.testing.threadtester.AnnotatedTestRunner; +import com.google.testing.threadtester.ThreadedAfter; +import com.google.testing.threadtester.ThreadedBefore; +import com.google.testing.threadtester.ThreadedMain; +import com.google.testing.threadtester.ThreadedSecondary; + +/** + * This is defined as a manual test because it tries to simulate the race conditions + * in a concurrent program that is poorly designed and hence may fail nondeterministically. + * This will help the CI jobs to ignore these tests and a developer to run them manually. + * + */ +public class MyCounterThreadWeaverManualTest { + + private MyCounter counter; + + @ThreadedBefore + public void before() { + counter = new MyCounter(); + } + + @ThreadedMain + public void mainThread() { + counter.increment(); + } + + @ThreadedSecondary + public void secondThread() { + counter.increment(); + } + + @ThreadedAfter + public void after() { + assertEquals(2, counter.getCount()); + } + + @Test + public void testCounter() { + new AnnotatedTestRunner().runTests(this.getClass(), MyCounter.class); + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterThreadWeaverUnitTest.java b/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterThreadWeaverUnitTest.java deleted file mode 100644 index e65a963584..0000000000 --- a/core-java-modules/core-java-concurrency-2/src/test/java/com/baeldung/concurrent/MyCounterThreadWeaverUnitTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.baeldung.concurrent; - -import static org.junit.Assert.assertEquals; - -import org.junit.Ignore; -import org.junit.Test; - -import com.google.testing.threadtester.AnnotatedTestRunner; -import com.google.testing.threadtester.ThreadedAfter; -import com.google.testing.threadtester.ThreadedBefore; -import com.google.testing.threadtester.ThreadedMain; -import com.google.testing.threadtester.ThreadedSecondary; - -public class MyCounterThreadWeaverUnitTest { - - private MyCounter counter; - - @ThreadedBefore - public void before() { - counter = new MyCounter(); - } - - @ThreadedMain - public void mainThread() { - counter.increment(); - } - - @ThreadedSecondary - public void secondThread() { - counter.increment(); - } - - @ThreadedAfter - public void after() { - assertEquals(2, counter.getCount()); - } - - @Ignore - @Test - public void testCounter() { - new AnnotatedTestRunner().runTests(this.getClass(), MyCounter.class); - } - -} \ No newline at end of file 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 7d98e462d7..9495d5f479 100644 --- a/core-java-modules/core-java-concurrency-advanced-3/README.md +++ b/core-java-modules/core-java-concurrency-advanced-3/README.md @@ -13,7 +13,7 @@ This module contains articles about advanced topics about multithreading with co - [Java Thread Deadlock and Livelock](https://www.baeldung.com/java-deadlock-livelock) - [Guide to AtomicStampedReference in Java](https://www.baeldung.com/java-atomicstampedreference) - [The ABA Problem in Concurrency](https://www.baeldung.com/cs/aba-concurrency) -- [Introduction to Lock-Free Data Structures](https://www.baeldung.com/lock-free-programming) +- [Introduction to Lock-Free Data Structures with Java Examples](https://www.baeldung.com/lock-free-programming) - [Introduction to Exchanger in Java](https://www.baeldung.com/java-exchanger) - [Why Not To Start A Thread In The Constructor?](https://www.baeldung.com/java-thread-constructor) - [[<-- previous]](/core-java-modules/core-java-concurrency-advanced-2) diff --git a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/deadlockAndLivelock/LivelockExample.java b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/deadlockAndLivelock/LivelockExample.java index b0d66a92c2..7c3ea6f94e 100644 --- a/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/deadlockAndLivelock/LivelockExample.java +++ b/core-java-modules/core-java-concurrency-advanced-3/src/main/java/com/baeldung/deadlockAndLivelock/LivelockExample.java @@ -73,7 +73,7 @@ public class LivelockExample { public void tryLock(Lock lock, long millis) { try { - lock.tryLock(10, TimeUnit.MILLISECONDS); + lock.tryLock(millis, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { e.printStackTrace(); } diff --git a/core-java-modules/core-java-concurrency-advanced-4/README.md b/core-java-modules/core-java-concurrency-advanced-4/README.md new file mode 100644 index 0000000000..5b93cec0dd --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/README.md @@ -0,0 +1,4 @@ +### Relevant Articles: + +- [Binary Semaphore vs Reentrant Lock](https://www.baeldung.com/java-binary-semaphore-vs-reentrant-lock) +- [Bad Practices With Synchronization](https://www.baeldung.com/java-synchronization-bad-practices) diff --git a/core-java-modules/core-java-concurrency-advanced-4/pom.xml b/core-java-modules/core-java-concurrency-advanced-4/pom.xml new file mode 100644 index 0000000000..eb9ed3adc1 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/pom.xml @@ -0,0 +1,47 @@ + + + + 4.0.0 + core-java-concurrency-advanced-4 + 0.1.0-SNAPSHOT + core-java-concurrency-advanced-4 + jar + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + ../ + + + + + + + core-java-concurrency-advanced-4 + + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + src/main/resources + true + + + + + + 1.8 + 1.8 + + + diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/synchronizationbadpractices/AnimalBadPractice.java b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/synchronizationbadpractices/AnimalBadPractice.java new file mode 100644 index 0000000000..ca6b7db765 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/synchronizationbadpractices/AnimalBadPractice.java @@ -0,0 +1,35 @@ +package com.baeldung.synchronizationbadpractices; + +public class AnimalBadPractice { + + private String name; + private String owner; + + public String getName() { + return name; + } + + public String getOwner() { + return owner; + } + + public synchronized void setName(String name) { + this.name = name; + } + + public void setOwner(String owner) { + synchronized(this) { + this.owner = owner; + } + } + + public AnimalBadPractice() { + + } + + public AnimalBadPractice(String name, String owner) { + this.name = name; + this.owner = owner; + } + +} diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/synchronizationbadpractices/AnimalSolution.java b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/synchronizationbadpractices/AnimalSolution.java new file mode 100644 index 0000000000..b49cfa05d4 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/synchronizationbadpractices/AnimalSolution.java @@ -0,0 +1,42 @@ +package com.baeldung.synchronizationbadpractices; + +public class AnimalSolution { + + private final Object objLock1 = new Object(); + private final Object objLock2 = new Object(); + + private String name; + private String owner; + + public String getName() { + return name; + } + + public String getOwner() { + return owner; + } + + + public void setName(String name) { + synchronized(objLock1) { + this.name = name; + } + } + + public void setOwner(String owner) { + synchronized(objLock2) { + this.owner = owner; + } + } + + public AnimalSolution() { + + } + + public AnimalSolution(String name, String owner) { + this.name = name; + this.owner = owner; + } + + +} \ No newline at end of file diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/synchronizationbadpractices/SynchronizationBadPracticeExample.java b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/synchronizationbadpractices/SynchronizationBadPracticeExample.java new file mode 100644 index 0000000000..84d2e1cbb6 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/synchronizationbadpractices/SynchronizationBadPracticeExample.java @@ -0,0 +1,51 @@ +package com.baeldung.synchronizationbadpractices; + +public class SynchronizationBadPracticeExample { + + public void stringBadPractice1() { + String stringLock = "LOCK_STRING"; + synchronized (stringLock) { + // ... + } + } + + private final String stringLock = "LOCK_STRING"; + public void stringBadPractice2() { + synchronized (stringLock) { + // ... + } + } + + private final String internedStringLock = new String("LOCK_STRING").intern(); + public void stringBadPractice3() { + synchronized (internedStringLock) { + // ... + } + } + + private final Boolean booleanLock = Boolean.FALSE; + public void booleanBadPractice() { + synchronized (booleanLock) { + // ... + } + } + + private int count = 0; + private final Integer intLock = count; + public void boxedPrimitiveBadPractice() { + synchronized (intLock) { + count++; + // ... + } + } + + public void classBadPractice() throws InterruptedException { + AnimalBadPractice animalObj = new AnimalBadPractice("Tommy", "John"); + synchronized(animalObj) { + while (true) { + Thread.sleep(Integer.MAX_VALUE); + } + } + } + +} diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/synchronizationbadpractices/SynchronizationSolutionExample.java b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/synchronizationbadpractices/SynchronizationSolutionExample.java new file mode 100644 index 0000000000..a3ab8a2cee --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/src/main/java/com/baeldung/synchronizationbadpractices/SynchronizationSolutionExample.java @@ -0,0 +1,30 @@ +package com.baeldung.synchronizationbadpractices; + +public class SynchronizationSolutionExample { + + private final String stringLock = new String("LOCK_STRING"); + public void stringSolution() { + synchronized (stringLock) { + // ... + } + } + + private int count = 0; + private final Integer intLock = new Integer(count); + public void boxedPrimitiveSolution() { + synchronized(intLock) { + count++; + // ... + } + } + + private static int staticCount = 0; + private static final Object staticObjLock = new Object(); + public void staticVariableSolution() { + synchronized(staticObjLock) { + staticCount++; + // ... + } + } + +} diff --git a/core-java-modules/core-java-concurrency-advanced-4/src/test/java/com/baeldung/binarysemaphorereentrantlock/BinarySemaphoreVsReentrantLockUnitTest.java b/core-java-modules/core-java-concurrency-advanced-4/src/test/java/com/baeldung/binarysemaphorereentrantlock/BinarySemaphoreVsReentrantLockUnitTest.java new file mode 100644 index 0000000000..f456e82f39 --- /dev/null +++ b/core-java-modules/core-java-concurrency-advanced-4/src/test/java/com/baeldung/binarysemaphorereentrantlock/BinarySemaphoreVsReentrantLockUnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung.binarysemaphorereentrantlock; + +import static org.junit.Assert.assertEquals; +import java.util.concurrent.Semaphore; +import java.util.concurrent.locks.ReentrantLock; + +import org.junit.Test; + +public class BinarySemaphoreVsReentrantLockUnitTest { + + @Test + public void givenBinarySemaphore_whenAcquireAndRelease_thenCheckAvailablePermits() throws InterruptedException { + Semaphore binarySemaphore = new Semaphore(1); + try { + binarySemaphore.acquire(); + assertEquals(0, binarySemaphore.availablePermits()); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + binarySemaphore.release(); + assertEquals(1, binarySemaphore.availablePermits()); + } + } + + @Test + public void givenReentrantLock_whenLockAndUnlock_thenCheckHoldCountAndIsLocked() throws InterruptedException { + ReentrantLock reentrantLock = new ReentrantLock(); + try { + reentrantLock.lock(); + assertEquals(1, reentrantLock.getHoldCount()); + assertEquals(true, reentrantLock.isLocked()); + } finally { + reentrantLock.unlock(); + assertEquals(0, reentrantLock.getHoldCount()); + assertEquals(false, reentrantLock.isLocked()); + } + } + + @Test + public void givenReentrantLock_whenLockMultipleTimes_thenUnlockMultipleTimesToRelease() throws InterruptedException { + ReentrantLock reentrantLock = new ReentrantLock(); + try { + reentrantLock.lock(); + reentrantLock.lock(); + assertEquals(2, reentrantLock.getHoldCount()); + assertEquals(true, reentrantLock.isLocked()); + } finally { + reentrantLock.unlock(); + assertEquals(1, reentrantLock.getHoldCount()); + assertEquals(true, reentrantLock.isLocked()); + + reentrantLock.unlock(); + assertEquals(0, reentrantLock.getHoldCount()); + assertEquals(false, reentrantLock.isLocked()); + } + } + +} 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 a8daf14ea9..bf973f7036 100644 --- a/core-java-modules/core-java-concurrency-basic-2/README.md +++ b/core-java-modules/core-java-concurrency-basic-2/README.md @@ -11,4 +11,5 @@ This module contains articles about basic Java concurrency - [Life Cycle of a Thread in Java](https://www.baeldung.com/java-thread-lifecycle) - [Guide to AtomicMarkableReference](https://www.baeldung.com/java-atomicmarkablereference) - [Why are Local Variables Thread-Safe in Java](https://www.baeldung.com/java-local-variables-thread-safe) +- [How to Stop Execution After a Certain Time in Java](https://www.baeldung.com/java-stop-execution-after-certain-time) - [[<-- Prev]](/core-java-modules/core-java-concurrency-basic) diff --git a/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/StopExecution.java b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/StopExecution.java new file mode 100644 index 0000000000..20f66da5da --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic-2/src/main/java/com/baeldung/concurrent/stopexecution/StopExecution.java @@ -0,0 +1,263 @@ +package com.baeldung.concurrent.stopexecution; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class StopExecution { + private static final Logger LOG = LoggerFactory.getLogger(StopExecution.class); + + public static void main(String[] args) { + StopExecution stopExecution = new StopExecution(); + //stopExecution.testUsingLoop(); + //stopExecution.testTimer(); + stopExecution.testScheduledExecutor(); + LOG.info("done"); + } + + public void testUsingLoop() { + long start = System.currentTimeMillis(); + long end = start + 5000; + List items = new ArrayList<>(); + int counter = 0; + + // Let this loop run only upto 5 seconds + while (System.currentTimeMillis() < end && counter < items.size()) { + // Fetch the item from the list. + // Some expensive operation on the item. + try { + Thread.sleep(100); + } catch (InterruptedException e) { + e.printStackTrace(); + } + counter++; + } + } + + public static void testThreads() { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + LOG.info("inside run"); + + try { + Thread.sleep(10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + LOG.info("exit run"); + } + }); + thread.start(); + while (thread.getState() != Thread.State.TERMINATED) { + LOG.info(thread.getState().name()); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + public static void testExecutor() { + final ExecutorService service = Executors.newSingleThreadExecutor(); + Future f = null; + try { + f = service.submit(() -> { + // Do you long running calculation here + try { + Thread.sleep(2737); // Simulate some delay + } catch (InterruptedException e) { + LOG.info("Interrupted"); + return "interrupted"; + } + LOG.info("Sleep finished"); + return "42"; + }); + + LOG.info(f.get(2, TimeUnit.SECONDS)); + } catch (TimeoutException e) { + f.cancel(true); + LOG.error("Calculation took to long"); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + service.shutdown(); + } + } + + public void testExecutor2() { + final ExecutorService service = Executors.newSingleThreadExecutor(); + Future f = null; + try { + f = service.submit(new LongRunningTask()); + LOG.info("testExecutor2"); + f.get(1, TimeUnit.SECONDS); + } catch (final TimeoutException e) { + f.cancel(true); + LOG.error("Calculation took to long"); + } catch (final Exception e) { + throw new RuntimeException(e); + } finally { + service.shutdownNow(); + } + } + + public void testScheduledExecutor() { + LOG.info("testScheduledExecutor"); + ScheduledExecutorService executor = Executors.newScheduledThreadPool(2); + Future future = executor.submit(new LongRunningTask()); + executor.schedule(new Runnable() { + public void run() { + future.cancel(true); + } + }, 1000, TimeUnit.MILLISECONDS); + executor.shutdown(); + } + + public void testThreadAndInterrupt() { + + Thread t; + try { + t = new Thread(new LongRunningTask()); + + LOG.info("testExecutor3"); + long end = System.currentTimeMillis() + 2000; + t.start(); + while (t.isAlive() && System.currentTimeMillis() < end) { + Thread.sleep(50); + } + t.interrupt(); + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + + public void testTimer() { + LOG.info("Timer test"); + Thread t = new Thread(new LongRunningTask()); + Timer timeoutTimer = new Timer(); + timeoutTimer.schedule(new TimeOutTask(t, timeoutTimer), 1000); + t.start(); + } + + class MyRunnableTask implements Runnable { + public void run() { + try { + LOG.info("MyRunnable..."); + Thread.sleep(10000); + } catch (InterruptedException ie) { + LOG.info("MyRunnable interrupted..."); + } + } + } + + class TimeOutTask extends TimerTask { + private Thread t; + private Timer timer; + + TimeOutTask(Thread t, Timer timer) { + this.t = t; + this.timer = timer; + } + + public void run() { + if (t != null && t.isAlive()) { + t.interrupt(); + timer.cancel(); + } + } + } + + class LongRunningTask implements Runnable { + @Override + public void run() { + longRunningSort(); + } + + private void longRunningOperation() { + LOG.info("long Running operation started"); + + try { + //Thread.sleep(500); + longFileRead(); + LOG.info("long running operation finished"); + } catch (InterruptedException e) { + LOG.info("long Running operation interrupted"); + } + } + + private void longRunningSort() { + LOG.info("long Running task started"); + // Do you long running calculation here + int len = 100000; + List numbers = new ArrayList<>(); + try { + for (int i = len; i > 0; i--) { + //Thread.sleep(5) + numbers.add(i); + } + + int i = 0; + for (i = 0; i < len; i++) { + int minIndex = i; + for (int j = i + 1; j < len; j++) { + if (numbers.get(minIndex) > numbers.get(j)) + minIndex = j; + } + if (minIndex != i) { + int temp = numbers.get(i); + numbers.set(i, numbers.get(minIndex)); + numbers.set(minIndex, temp); + } + throwExceptionOnThreadInterrupt(); + } + LOG.info("Index position: " + i); + LOG.info("Long running task finished"); + } catch (InterruptedException e) { + LOG.info("long Running operation interrupted"); + } + } + + private void longFileRead() throws InterruptedException { + String file = "input.txt"; + ClassLoader classloader = getClass().getClassLoader(); + + try (InputStream inputStream = classloader.getResourceAsStream(file)) { + Reader inputStreamReader = new InputStreamReader(inputStream); + + int data = inputStreamReader.read(); + while (data != -1) { + char theChar = (char) data; + data = inputStreamReader.read(); + throwExceptionOnThreadInterrupt(); + } + } catch (IOException e) { + LOG.error("Exception: ", e); + } + } + + private void throwExceptionOnThreadInterrupt() throws InterruptedException { + if (Thread.currentThread().interrupted()) { + throw new InterruptedException(); + } + } + } + +} + + diff --git a/core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/datetime/ConvertInstantToTimestampUnitTest.java b/core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/datetime/ConvertInstantToTimestampUnitTest.java index e5fd80285c..bb36dd634e 100644 --- a/core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/datetime/ConvertInstantToTimestampUnitTest.java +++ b/core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/datetime/ConvertInstantToTimestampUnitTest.java @@ -6,6 +6,7 @@ import java.sql.Timestamp; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.time.Instant; +import java.time.format.DateTimeFormatter; import java.util.TimeZone; import static org.assertj.core.api.Assertions.assertThat; @@ -21,9 +22,12 @@ public class ConvertInstantToTimestampUnitTest { instant = timestamp.toInstant(); assertThat(instant.toEpochMilli()).isEqualTo(timestamp.getTime()); - DateFormat df = DateFormat.getDateTimeInstance(); - df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SS'Z'"); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); + formatter = formatter.withZone(TimeZone.getTimeZone("UTC").toZoneId()); + + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); df.setTimeZone(TimeZone.getTimeZone("UTC")); - assertThat(instant.toString()).isEqualTo(df.format(timestamp).toString()); + + assertThat(formatter.format(instant)).isEqualTo(df.format(timestamp)); } } diff --git a/core-java-modules/core-java-datetime-string/src/test/java/com/baeldung/date/StringToDateUnitTest.java b/core-java-modules/core-java-datetime-string/src/test/java/com/baeldung/date/StringToDateUnitTest.java index e07422a9c6..0d2bb810f0 100644 --- a/core-java-modules/core-java-datetime-string/src/test/java/com/baeldung/date/StringToDateUnitTest.java +++ b/core-java-modules/core-java-datetime-string/src/test/java/com/baeldung/date/StringToDateUnitTest.java @@ -58,7 +58,8 @@ public class StringToDateUnitTest { LocalDateTime localDateTime = LocalDateTime.of(2015, 05, 05, 10, 15, 30); ZonedDateTime expectedZonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.of("Europe/Paris")); - ZonedDateTime zonedDateTime = ZonedDateTime.parse("2015-05-05T10:15:30+01:00[Europe/Paris]"); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z"); + ZonedDateTime zonedDateTime = ZonedDateTime.parse("2015-05-05 10:15:30 Europe/Paris", formatter); assertThat(zonedDateTime).isEqualTo(expectedZonedDateTime); } diff --git a/core-java-modules/core-java-datetime-string/src/test/java/com/baeldung/datetime/DateTimeFormatterUnitTest.java b/core-java-modules/core-java-datetime-string/src/test/java/com/baeldung/datetime/DateTimeFormatterUnitTest.java index f3b2b11893..b1c88cb44c 100644 --- a/core-java-modules/core-java-datetime-string/src/test/java/com/baeldung/datetime/DateTimeFormatterUnitTest.java +++ b/core-java-modules/core-java-datetime-string/src/test/java/com/baeldung/datetime/DateTimeFormatterUnitTest.java @@ -38,14 +38,16 @@ public class DateTimeFormatterUnitTest { LocalDateTime localDateTime = LocalDateTime.of(2018, 1, 1, 10, 15, 50, 500); ZoneId losAngelesTimeZone = TimeZone.getTimeZone("America/Los_Angeles").toZoneId(); - DateTimeFormatter localizedFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL); - DateTimeFormatter frLocalizedFormatter = - DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale(Locale.FRANCE); + DateTimeFormatter localizedFormatter = DateTimeFormatter.ofPattern("EEEE, MMMM dd, yyyy z", Locale.US); + DateTimeFormatter frLocalizedFormatter = DateTimeFormatter.ofPattern("EEEE, MMMM dd, yyyy z", Locale.FRANCE); String formattedDateTime = localizedFormatter.format(ZonedDateTime.of(localDateTime, losAngelesTimeZone)); String frFormattedDateTime = frLocalizedFormatter.format(ZonedDateTime.of(localDateTime, losAngelesTimeZone)); - Assert.assertEquals("Monday, January 1, 2018 10:15:50 AM PST", formattedDateTime); - Assert.assertEquals("lundi 1 janvier 2018 10 h 15 PST", frFormattedDateTime); + System.out.println(formattedDateTime); + System.out.println(frFormattedDateTime); + + Assert.assertEquals("Monday, January 01, 2018 PST", formattedDateTime); + Assert.assertEquals("lundi, janvier 01, 2018 PST", frFormattedDateTime); } @Test @@ -105,14 +107,15 @@ public class DateTimeFormatterUnitTest { Assert.assertEquals("8/23/16", DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).format(anotherSummerDay)); } - @Test - public void shouldPrintStyledDateTime() { - LocalDateTime anotherSummerDay = LocalDateTime.of(2016, 8, 23, 13, 12, 45); - Assert.assertEquals("Tuesday, August 23, 2016 1:12:45 PM EET", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay)); - Assert.assertEquals("August 23, 2016 1:12:45 PM EET", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay)); - Assert.assertEquals("Aug 23, 2016 1:12:45 PM", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay)); - Assert.assertEquals("8/23/16 1:12 PM", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay)); - } + // Note: The exact output format using the different FormatStyle constants differs by JVM/Java version + // @Test + // public void shouldPrintStyledDateTime() { + // LocalDateTime anotherSummerDay = LocalDateTime.of(2016, 8, 23, 13, 12, 45); + // Assert.assertEquals("Tuesday, August 23, 2016 1:12:45 PM EET", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay)); + // Assert.assertEquals("August 23, 2016 1:12:45 PM EET", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay)); + // Assert.assertEquals("Aug 23, 2016 1:12:45 PM", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay)); + // Assert.assertEquals("8/23/16 1:12 PM", DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withZone(ZoneId.of("Europe/Helsinki")).format(anotherSummerDay)); + // } @Test public void shouldPrintFormattedDateTimeWithPredefined() { @@ -126,11 +129,12 @@ public class DateTimeFormatterUnitTest { Assert.assertEquals(LocalDate.of(2018, 3, 12), LocalDate.from(DateTimeFormatter.ISO_LOCAL_DATE.parse("2018-03-09")).plusDays(3)); } - @Test - public void shouldParseFormatStyleFull() { - ZonedDateTime dateTime = ZonedDateTime.from(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).parse("Tuesday, August 23, 2016 1:12:45 PM EET")); - Assert.assertEquals(ZonedDateTime.of(LocalDateTime.of(2016, 8, 23, 22, 12, 45), ZoneId.of("Europe/Bucharest")), dateTime.plusHours(9)); - } + // Note: The exact output format using the different FormatStyle constants differs by JVM/Java version + // @Test + // public void shouldParseFormatStyleFull() { + // ZonedDateTime dateTime = ZonedDateTime.from(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).parse("Tuesday, August 23, 2016 1:12:45 PM EET")); + // Assert.assertEquals(ZonedDateTime.of(LocalDateTime.of(2016, 8, 23, 22, 12, 45), ZoneId.of("Europe/Bucharest")), dateTime.plusHours(9)); + // } @Test public void shouldParseDateWithCustomFormatter() { diff --git a/core-java-modules/core-java-exceptions-3/README.md b/core-java-modules/core-java-exceptions-3/README.md index 4e3dd22bb8..e1372381a8 100644 --- a/core-java-modules/core-java-exceptions-3/README.md +++ b/core-java-modules/core-java-exceptions-3/README.md @@ -3,3 +3,8 @@ - [NoSuchMethodError in Java](https://www.baeldung.com/java-nosuchmethod-error) - [IllegalArgumentException or NullPointerException for a Null Parameter?](https://www.baeldung.com/java-illegalargumentexception-or-nullpointerexception) - [IllegalMonitorStateException in Java](https://www.baeldung.com/java-illegalmonitorstateexception) +- [AbstractMethodError in Java](https://www.baeldung.com/java-abstractmethoderror) +- [Java IndexOutOfBoundsException “Source Does Not Fit in Dest”](https://www.baeldung.com/java-indexoutofboundsexception) +- [Localizing Exception Messages in Java](https://www.baeldung.com/java-localize-exception-messages) +- [Explanation of ClassCastException in Java](https://www.baeldung.com/java-classcastexception) +- [NoSuchFieldError in Java](https://www.baeldung.com/java-nosuchfielderror) diff --git a/core-java-modules/core-java-exceptions-3/pom.xml b/core-java-modules/core-java-exceptions-3/pom.xml index b909572afe..8c36fd0af1 100644 --- a/core-java-modules/core-java-exceptions-3/pom.xml +++ b/core-java-modules/core-java-exceptions-3/pom.xml @@ -17,6 +17,14 @@ + + + com.h2database + h2 + 1.4.191 + test + + org.assertj diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/CopyListUsingAddAllMethodDemo.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/CopyListUsingAddAllMethodDemo.java new file mode 100644 index 0000000000..34e6f1c998 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/CopyListUsingAddAllMethodDemo.java @@ -0,0 +1,14 @@ +package com.baeldung.exception.indexoutofbounds; + +import java.util.ArrayList; +import java.util.List; + +public class CopyListUsingAddAllMethodDemo { + static List copyList(List source) { + List destination = new ArrayList<>(); + + destination.addAll(source); + + return destination; + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/CopyListUsingCollectionsCopyMethodDemo.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/CopyListUsingCollectionsCopyMethodDemo.java new file mode 100644 index 0000000000..664e2152d8 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/CopyListUsingCollectionsCopyMethodDemo.java @@ -0,0 +1,10 @@ +package com.baeldung.exception.indexoutofbounds; + +import java.util.Collections; +import java.util.List; + +public class CopyListUsingCollectionsCopyMethodDemo { + static void copyList(List source, List destination) { + Collections.copy(destination, source); + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/CopyListUsingConstructorDemo.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/CopyListUsingConstructorDemo.java new file mode 100644 index 0000000000..493031ba0a --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/CopyListUsingConstructorDemo.java @@ -0,0 +1,10 @@ +package com.baeldung.exception.indexoutofbounds; + +import java.util.ArrayList; +import java.util.List; + +public class CopyListUsingConstructorDemo { + static List copyList(List source) { + return new ArrayList<>(source); + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/CopyListUsingJava8StreamDemo.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/CopyListUsingJava8StreamDemo.java new file mode 100644 index 0000000000..d9d0247d2f --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/CopyListUsingJava8StreamDemo.java @@ -0,0 +1,12 @@ +package com.baeldung.exception.indexoutofbounds; + +import java.util.List; +import java.util.stream.Collectors; + +public class CopyListUsingJava8StreamDemo { + static List copyList(List source) { + return source + .stream() + .collect(Collectors.toList()); + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/IndexOutOfBoundsExceptionDemo.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/IndexOutOfBoundsExceptionDemo.java new file mode 100644 index 0000000000..78b7b03bc1 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exception/indexoutofbounds/IndexOutOfBoundsExceptionDemo.java @@ -0,0 +1,13 @@ +package com.baeldung.exception.indexoutofbounds; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class IndexOutOfBoundsExceptionDemo { + static List copyList(List source) { + List destination = new ArrayList<>(source.size()); + Collections.copy(destination, source); + return destination; + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Amphibian.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Amphibian.java new file mode 100644 index 0000000000..f31c19bc0f --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Amphibian.java @@ -0,0 +1,9 @@ +package com.baeldung.exceptions.classcastexception; + +public class Amphibian implements Animal { + + @Override + public String getName() { + return "Amphibian"; + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Animal.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Animal.java new file mode 100644 index 0000000000..b57f68f053 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Animal.java @@ -0,0 +1,6 @@ +package com.baeldung.exceptions.classcastexception; + +public interface Animal { + + String getName(); +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Box.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Box.java new file mode 100644 index 0000000000..bb67407218 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Box.java @@ -0,0 +1,14 @@ +package com.baeldung.exceptions.classcastexception; + +public class Box { + + private T content; + + public T getContent() { + return content; + } + + public void setContent(T content) { + this.content = content; + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Frog.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Frog.java new file mode 100644 index 0000000000..a3837f4c2f --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Frog.java @@ -0,0 +1,9 @@ +package com.baeldung.exceptions.classcastexception; + +public class Frog extends Amphibian { + + @Override + public String getName() { + return super.getName() + ": Frog"; + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Mammal.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Mammal.java new file mode 100644 index 0000000000..2723cc5b7b --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/classcastexception/Mammal.java @@ -0,0 +1,9 @@ +package com.baeldung.exceptions.classcastexception; + +public class Mammal implements Animal { + + @Override + public String getName() { + return "Mammal"; + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/localization/LocalizedException.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/localization/LocalizedException.java new file mode 100644 index 0000000000..c3f9980b99 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/localization/LocalizedException.java @@ -0,0 +1,47 @@ +package com.baeldung.exceptions.localization; + +import java.util.Locale; + +public class LocalizedException extends Exception { + + private static final long serialVersionUID = 1L; + + private final String messageKey; + private final Locale locale; + + public LocalizedException(String messageKey) { + this(messageKey, Locale.getDefault()); + } + + public LocalizedException(String messageKey, Locale locale) { + this.messageKey = messageKey; + this.locale = locale; + } + + /** + * @return a localized message based on the messageKey provided at instantiation. + */ + public String getMessage() { + + /* + * This is a deliberate role reversal of the default implementation of getLocalizedMessage. + * some logging frameworks like Log4J 1 & 2 and Logback will use getMessage instead of + * getLocalizedMessage when logging Throwables. If we want to use these frameworks in client + * applications to log localized messages, then we'll need to override getMessage in a + * similar fashion to return the appropriate content. Or, you can call getLocalizedMessage + * on your own to create the log content. + */ + return getLocalizedMessage(); + } + + /** + * @return a localized message based on the messageKey provided at instantiation. + */ + public String getLocalizedMessage() { + + /* + * java.util.logging uses getLocalizedMessage when logging Throwables. + */ + return Messages.getMessageForLocale(messageKey, locale); + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/localization/Messages.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/localization/Messages.java new file mode 100644 index 0000000000..1079bedd1a --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/localization/Messages.java @@ -0,0 +1,27 @@ +package com.baeldung.exceptions.localization; + +import java.util.Locale; +import java.util.ResourceBundle; + +public class Messages { + + /** + * Retrieves the value for the messageKey from the locale-specific messages.properties, or from + * the base messages.properties for unsupported locales. + * + * @param messageKey The key for the message in the messages.properties ResourceBundle. + * @param locale The locale to search the message key. + * @return The value defined for the messageKey in the provided locale. + */ + public static String getMessageForLocale(String messageKey, Locale locale) { + + /* + * For more complex implementations, you will want a var-args parameter for MessageFormat + * substitutions. Then we can read the value from the bundle and pass the value with the + * substitutions to MessageFormat to create the final message value. + */ + return ResourceBundle.getBundle("messages", locale) + .getString(messageKey); + } + +} diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/nosuchfielderror/Dependency.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/nosuchfielderror/Dependency.java new file mode 100644 index 0000000000..31ac54ac6b --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/nosuchfielderror/Dependency.java @@ -0,0 +1,8 @@ +package com.baeldung.exceptions.nosuchfielderror; + +public class Dependency { + + // This needed to be commented post compilation of NoSuchFielDError and Compile + public static String message = "Hello Baeldung!!"; + +} \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/nosuchfielderror/FieldErrorExample.java b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/nosuchfielderror/FieldErrorExample.java new file mode 100644 index 0000000000..021ed57d87 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/java/com/baeldung/exceptions/nosuchfielderror/FieldErrorExample.java @@ -0,0 +1,20 @@ +package com.baeldung.exceptions.nosuchfielderror; + +public class FieldErrorExample { + + public static void main(String... args) { + + fetchAndPrint(); + } + + public static String getDependentMessage() { + + return Dependency.message; + } + + public static void fetchAndPrint() { + + System.out.println(getDependentMessage()); + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-3/src/main/resources/messages.properties b/core-java-modules/core-java-exceptions-3/src/main/resources/messages.properties new file mode 100644 index 0000000000..b6122d7f21 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/resources/messages.properties @@ -0,0 +1 @@ +message.exception = I am an exception. \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-3/src/main/resources/messages_fr.properties b/core-java-modules/core-java-exceptions-3/src/main/resources/messages_fr.properties new file mode 100644 index 0000000000..f28e0d54ff --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/main/resources/messages_fr.properties @@ -0,0 +1 @@ +message.exception = Je suis une exception. \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/CopyListUsingAddAllMethodDemoUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/CopyListUsingAddAllMethodDemoUnitTest.java new file mode 100644 index 0000000000..204bbff696 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/CopyListUsingAddAllMethodDemoUnitTest.java @@ -0,0 +1,18 @@ +package com.baeldung.exception.indexoutofbounds; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class CopyListUsingAddAllMethodDemoUnitTest { + + @Test + void whenPassValidArrayList_thenCopyListUsingAddAllMethod() { + List source = Arrays.asList(11, 22, 33); + + assertEquals(source, CopyListUsingAddAllMethodDemo.copyList(source)); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/CopyListUsingCollectionsCopyMethodDemoUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/CopyListUsingCollectionsCopyMethodDemoUnitTest.java new file mode 100644 index 0000000000..7ebf7461a6 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/CopyListUsingCollectionsCopyMethodDemoUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.exception.indexoutofbounds; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class CopyListUsingCollectionsCopyMethodDemoUnitTest { + @Test + void whenCopyListUsingCollectionsCopy_thenOverrideAllDestinationListValues() { + List source = Arrays.asList(11, 22, 33); + List destination = Arrays.asList(1, 2, 3); + + CopyListUsingCollectionsCopyMethodDemo.copyList(source, destination); + + assertEquals(source, destination); + } + + @Test + void whenCopyListUsingCollectionsCopy_thenOverrideInitialDestinationValuesAndOthersShouldBeUnchanged(){ + List source = Arrays.asList(11, 22, 33); + List destination = Arrays.asList(1, 2, 3, 4, 5); + List expectedList = Arrays.asList(11, 22, 33, 4, 5); + + CopyListUsingCollectionsCopyMethodDemo.copyList(source, destination); + + assertEquals(expectedList, destination); + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/CopyListUsingConstructorDemoUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/CopyListUsingConstructorDemoUnitTest.java new file mode 100644 index 0000000000..cd15c5055c --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/CopyListUsingConstructorDemoUnitTest.java @@ -0,0 +1,18 @@ +package com.baeldung.exception.indexoutofbounds; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class CopyListUsingConstructorDemoUnitTest { + + @Test + void whenCopyListUsingConstructor_thenMakeACopyOfList() { + List source = Arrays.asList(11, 22, 33); + + assertEquals(source, CopyListUsingConstructorDemo.copyList(source)); + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/CopyListUsingJava8StreamDemoUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/CopyListUsingJava8StreamDemoUnitTest.java new file mode 100644 index 0000000000..9fb8e16b2a --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/CopyListUsingJava8StreamDemoUnitTest.java @@ -0,0 +1,18 @@ +package com.baeldung.exception.indexoutofbounds; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class CopyListUsingJava8StreamDemoUnitTest { + + @Test + void whenCopyListUsingStream_thenMakeACopyOfArrayList() { + List source = Arrays.asList(11, 22, 33); + + assertEquals(source, CopyListUsingJava8StreamDemo.copyList(source)); + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/IndexOutOfBoundsExceptionDemoUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/IndexOutOfBoundsExceptionDemoUnitTest.java new file mode 100644 index 0000000000..9929fa78d3 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exception/indexoutofbounds/IndexOutOfBoundsExceptionDemoUnitTest.java @@ -0,0 +1,28 @@ +package com.baeldung.exception.indexoutofbounds; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + + +class IndexOutOfBoundsExceptionDemoUnitTest { + + @Test + void givenDestinationArrayListSizeIsZero_whenCopySourceArrayListToDestination_thenShouldThrowIndexOutOfBoundsException() { + List source = Arrays.asList(1, 2, 3, 4, 5); + + assertThrows(IndexOutOfBoundsException.class, () -> IndexOutOfBoundsExceptionDemo.copyList(source)); + } + + @Test + void givenSourceAndDestinationListSizeIsEqual_whenCopySourceArrayListToDestination_thenShouldNotThrowIndexOutOfBoundsException() { + List source = Collections.emptyList(); + + assertEquals(source, IndexOutOfBoundsExceptionDemo.copyList(source)); + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/abstractmethoderror/AbstractMethodErrorUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/abstractmethoderror/AbstractMethodErrorUnitTest.java new file mode 100644 index 0000000000..cadc884487 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/abstractmethoderror/AbstractMethodErrorUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.exceptions.abstractmethoderror; + + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class AbstractMethodErrorUnitTest { + private static final String url = "jdbc:h2:mem:A-DATABASE;INIT=CREATE SCHEMA IF NOT EXISTS myschema"; + private static final String username = "sa"; + + @Test + void givenOldH2Database_whenCallgetSchemaMethod_thenThrowAbstractMethodError() throws SQLException { + Connection conn = DriverManager.getConnection(url, username, ""); + assertNotNull(conn); + Assertions.assertThrows(AbstractMethodError.class, () -> conn.getSchema()); + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/classcastexception/CheckedCastsUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/classcastexception/CheckedCastsUnitTest.java new file mode 100644 index 0000000000..7fac000fa8 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/classcastexception/CheckedCastsUnitTest.java @@ -0,0 +1,40 @@ +package com.baeldung.exceptions.classcastexception; + +import org.junit.Test; + +import java.io.Serializable; + +public class CheckedCastsUnitTest { + + @Test(expected = ClassCastException.class) + public void givenBaseTypeVariableReferencingChildInstance_whenCastToIncompatibleSubtype_thenClassCastException() { + Animal animal = new Frog(); + + //A checked downcast to Mammal is incompatible from Frog because Frog is not a subtype of Mammal. + Mammal mammal = (Mammal) animal; + } + + @Test(expected = ClassCastException.class) + public void givenBaseTypeVariableReferencingChildInstance_whenCastToIncompatibleInterface_thenClassCastException() { + Animal animal = new Frog(); + + //A checked cast to Serializable is incompatible from Frog because Frog is not a subtype of Serializable. + Serializable serial = (Serializable) animal; + } + + @Test(expected = ClassCastException.class) + public void givenObjectVariableReferencingPrimitiveArray_whenCastToBoxedTypeArray_thenClassCastException() { + Object primitives = new int[1]; + + //A checked cast to Integer[] is incompatible from primitive arrays. Auto-boxing does not work for arrays. + Integer[] integers = (Integer[]) primitives; + } + + @Test(expected = ClassCastException.class) + public void givenObjectVariableReferencingPrimitiveArray_whenCastToPromotedTypeArray_thenClassCastException() { + Object primitives = new int[1]; + + //A checked cast to long[] is incompatible from int[]. Type promotion does not work for arrays. + long[] longs = (long[]) primitives; + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/classcastexception/GenericConversionUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/classcastexception/GenericConversionUnitTest.java new file mode 100644 index 0000000000..027ece2db7 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/classcastexception/GenericConversionUnitTest.java @@ -0,0 +1,21 @@ +package com.baeldung.exceptions.classcastexception; + +import org.junit.Test; + +public class GenericConversionUnitTest { + + @Test(expected = ClassCastException.class) + public void givenIncompatibleType_whenConvertInstanceOfObject_thenClassCastException() { + // Should have been null, but due to type erasure, inside convertInstanceOfObject, + // it will attempt to cast to Object instead of String, so it casts to Object, which is always possible. + String shouldBeNull = convertInstanceOfObject(123); + } + + public static T convertInstanceOfObject(Object o) { + try { + return (T) o; // Casts to Object due to type erasure + } catch (ClassCastException e) { + return null; // Will never reach this + } + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/classcastexception/UncheckedConversionUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/classcastexception/UncheckedConversionUnitTest.java new file mode 100644 index 0000000000..60e7d5a147 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/classcastexception/UncheckedConversionUnitTest.java @@ -0,0 +1,17 @@ +package com.baeldung.exceptions.classcastexception; + +import org.junit.Test; + +public class UncheckedConversionUnitTest { + + @Test(expected = ClassCastException.class) + public void givenPollutedGenericType_whenGetProperty_thenClassCastException() { + Box originalBox = new Box<>(); + Box raw = originalBox; + raw.setContent(2.5); + Box bound = (Box) raw; + + //An incompatible element was found in the raw box. + Long content = bound.getContent(); + } +} diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/illegalmonitorstate/IllegalMonitorStateExceptionUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/illegalmonitorstate/IllegalMonitorStateExceptionUnitTest.java index a729facdbd..82c00bc72f 100644 --- a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/illegalmonitorstate/IllegalMonitorStateExceptionUnitTest.java +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/illegalmonitorstate/IllegalMonitorStateExceptionUnitTest.java @@ -20,6 +20,8 @@ public class IllegalMonitorStateExceptionUnitTest { senderThread.join(1000); receiverThread.join(1000); + + Thread.sleep(2000); assertEquals("test", receiver.getMessage()); assertFalse(sender.hasIllegalMonitorStateExceptionOccurred()); diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/localization/LocalizedExceptionUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/localization/LocalizedExceptionUnitTest.java new file mode 100644 index 0000000000..a46ca05d23 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/localization/LocalizedExceptionUnitTest.java @@ -0,0 +1,61 @@ +package com.baeldung.exceptions.localization; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; + +public class LocalizedExceptionUnitTest { + + private Locale originalDefaultLocale; + + @Before + public void saveOriginalDefaultLocale() { + originalDefaultLocale = Locale.getDefault(); + } + + @After + public void restoreOriginalDefaultLocale() { + Locale.setDefault(originalDefaultLocale); + } + + @Test + public void givenUsEnglishDefaultLocale_whenLocalizingMessage_thenMessageComesFromDefaultMessages() { + Locale.setDefault(Locale.US); + + LocalizedException localizedException = new LocalizedException("message.exception"); + String usEnglishLocalizedExceptionMessage = localizedException.getLocalizedMessage(); + + assertThat(usEnglishLocalizedExceptionMessage).isEqualTo("I am an exception."); + } + + @Test + public void givenFranceFrenchDefaultLocale_whenLocalizingMessage_thenMessageComesFromFrenchTranslationMessages() { + Locale.setDefault(Locale.FRANCE); + + LocalizedException localizedException = new LocalizedException("message.exception"); + String franceFrenchLocalizedExceptionMessage = localizedException.getLocalizedMessage(); + + assertThat(franceFrenchLocalizedExceptionMessage).isEqualTo("Je suis une exception."); + } + + @Test + public void givenUsEnglishProvidedLocale_whenLocalizingMessage_thenMessageComesFromDefaultMessage() { + LocalizedException localizedException = new LocalizedException("message.exception", Locale.US); + String usEnglishLocalizedExceptionMessage = localizedException.getLocalizedMessage(); + + assertThat(usEnglishLocalizedExceptionMessage).isEqualTo("I am an exception."); + } + + @Test + public void givenFranceFrenchProvidedLocale_whenLocalizingMessage_thenMessageComesFromFrenchTranslationMessages() { + LocalizedException localizedException = new LocalizedException("message.exception", Locale.FRANCE); + String franceFrenchLocalizedExceptionMessage = localizedException.getLocalizedMessage(); + + assertThat(franceFrenchLocalizedExceptionMessage).isEqualTo("Je suis une exception."); + } + +} diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/localization/MessagesUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/localization/MessagesUnitTest.java new file mode 100644 index 0000000000..7a6cb8ed32 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/localization/MessagesUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.exceptions.localization; + +import org.junit.Test; + +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; + +public class MessagesUnitTest { + + @Test + public void givenUsEnglishLocale_whenRetrievingMessage_thenEnglishTranslationIsReturned() { + String translatedMessage = Messages.getMessageForLocale("message.exception", Locale.US); + + assertThat(translatedMessage).isEqualTo("I am an exception."); + } + + @Test + public void givenFranceFrenchLocale_whenRetrievingMessage_thenFrenchTranslationIsReturned() { + String translatedMessage = Messages.getMessageForLocale("message.exception", Locale.FRANCE); + + assertThat(translatedMessage).isEqualTo("Je suis une exception."); + } + +} diff --git a/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/nosuchfielderror/FieldErrorExampleUnitTest.java b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/nosuchfielderror/FieldErrorExampleUnitTest.java new file mode 100644 index 0000000000..d9a3efacc8 --- /dev/null +++ b/core-java-modules/core-java-exceptions-3/src/test/java/com/baeldung/exceptions/nosuchfielderror/FieldErrorExampleUnitTest.java @@ -0,0 +1,16 @@ +package com.baeldung.exceptions.nosuchfielderror; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +public class FieldErrorExampleUnitTest { + + @Test + public void whenDependentMessage_returnMessage() { + + String dependentMessage = FieldErrorExample.getDependentMessage(); + assertTrue("Hello Baeldung!!".equals(dependentMessage)); + } + +} \ No newline at end of file diff --git a/core-java-modules/core-java-functional/README.md b/core-java-modules/core-java-functional/README.md new file mode 100644 index 0000000000..5891b4a943 --- /dev/null +++ b/core-java-modules/core-java-functional/README.md @@ -0,0 +1,3 @@ +## Relevant articles: + +- [Functional Programming in Java](https://www.baeldung.com/java-functional-programming) diff --git a/core-java-modules/core-java-functional/pom.xml b/core-java-modules/core-java-functional/pom.xml new file mode 100644 index 0000000000..f00600c794 --- /dev/null +++ b/core-java-modules/core-java-functional/pom.xml @@ -0,0 +1,18 @@ + + + 4.0.0 + core-java-functional + 0.1.0-SNAPSHOT + core-java-functional + jar + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + ../ + + + \ No newline at end of file diff --git a/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/Currying.java b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/Currying.java new file mode 100644 index 0000000000..594fea4b8c --- /dev/null +++ b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/Currying.java @@ -0,0 +1,26 @@ +package com.baeldung.functional; + +import java.util.function.Function; + +public class Currying { + + private static Function> weight = mass -> gravity -> mass * gravity; + + private static Function weightOnEarth = weight.apply(9.81); + + private static Function weightOnMars = weight.apply(3.75); + + public static Double weightOnEarth(Double mass) { + return weightOnEarth.apply(mass); + } + + public static Double weightOnMars(Double mass) { + return weightOnMars.apply(mass); + } + + public static Function weightOnEarth() { + final double gravity = 9.81; + return mass -> mass * gravity; + } + +} diff --git a/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/FirstClassFunctions.java b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/FirstClassFunctions.java new file mode 100644 index 0000000000..13b408ab27 --- /dev/null +++ b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/FirstClassFunctions.java @@ -0,0 +1,24 @@ +package com.baeldung.functional; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +public class FirstClassFunctions { + + public static List sortWithoutLambda(List numbers) { + Collections.sort(numbers, new Comparator() { + @Override + public int compare(Integer n1, Integer n2) { + return n1.compareTo(n2); + } + }); + return numbers; + } + + public static List sortWithLambda(List numbers) { + Collections.sort(numbers, (n1, n2) -> n1.compareTo(n2)); + return numbers; + } + +} diff --git a/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/FunctionComposition.java b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/FunctionComposition.java new file mode 100644 index 0000000000..57103be98a --- /dev/null +++ b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/FunctionComposition.java @@ -0,0 +1,20 @@ +package com.baeldung.functional; + +import java.util.function.Function; + +public class FunctionComposition { + + private static Function log = (value) -> Math.log(value); + private static Function sqrt = (value) -> Math.sqrt(value); + + public static Double logThenSqrt(Double number) { + Function logThenSqrt = sqrt.compose(log); + return (logThenSqrt.apply(3.14)); + } + + public static Double sqrtThenLog(Double number) { + Function sqrtThenLog = sqrt.andThen(log); + return (sqrtThenLog.apply(3.14)); + } + +} diff --git a/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/ImmutableData.java b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/ImmutableData.java new file mode 100644 index 0000000000..738680f743 --- /dev/null +++ b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/ImmutableData.java @@ -0,0 +1,36 @@ +package com.baeldung.functional; + +public class ImmutableData { + + private final String someData; + + private final AnotherImmutableData anotherImmutableData; + + public ImmutableData(final String someData, final AnotherImmutableData anotherImmutableData) { + this.someData = someData; + this.anotherImmutableData = anotherImmutableData; + } + + public String getSomeData() { + return someData; + } + + public AnotherImmutableData getAnotherImmutableData() { + return anotherImmutableData; + } + + public class AnotherImmutableData { + + private final Integer someOtherData; + + public AnotherImmutableData(final Integer someData) { + this.someOtherData = someData; + } + + public Integer getSomeOtherData() { + return someOtherData; + } + + } + +} diff --git a/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/Monads.java b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/Monads.java new file mode 100644 index 0000000000..c1223c73c7 --- /dev/null +++ b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/Monads.java @@ -0,0 +1,11 @@ +package com.baeldung.functional; + +import java.util.Optional; + +public class Monads { + + public static Optional add(Optional val1, Optional val2) { + return val1.flatMap(first -> val2.flatMap(second -> Optional.of(first + second))); + } + +} diff --git a/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/PureFunctions.java b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/PureFunctions.java new file mode 100644 index 0000000000..522b9de9eb --- /dev/null +++ b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/PureFunctions.java @@ -0,0 +1,13 @@ +package com.baeldung.functional; + +import java.util.List; +import java.util.stream.Collectors; + +public class PureFunctions { + + public static Integer sum(List numbers) { + return numbers.stream() + .collect(Collectors.summingInt(Integer::intValue)); + } + +} diff --git a/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/Recursion.java b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/Recursion.java new file mode 100644 index 0000000000..d5492df69d --- /dev/null +++ b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/Recursion.java @@ -0,0 +1,17 @@ +package com.baeldung.functional; + +public class Recursion { + + public static Integer headRecursion(Integer number) { + + return (number == 1) ? 1 : number * headRecursion(number - 1); + + } + + public static Integer tailRecursion(Integer number, Integer result) { + + return (number == 1) ? result : tailRecursion(number - 1, result * number); + + } + +} diff --git a/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/ReferentialTransparency.java b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/ReferentialTransparency.java new file mode 100644 index 0000000000..1392cdd00a --- /dev/null +++ b/core-java-modules/core-java-functional/src/main/java/com/baeldung/functional/ReferentialTransparency.java @@ -0,0 +1,39 @@ +package com.baeldung.functional; + +import java.util.logging.Level; +import java.util.logging.Logger; + +public class ReferentialTransparency { + + private static Logger logger = Logger.getGlobal(); + + public void main() { + + String data = new SimpleData().setData("Baeldung") + .getData(); + logger.log(Level.INFO, new SimpleData().setData("Baeldung") + .getData()); + logger.log(Level.INFO, data); + logger.log(Level.INFO, "Baeldung"); + } + + public class SimpleData { + + private Logger logger = Logger.getGlobal(); + + private String data; + + public String getData() { + logger.log(Level.INFO, "Get data called for SimpleData"); + return data; + } + + public SimpleData setData(String data) { + logger.log(Level.INFO, "Set data called for SimpleData"); + this.data = data; + return this; + } + + } + +} diff --git a/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/CurryingUnitTest.java b/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/CurryingUnitTest.java new file mode 100644 index 0000000000..0cf96ed566 --- /dev/null +++ b/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/CurryingUnitTest.java @@ -0,0 +1,22 @@ +package com.baeldung.functional; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.Test; + +public class CurryingUnitTest { + + @Test + public void testWeightOnEarth() { + + assertEquals(588.6, Currying.weightOnEarth(60.0), 0.1); + + } + + @Test + public void testWeightOnMars() { + + assertEquals(225.0, Currying.weightOnMars(60.0), 0.1); + + } +} diff --git a/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/FirstClassFunctionsUnitTest.java b/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/FirstClassFunctionsUnitTest.java new file mode 100644 index 0000000000..8056b44f21 --- /dev/null +++ b/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/FirstClassFunctionsUnitTest.java @@ -0,0 +1,27 @@ +package com.baeldung.functional; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; + +import org.junit.Test; + +public class FirstClassFunctionsUnitTest { + + @Test + public void testSortingWithoutLambda() { + + assertEquals(new Integer(8), FirstClassFunctions.sortWithoutLambda(Arrays.asList(new Integer(10), new Integer(8))) + .get(0)); + + } + + @Test + public void testSortingWithLambda() { + + assertEquals(new Integer(8), FirstClassFunctions.sortWithLambda(Arrays.asList(new Integer(10), new Integer(8))) + .get(0)); + + } + +} diff --git a/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/FunctionCompositionUnitTest.java b/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/FunctionCompositionUnitTest.java new file mode 100644 index 0000000000..48d8fb695c --- /dev/null +++ b/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/FunctionCompositionUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.functional; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.Test; + +public class FunctionCompositionUnitTest { + + @Test + public void testLogThenSqrt() { + + assertEquals(1.07, FunctionComposition.logThenSqrt(3.14), 0.01); + + } + + @Test + public void testSqrtThenLog() { + + assertEquals(0.57, FunctionComposition.sqrtThenLog(3.14), 0.01); + + } + +} diff --git a/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/MonadsUnitTest.java b/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/MonadsUnitTest.java new file mode 100644 index 0000000000..8258eef59e --- /dev/null +++ b/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/MonadsUnitTest.java @@ -0,0 +1,19 @@ +package com.baeldung.functional; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Optional; + +import org.junit.Test; + +public class MonadsUnitTest { + + @Test + public void testOptionalAdd() { + + assertEquals(5, Monads.add(Optional.of(new Integer(2)), Optional.of(new Integer(3))) + .get()); + + } + +} diff --git a/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/PureFunctionsUnitTets.java b/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/PureFunctionsUnitTets.java new file mode 100644 index 0000000000..23cca8bf8d --- /dev/null +++ b/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/PureFunctionsUnitTets.java @@ -0,0 +1,18 @@ +package com.baeldung.functional; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Arrays; + +import org.junit.Test; + +public class PureFunctionsUnitTets { + + @Test + public void testSortingWithoutLambda() { + + assertEquals(new Integer(18), PureFunctions.sum(Arrays.asList(new Integer(10), new Integer(8)))); + + } + +} diff --git a/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/RecursionUnitTest.java b/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/RecursionUnitTest.java new file mode 100644 index 0000000000..aa406dc7ab --- /dev/null +++ b/core-java-modules/core-java-functional/src/test/java/com/baeldung/functional/RecursionUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.functional; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.Test; + +public class RecursionUnitTest { + + @Test + public void testHeadRecursion() { + + assertEquals(120, Recursion.headRecursion(5)); + + } + + @Test + public void testTailRecursion() { + + assertEquals(120, Recursion.tailRecursion(5, 1)); + + } + +} diff --git a/core-java-modules/core-java-io-2/src/main/java/com/baeldung/listfiles/ListFiles.java b/core-java-modules/core-java-io-2/src/main/java/com/baeldung/listfiles/ListFiles.java index 2275128dfe..c108d9ed96 100644 --- a/core-java-modules/core-java-io-2/src/main/java/com/baeldung/listfiles/ListFiles.java +++ b/core-java-modules/core-java-io-2/src/main/java/com/baeldung/listfiles/ListFiles.java @@ -24,9 +24,20 @@ public class ListFiles { .collect(Collectors.toSet()); } + public Set listFilesUsingFilesList(String dir) throws IOException { + try (Stream stream = Files.list(Paths.get(dir))) { + return stream + .filter(file -> !Files.isDirectory(file)) + .map(Path::getFileName) + .map(Path::toString) + .collect(Collectors.toSet()); + } + } + public Set listFilesUsingFileWalk(String dir, int depth) throws IOException { try (Stream stream = Files.walk(Paths.get(dir), depth)) { - return stream.filter(file -> !Files.isDirectory(file)) + return stream + .filter(file -> !Files.isDirectory(file)) .map(Path::getFileName) .map(Path::toString) .collect(Collectors.toSet()); diff --git a/core-java-modules/core-java-io-2/src/test/java/com/baeldung/listfiles/ListFilesUnitTest.java b/core-java-modules/core-java-io-2/src/test/java/com/baeldung/listfiles/ListFilesUnitTest.java index a87097f085..5b4efc9e58 100644 --- a/core-java-modules/core-java-io-2/src/test/java/com/baeldung/listfiles/ListFilesUnitTest.java +++ b/core-java-modules/core-java-io-2/src/test/java/com/baeldung/listfiles/ListFilesUnitTest.java @@ -25,10 +25,15 @@ public class ListFilesUnitTest { }; @Test - public void givenDir_whenUsingJAVAIO_thenListAllFiles() throws IOException { + public void givenDir_whenUsingJAVAIO_thenListAllFiles() { assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingJavaIO(DIRECTORY)); } + @Test + public void givenDir_whenUsingFilesList_thenListAllFiles() throws IOException { + assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingFilesList(DIRECTORY)); + } + @Test public void givenDir_whenWalkingTree_thenListAllFiles() throws IOException { assertEquals(EXPECTED_FILE_LIST, listFiles.listFilesUsingFileWalk(DIRECTORY,DEPTH)); diff --git a/core-java-modules/core-java-io-3/README.md b/core-java-modules/core-java-io-3/README.md index 4b1a14ab3e..d0ac5387a8 100644 --- a/core-java-modules/core-java-io-3/README.md +++ b/core-java-modules/core-java-io-3/README.md @@ -11,4 +11,7 @@ This module contains articles about core Java input and output (IO) - [Java Files Open Options](https://www.baeldung.com/java-file-options) - [Creating Temporary Directories in Java](https://www.baeldung.com/java-temp-directories) - [Reading a Line at a Given Line Number From a File in Java](https://www.baeldung.com/java-read-line-at-number) +- [Find the Last Modified File in a Directory with Java](https://www.baeldung.com/java-last-modified-file) +- [Get a Filename Without the Extension in Java](https://www.baeldung.com/java-filename-without-extension) +- [Writing byte[] to a File in Java](https://www.baeldung.com/java-write-byte-array-file) - [[<-- Prev]](/core-java-modules/core-java-io-2) diff --git a/core-java-modules/core-java-io-3/src/main/java/com/baeldung/filenamewithoutextension/MyFilenameUtil.java b/core-java-modules/core-java-io-3/src/main/java/com/baeldung/filenamewithoutextension/MyFilenameUtil.java new file mode 100644 index 0000000000..102c454c49 --- /dev/null +++ b/core-java-modules/core-java-io-3/src/main/java/com/baeldung/filenamewithoutextension/MyFilenameUtil.java @@ -0,0 +1,14 @@ +package com.baeldung.filenamewithoutextension; + +public class MyFilenameUtil { + private MyFilenameUtil() {} + + public static String removeFileExtension(String filename, boolean removeAllExtensions) { + if (filename == null || filename.isEmpty()) { + return filename; + } + + String extPattern = "(? + + 4.0.0 + core-java-io-4 + 0.1.0-SNAPSHOT + core-java-io-4 + jar + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + ../ + + + + + + commons-io + commons-io + ${commons-io.version} + + + + log4j + log4j + ${log4j.version} + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + + + + 3.6.1 + + + \ No newline at end of file diff --git a/core-java-modules/core-java-io-4/src/test/java/com/baeldung/fileseparator/FilePathSeparatorUnitTest.java b/core-java-modules/core-java-io-4/src/test/java/com/baeldung/fileseparator/FilePathSeparatorUnitTest.java new file mode 100644 index 0000000000..959aae8aff --- /dev/null +++ b/core-java-modules/core-java-io-4/src/test/java/com/baeldung/fileseparator/FilePathSeparatorUnitTest.java @@ -0,0 +1,63 @@ +package com.baeldung.fileseparator; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.util.StringJoiner; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; + +public class FilePathSeparatorUnitTest { + + @Test + @EnabledOnOs(OS.WINDOWS) + public void whenCheckPathSeparator_thenResultIsAsExpectedOnWindows() throws IOException { + assertEquals(";", File.pathSeparator); + assertEquals(';', File.pathSeparatorChar); + } + + @Test + @EnabledOnOs({ OS.LINUX, OS.MAC }) + public void whenCheckPathSeparator_thenResultIsAsExpected() throws IOException { + assertEquals(":", File.pathSeparator); + assertEquals(':', File.pathSeparatorChar); + } + + @Test + @EnabledOnOs(OS.WINDOWS) + public void whenBuildPathUsingString_thenResultIsAsExpectedOnWindows() throws IOException { + String[] pathNames = { "path1", "path2", "path3" }; + String path = String.join(File.pathSeparator, pathNames); + assertEquals("path1;path2;path3",path); + } + + @Test + @EnabledOnOs({ OS.LINUX, OS.MAC }) + public void whenBuildPathUsingString_thenResultIsAsExpected() throws IOException { + String[] pathNames = { "path1", "path2", "path3" }; + String path = String.join(File.pathSeparator, pathNames); + assertEquals("path1:path2:path3", path); + } + + @Test + @EnabledOnOs(OS.WINDOWS) + public void whenbuildPathUsingStringJoiner_thenResultIsAsExpectedOnWindows() throws IOException { + assertEquals("path1;path2", buildPathUsingStringJoiner("path1", "path2")); + } + + @Test + @EnabledOnOs({ OS.LINUX, OS.MAC }) + public void whenbuildPathUsingStringJoiner_thenResultIsAsExpected() throws IOException { + assertEquals("path1:path2", buildPathUsingStringJoiner("path1", "path2")); + } + + private String buildPathUsingStringJoiner(String path1, String path2) { + StringJoiner joiner = new StringJoiner(File.pathSeparator); + joiner.add(path1); + joiner.add(path2); + return joiner.toString(); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-io-4/src/test/java/com/baeldung/fileseparator/FileSeparatorUnitTest.java b/core-java-modules/core-java-io-4/src/test/java/com/baeldung/fileseparator/FileSeparatorUnitTest.java new file mode 100644 index 0000000000..f908dcc9bb --- /dev/null +++ b/core-java-modules/core-java-io-4/src/test/java/com/baeldung/fileseparator/FileSeparatorUnitTest.java @@ -0,0 +1,63 @@ +package com.baeldung.fileseparator; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.File; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; + +public class FileSeparatorUnitTest { + + @Test + @EnabledOnOs(OS.WINDOWS) + public void whenCheckFileSeparator_thenCorrectOnWindows() { + assertEquals("\\", File.separator); + assertEquals('\\', File.separatorChar); + + String fileSeparator = FileSystems.getDefault().getSeparator(); + assertEquals("\\",fileSeparator); + } + + @Test + @EnabledOnOs({ OS.LINUX, OS.MAC }) + public void whenCheckFileSeparator_thenCorrect() { + assertEquals("/", File.separator); + assertEquals('/', File.separatorChar); + + String fileSeparator = FileSystems.getDefault().getSeparator(); + assertEquals("/",fileSeparator); + } + + @Test + @EnabledOnOs(OS.WINDOWS) + public void whenBuildFilePathUsingPathsClass_thenCorrectOnWindows() { + Path path = Paths.get("dir1", "dir2"); + assertEquals("dir1\\dir2", path.toString()); + } + + @Test + @EnabledOnOs({ OS.LINUX, OS.MAC }) + public void whenBuildFilePathUsingPathsClass_thenCorrect() { + Path path = Paths.get("dir1", "dir2"); + assertEquals("dir1/dir2", path.toString()); + } + + @Test + @EnabledOnOs(OS.WINDOWS) + public void whenBuildFilePathUsingFileClass_thenOutputIsAsExpectedOnWindows() { + File file = new File("file1", "file2"); + assertEquals("file1\\file2", file.toString()); + } + + @Test + @EnabledOnOs({ OS.LINUX, OS.MAC }) + public void whenBuildFilePathUsingFileClass_thenOutputIsAsExpected() { + File file = new File("file1", "file2"); + assertEquals("file1/file2", file.toString()); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-io/src/main/java/com/baeldung/unzip/UnzipFile.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/unzip/UnzipFile.java index 140d809d44..a18663f544 100644 --- a/core-java-modules/core-java-io/src/main/java/com/baeldung/unzip/UnzipFile.java +++ b/core-java-modules/core-java-io/src/main/java/com/baeldung/unzip/UnzipFile.java @@ -16,31 +16,42 @@ public class UnzipFile { ZipEntry zipEntry = zis.getNextEntry(); while (zipEntry != null) { final File newFile = newFile(destDir, zipEntry); - final FileOutputStream fos = new FileOutputStream(newFile); - int len; - while ((len = zis.read(buffer)) > 0) { - fos.write(buffer, 0, len); + if (zipEntry.isDirectory()) { + if (!newFile.isDirectory() && !newFile.mkdirs()) { + throw new IOException("Failed to create directory " + newFile); + } + } else { + File parent = newFile.getParentFile(); + if (!parent.isDirectory() && !parent.mkdirs()) { + throw new IOException("Failed to create directory " + parent); + } + + final FileOutputStream fos = new FileOutputStream(newFile); + int len; + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } + fos.close(); } - fos.close(); zipEntry = zis.getNextEntry(); } zis.closeEntry(); zis.close(); } - + /** * @see https://snyk.io/research/zip-slip-vulnerability */ public static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException { File destFile = new File(destinationDir, zipEntry.getName()); - + String destDirPath = destinationDir.getCanonicalPath(); String destFilePath = destFile.getCanonicalPath(); - + if (!destFilePath.startsWith(destDirPath + File.separator)) { throw new IOException("Entry is outside of the target dir: " + zipEntry.getName()); } - + return destFile; } } \ No newline at end of file diff --git a/core-java-modules/core-java-jar/.gitignore b/core-java-modules/core-java-jar/.gitignore new file mode 100644 index 0000000000..ba516c02b5 --- /dev/null +++ b/core-java-modules/core-java-jar/.gitignore @@ -0,0 +1 @@ +!src/test/resources/example-jar/stripe-0.0.1-SNAPSHOT.jar diff --git a/core-java-modules/core-java-jar/README.md b/core-java-modules/core-java-jar/README.md index f6bb7677d4..f83ea496ab 100644 --- a/core-java-modules/core-java-jar/README.md +++ b/core-java-modules/core-java-jar/README.md @@ -7,3 +7,4 @@ This module contains articles about JAR files - [How to Create an Executable JAR with Maven](http://www.baeldung.com/executable-jar-with-maven) - [Importance of Main Manifest Attribute in a Self-Executing JAR](http://www.baeldung.com/java-jar-executable-manifest-main-class) - [Guide to Creating and Running a Jar File in Java](https://www.baeldung.com/java-create-jar) +- [Get Names of Classes Inside a JAR File](https://www.baeldung.com/jar-file-get-class-names) diff --git a/core-java-modules/core-java-jar/src/main/java/com/baeldung/jar/GetClassNamesFromJar.java b/core-java-modules/core-java-jar/src/main/java/com/baeldung/jar/GetClassNamesFromJar.java new file mode 100644 index 0000000000..0d8a67dbd6 --- /dev/null +++ b/core-java-modules/core-java-jar/src/main/java/com/baeldung/jar/GetClassNamesFromJar.java @@ -0,0 +1,43 @@ +package com.baeldung.jar; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +public class GetClassNamesFromJar { + + public static Set getClassNamesFromJarFile(File givenFile) throws IOException { + Set classNames = new HashSet<>(); + try (JarFile jarFile = new JarFile(givenFile)) { + Enumeration e = jarFile.entries(); + while (e.hasMoreElements()) { + JarEntry jarEntry = e.nextElement(); + if (jarEntry.getName().endsWith(".class")) { + String className = jarEntry.getName() + .replace("/", ".") + .replace(".class", ""); + classNames.add(className); + } + } + return classNames; + } + } + + public static Set getClassesFromJarFile(File jarFile) throws IOException, ClassNotFoundException { + Set classNames = getClassNamesFromJarFile(jarFile); + Set classes = new HashSet<>(classNames.size()); + try (URLClassLoader cl = URLClassLoader.newInstance(new URL[] { new URL("jar:file:" + jarFile + "!/") })) { + for (String name : classNames) { + Class clazz = cl.loadClass(name); // Loading the class by its name + classes.add(clazz); + } + } + return classes; + } +} diff --git a/core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/GetClassNamesFromJarUnitTest.java b/core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/GetClassNamesFromJarUnitTest.java new file mode 100644 index 0000000000..7af3ff59fd --- /dev/null +++ b/core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/GetClassNamesFromJarUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.jar; + +import com.google.common.collect.Sets; +import org.junit.Assert; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +public class GetClassNamesFromJarUnitTest { + private static final String JAR_PATH = "example-jar/stripe-0.0.1-SNAPSHOT.jar"; + private static final Set EXPECTED_CLASS_NAMES = Sets.newHashSet( + "com.baeldung.stripe.StripeApplication", + "com.baeldung.stripe.ChargeRequest", + "com.baeldung.stripe.StripeService", + "com.baeldung.stripe.ChargeRequest$Currency", + "com.baeldung.stripe.ChargeController", + "com.baeldung.stripe.CheckoutController"); + + @Test + public void givenJarFilePath_whenLoadClassNames_thenGetClassNames() throws IOException, URISyntaxException { + File jarFile = new File(Objects.requireNonNull(getClass().getClassLoader().getResource(JAR_PATH)).toURI()); + Set classNames = GetClassNamesFromJar.getClassNamesFromJarFile(jarFile); + Assert.assertEquals(EXPECTED_CLASS_NAMES, classNames); + } + + @Test + public void givenJarFilePath_whenLoadClass_thenGetClassObjects() throws IOException, ClassNotFoundException, URISyntaxException { + File jarFile = new File(Objects.requireNonNull(getClass().getClassLoader().getResource(JAR_PATH)).toURI()); + Set classes = GetClassNamesFromJar.getClassesFromJarFile(jarFile); + Set names = classes.stream().map(Class::getName).collect(Collectors.toSet()); + Assert.assertEquals(EXPECTED_CLASS_NAMES, names); + } +} diff --git a/core-java-modules/core-java-jar/src/test/resources/example-jar/stripe-0.0.1-SNAPSHOT.jar b/core-java-modules/core-java-jar/src/test/resources/example-jar/stripe-0.0.1-SNAPSHOT.jar new file mode 100644 index 0000000000..213d7f9400 Binary files /dev/null and b/core-java-modules/core-java-jar/src/test/resources/example-jar/stripe-0.0.1-SNAPSHOT.jar differ diff --git a/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/pom.xml b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/pom.xml index e6b351b1b9..816f5cf9e8 100644 --- a/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/pom.xml +++ b/core-java-modules/core-java-jpms/decoupling-pattern2/consumermodule/pom.xml @@ -17,7 +17,7 @@ com.baeldung.servicemodule - servicemodule + servicemodule2 ${servicemodule.version} @@ -41,4 +41,4 @@ 1.0 - \ No newline at end of file + diff --git a/core-java-modules/core-java-jvm-2/README.md b/core-java-modules/core-java-jvm-2/README.md index 36cafd3288..ccca3a11ac 100644 --- a/core-java-modules/core-java-jvm-2/README.md +++ b/core-java-modules/core-java-jvm-2/README.md @@ -11,4 +11,5 @@ This module contains articles about working with the Java Virtual Machine (JVM). - [Where Is the Array Length Stored in JVM?](https://www.baeldung.com/java-jvm-array-length) - [Memory Address of Objects in Java](https://www.baeldung.com/java-object-memory-address) - [List All Classes Loaded in a Specific Class Loader](https://www.baeldung.com/java-list-classes-class-loader) +- [An Introduction to the Constant Pool in the JVM](https://www.baeldung.com/jvm-constant-pool) - More articles: [[<-- prev]](/core-java-modules/core-java-jvm) diff --git a/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/constantpool/ConstantPool.java b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/constantpool/ConstantPool.java new file mode 100644 index 0000000000..b9aea05272 --- /dev/null +++ b/core-java-modules/core-java-jvm-2/src/main/java/com/baeldung/constantpool/ConstantPool.java @@ -0,0 +1,8 @@ +package com.baeldung.constantpool; + +public class ConstantPool { + + public void sayHello() { + System.out.println("Hello World"); + } +} diff --git a/core-java-modules/core-java-lang-2/pom.xml b/core-java-modules/core-java-lang-2/pom.xml index 5f2d4ec901..d395e8efb1 100644 --- a/core-java-modules/core-java-lang-2/pom.xml +++ b/core-java-modules/core-java-lang-2/pom.xml @@ -69,7 +69,6 @@ 1.19 3.12.2 1.9.4 - 3.10 29.0-jre diff --git a/core-java-modules/core-java-lang-3/README.md b/core-java-modules/core-java-lang-3/README.md index 121d30f20f..8ed945a56c 100644 --- a/core-java-modules/core-java-lang-3/README.md +++ b/core-java-modules/core-java-lang-3/README.md @@ -6,4 +6,10 @@ This module contains articles about core features in the Java language - [Converting a Java String Into a Boolean](https://www.baeldung.com/java-string-to-boolean) - [When are Static Variables Initialized in Java?](https://www.baeldung.com/java-static-variables-initialization) - [Checking if a Class Exists in Java](https://www.baeldung.com/java-check-class-exists) +- [The Difference Between a.getClass() and A.class in Java](https://www.baeldung.com/java-getclass-vs-class) +- [Constants in Java: Patterns and Anti-Patterns](https://www.baeldung.com/java-constants-good-practices) +- [The transient Keyword in Java](https://www.baeldung.com/java-transient-keyword) +- [How to Access an Iteration Counter in a For Each Loop](https://www.baeldung.com/java-foreach-counter) +- [Comparing Doubles in Java](https://www.baeldung.com/java-comparing-doubles) +- [Guide to Implementing the compareTo Method](https://www.baeldung.com/java-compareto) - [[<-- Prev]](/core-java-modules/core-java-lang-2) diff --git a/core-java-modules/core-java-lang-3/pom.xml b/core-java-modules/core-java-lang-3/pom.xml index de290717b1..f98074ad1b 100644 --- a/core-java-modules/core-java-lang-3/pom.xml +++ b/core-java-modules/core-java-lang-3/pom.xml @@ -23,6 +23,18 @@ ${assertj.version} test + + com.google.guava + guava + ${guava.version} + test + + + org.apache.commons + commons-math3 + 3.6.1 + test + diff --git a/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/compareto/BankAccount.java b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/compareto/BankAccount.java new file mode 100644 index 0000000000..db1f41e6df --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/compareto/BankAccount.java @@ -0,0 +1,16 @@ +package com.baeldung.compareto; + +public class BankAccount implements Comparable { + + private final int balance; + + public BankAccount(int balance) { + this.balance = balance; + } + + @Override + public int compareTo(BankAccount anotherAccount) { + return this.balance - anotherAccount.balance; + } + +} diff --git a/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/compareto/BankAccountFix.java b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/compareto/BankAccountFix.java new file mode 100644 index 0000000000..95e55fdf22 --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/compareto/BankAccountFix.java @@ -0,0 +1,16 @@ +package com.baeldung.compareto; + +public class BankAccountFix implements Comparable { + + private final int balance; + + public BankAccountFix(int balance) { + this.balance = balance; + } + + @Override + public int compareTo(BankAccountFix anotherAccount) { + return Integer.compare(this.balance, anotherAccount.balance); + } + +} diff --git a/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/compareto/FootballPlayer.java b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/compareto/FootballPlayer.java new file mode 100644 index 0000000000..173ee32434 --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/compareto/FootballPlayer.java @@ -0,0 +1,32 @@ +package com.baeldung.compareto; + +public class FootballPlayer implements Comparable { + + private final String name; + private final int goalsScored; + + public FootballPlayer(String name, int goalsScored) { + this.name = name; + this.goalsScored = goalsScored; + } + + public String getName() { + return name; + } + + @Override + public int compareTo(FootballPlayer anotherPlayer) { + return Integer.compare(this.goalsScored, anotherPlayer.goalsScored); + } + + @Override + public boolean equals(Object object) { + if (this == object) + return true; + if (object == null || getClass() != object.getClass()) + return false; + FootballPlayer player = (FootballPlayer) object; + return name.equals(player.name); + } + +} diff --git a/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/compareto/HandballPlayer.java b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/compareto/HandballPlayer.java new file mode 100644 index 0000000000..022155ccae --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/compareto/HandballPlayer.java @@ -0,0 +1,12 @@ +package com.baeldung.compareto; + +public class HandballPlayer { + + private final String name; + private final int height; + + public HandballPlayer(String name, int height) { + this.name = name; + this.height = height; + } +} diff --git a/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/constantspatterns/Calculator.java b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/constantspatterns/Calculator.java new file mode 100644 index 0000000000..78b51c1c93 --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/constantspatterns/Calculator.java @@ -0,0 +1,37 @@ +package com.baeldung.constantspatterns; + +public class Calculator { + public static final double PI = 3.14159265359; + private static final double UPPER_LIMIT = 0x1.fffffffffffffP+1023; + + public enum Operation { + ADD, SUBTRACT, DIVIDE, MULTIPLY + } + + public double operateOnTwoNumbers(double numberOne, double numberTwo, Operation operation) { + if (numberOne > UPPER_LIMIT) { + throw new IllegalArgumentException("'numberOne' is too large"); + } + if (numberTwo > UPPER_LIMIT) { + throw new IllegalArgumentException("'numberTwo' is too large"); + } + double answer = 0; + + switch (operation) { + case ADD: + answer = numberOne + numberTwo; + break; + case SUBTRACT: + answer = numberOne - numberTwo; + break; + case DIVIDE: + answer = numberOne / numberTwo; + break; + case MULTIPLY: + answer = numberOne * numberTwo; + break; + } + + return answer; + } +} diff --git a/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/constantspatterns/CalculatorConstants.java b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/constantspatterns/CalculatorConstants.java new file mode 100644 index 0000000000..2237782b00 --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/constantspatterns/CalculatorConstants.java @@ -0,0 +1,10 @@ +package com.baeldung.constantspatterns; + +public interface CalculatorConstants { + double PI = 3.14159265359; + double UPPER_LIMIT = 0x1.fffffffffffffP+1023; + + enum Operation { + ADD, SUBTRACT, MULTIPLY, DIVIDE + }; +} diff --git a/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/constantspatterns/GeometryCalculator.java b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/constantspatterns/GeometryCalculator.java new file mode 100644 index 0000000000..47a0dc5233 --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/constantspatterns/GeometryCalculator.java @@ -0,0 +1,32 @@ +package com.baeldung.constantspatterns; + +public class GeometryCalculator implements CalculatorConstants { + public static final double UPPER_LIMIT = 100000000000000000000.0; + + public double operateOnTwoNumbers(double numberOne, double numberTwo, Operation operation) { + if (numberOne > UPPER_LIMIT) { + throw new IllegalArgumentException("'numberOne' is too large"); + } + if (numberTwo > UPPER_LIMIT) { + throw new IllegalArgumentException("'numberTwo' is too large"); + } + double answer = 0; + + switch (operation) { + case ADD: + answer = numberOne + numberTwo; + break; + case SUBTRACT: + answer = numberOne - numberTwo; + break; + case DIVIDE: + answer = numberOne / numberTwo; + break; + case MULTIPLY: + answer = numberOne * numberTwo; + break; + } + + return answer; + } +} diff --git a/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/constantspatterns/calculations/MathConstants.java b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/constantspatterns/calculations/MathConstants.java new file mode 100644 index 0000000000..1c9c4172ca --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/constantspatterns/calculations/MathConstants.java @@ -0,0 +1,16 @@ +package com.baeldung.constantspatterns.calculations; + +public final class MathConstants { + public static final double PI = 3.14159265359; + static final double GOLDEN_RATIO = 1.6180; + static final double GRAVITATIONAL_ACCELERATION = 9.8; + static final double EULERS_NUMBER = 2.7182818284590452353602874713527; + + public enum Operation { + ADD, SUBTRACT, DIVIDE, MULTIPLY + } + + private MathConstants() { + + } +} diff --git a/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/iterationcounter/IterationCounter.java b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/iterationcounter/IterationCounter.java new file mode 100644 index 0000000000..40d997cb0e --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/iterationcounter/IterationCounter.java @@ -0,0 +1,68 @@ +package com.baeldung.iterationcounter; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BiConsumer; +import java.util.function.Consumer; +import java.util.stream.Stream; + +public class IterationCounter { + public static final List IMDB_TOP_MOVIES = Arrays.asList("The Shawshank Redemption", + "The Godfather", "The Godfather II", "The Dark Knight"); + + public static List getRankingsWithForLoop(List movies) { + List rankings = new ArrayList<>(); + for (int i = 0; i < movies.size(); i++) { + String ranking = (i + 1) + ": " + movies.get(i); + rankings.add(ranking); + } + return rankings; + } + + public static List getRankingsWithForEachLoop(List movies) { + List rankings = new ArrayList<>(); + int i = 0; + for (String movie : movies) { + String ranking = (i + 1) + ": " + movies.get(i); + rankings.add(ranking); + + i++; + } + return rankings; + } + + public static List getRankingsWithFunctionalForEachLoop(List movies) { + List rankings = new ArrayList<>(); + forEachWithCounter(movies, (i, movie) -> { + String ranking = (i + 1) + ": " + movie; + rankings.add(ranking); + }); + + return rankings; + } + + public static void forEachWithCounter(Iterable source, BiConsumer consumer) { + int i = 0; + for (T item : source) { + consumer.accept(i, item); + i++; + } + } + + public static List getRankingsWithStream(Stream movies) { + List rankings = new ArrayList<>(); + movies.forEach(withCounter((i, movie) -> { + String ranking = (i + 1) + ": " + movie; + rankings.add(ranking); + })); + + return rankings; + } + + public static Consumer withCounter(BiConsumer consumer) { + AtomicInteger counter = new AtomicInteger(0); + return item -> consumer.accept(counter.getAndIncrement(), item); + } +} diff --git a/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/transientkw/Book.java b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/transientkw/Book.java new file mode 100644 index 0000000000..5822d83841 --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/transientkw/Book.java @@ -0,0 +1,42 @@ +package com.baeldung.transientkw; + +import java.io.Serializable; + +public class Book implements Serializable { + + private static final long serialVersionUID = -2936687026040726549L; + + private String bookName; + private transient String description; + private transient int copies; + private final transient String bookCategory = "Fiction"; + + public String getBookName() { + return bookName; + } + + public void setBookName(String bookName) { + this.bookName = bookName; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public int getCopies() { + return copies; + } + + public void setCopies(int copies) { + this.copies = copies; + } + + public String getBookCategory() { + return bookCategory; + } + +} diff --git a/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/transientkw/BookSerDe.java b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/transientkw/BookSerDe.java new file mode 100644 index 0000000000..38e018baa3 --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/main/java/com/baeldung/transientkw/BookSerDe.java @@ -0,0 +1,44 @@ +package com.baeldung.transientkw; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +public class BookSerDe { + static String fileName = "book.ser"; + + /** + * Method to serialize Book objects to the file + * @throws FileNotFoundException + */ + public static void serialize(Book book) throws Exception { + FileOutputStream file = new FileOutputStream(fileName); + ObjectOutputStream out = new ObjectOutputStream(file); + + out.writeObject(book); + + out.close(); + file.close(); + } + + /** + * Method to deserialize the person object + * @return book + * @throws IOException, ClassNotFoundException + */ + public static Book deserialize() throws Exception { + FileInputStream file = new FileInputStream(fileName); + ObjectInputStream in = new ObjectInputStream(file); + + Book book = (Book) in.readObject(); + + in.close(); + file.close(); + + return book; + } + +} diff --git a/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/comparedouble/CompareDoubleUnitTest.java b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/comparedouble/CompareDoubleUnitTest.java new file mode 100644 index 0000000000..c70dabd014 --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/comparedouble/CompareDoubleUnitTest.java @@ -0,0 +1,71 @@ +package com.baeldung.comparedouble; + +import com.google.common.math.DoubleMath; +import org.apache.commons.math3.util.Precision; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; + +public class CompareDoubleUnitTest { + + @Test + public void givenDoubleValuesThatShouldHaveSameValue_whenUsingSimpleComparison_thenFails() { + double d1 = getFirstDouble(0); + + double d2 = .1 * 8; + + assertThat(d1 == d2).isFalse(); + } + + @Test + public void givenDoubleValuesThatShouldHaveSameValue_whenUsingThresholdComparison_thenSuccess() { + double d1 = getFirstDouble(0); + + double d2 = .1 * 8; + + double epsilon = 0.000001d; + + assertThat(Math.abs(d1 - d2) < epsilon).isTrue(); + } + + @Test + public void givenDoubleValuesThatShouldHaveSameValue_whenUsingGuavaFuzzyComparison_thenSuccess() { + double d1 = getFirstDouble(0); + double d2 = .1 * 8; + + double epsilon = 0.000001d; + + + assertThat(DoubleMath.fuzzyEquals(d1, d2, epsilon)).isTrue(); + } + + @Test + public void givenDoubleValuesThatShouldHaveSameValue_whenUsingCommonsMathComparison_thenSuccess() { + double d1 = getFirstDouble(0); + double d2 = .1 * 8; + + double epsilon = 0.000001d; + + + assertThat(Precision.equals(d1, d2, epsilon)).isTrue(); + assertThat(Precision.equals(d1, d2)).isTrue(); + } + + @Test + public void givenDoubleValuesThatShouldHaveSameValue_whenUsingJunitComparison_thenSuccess() { + double d1 = getFirstDouble(0); + double d2 = .1 * 8; + + double epsilon = 0.000001d; + + assertEquals(d1, d2, epsilon); + } + + private double getFirstDouble(double d1) { + for (int i = 1; i <= 8; i++) { + d1 += .1; + } + return d1; + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/ArraysSortingUnitTest.java b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/ArraysSortingUnitTest.java new file mode 100644 index 0000000000..2082386dba --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/ArraysSortingUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.compareto; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ArraysSortingUnitTest { + + @Test + public void givenArrayOfNumbers_whenSortingArray_thenNumbersAreSortedAscending() { + int[] numbers = new int[] {5, 3, 9, 11, 1, 7}; + Arrays.sort(numbers); + assertThat(numbers).containsExactly(1, 3, 5, 7, 9, 11); + } + + @Test + public void givenArrayOfStrings_whenSortingArray_thenStringsAreSortedAlphabetically() { + String[] players = new String[] {"ronaldo", "modric", "ramos", "messi"}; + Arrays.sort(players); + assertThat(players).containsExactly("messi", "modric", "ramos", "ronaldo"); + } + +} diff --git a/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/BankAccountFixUnitTest.java b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/BankAccountFixUnitTest.java new file mode 100644 index 0000000000..9ca16d1372 --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/BankAccountFixUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.compareto; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class BankAccountFixUnitTest { + + @Test + public void givenComparisonBasedImpl_whenUsingSmallIntegers_thenComparisonWorks() { + BankAccountFix accountOne = new BankAccountFix(5000); + BankAccountFix accountTwo = new BankAccountFix(1000); + int comparison = accountOne.compareTo(accountTwo); + assertThat(comparison).isPositive(); + } + + @Test + public void givenComparisonBasedImpl_whenUsingLargeIntegers_thenComparisonWorks() { + BankAccountFix accountOne = new BankAccountFix(1900000000); + BankAccountFix accountTwo = new BankAccountFix(-2000000000); + int comparison = accountOne.compareTo(accountTwo); + assertThat(comparison).isPositive(); + } + +} diff --git a/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/BankAccountUnitTest.java b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/BankAccountUnitTest.java new file mode 100644 index 0000000000..6ef9372ff9 --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/BankAccountUnitTest.java @@ -0,0 +1,25 @@ +package com.baeldung.compareto; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + +public class BankAccountUnitTest { + + @Test + public void givenSubtractionBasedImpl_whenUsingSmallIntegers_thenComparisonWorks() { + BankAccount accountOne = new BankAccount(5000); + BankAccount accountTwo = new BankAccount(1000); + int comparison = accountOne.compareTo(accountTwo); + assertThat(comparison).isPositive(); + } + + @Test + public void givenSubtractionBasedImpl_whenUsingLargeIntegers_thenComparisonBreaks() { + BankAccount accountOne = new BankAccount(1900000000); + BankAccount accountTwo = new BankAccount(-2000000000); + int comparison = accountOne.compareTo(accountTwo); + assertThat(comparison).isNegative(); + } + +} diff --git a/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/FootballPlayerUnitTest.java b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/FootballPlayerUnitTest.java new file mode 100644 index 0000000000..6abd1e113b --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/FootballPlayerUnitTest.java @@ -0,0 +1,57 @@ +package com.baeldung.compareto; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import java.util.TreeSet; + +import static org.assertj.core.api.Assertions.assertThat; + +public class FootballPlayerUnitTest { + + @Test + public void givenInconsistentCompareToAndEqualsImpl_whenUsingSortedSet_thenSomeElementsAreNotAdded() { + FootballPlayer messi = new FootballPlayer("Messi", 800); + FootballPlayer ronaldo = new FootballPlayer("Ronaldo", 800); + + TreeSet set = new TreeSet<>(); + set.add(messi); + set.add(ronaldo); + + assertThat(set).hasSize(1); + assertThat(set).doesNotContain(ronaldo); + } + + @Test + public void givenCompareToImpl_whenUsingCustomComparator_thenComparatorLogicIsApplied() { + FootballPlayer ronaldo = new FootballPlayer("Ronaldo", 900); + FootballPlayer messi = new FootballPlayer("Messi", 800); + FootballPlayer modric = new FootballPlayer("Modric", 100); + + List players = Arrays.asList(ronaldo, messi, modric); + Comparator nameComparator = Comparator.comparing(FootballPlayer::getName); + Collections.sort(players, nameComparator); + + assertThat(players).containsExactly(messi, modric, ronaldo); + } + + @Test + public void givenCompareToImpl_whenSavingElementsInTreeMap_thenKeysAreSortedUsingCompareTo() { + FootballPlayer ronaldo = new FootballPlayer("Ronaldo", 900); + FootballPlayer messi = new FootballPlayer("Messi", 800); + FootballPlayer modric = new FootballPlayer("Modric", 100); + + Map players = new TreeMap<>(); + players.put(ronaldo, "forward"); + players.put(messi, "forward"); + players.put(modric, "midfielder"); + + assertThat(players.keySet()).containsExactly(modric, messi, ronaldo); + } + +} diff --git a/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/HandballPlayerUnitTest.java b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/HandballPlayerUnitTest.java new file mode 100644 index 0000000000..143286f15f --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/compareto/HandballPlayerUnitTest.java @@ -0,0 +1,20 @@ +package com.baeldung.compareto; + +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class HandballPlayerUnitTest { + + @Test + public void givenComparableIsNotImplemented_whenSortingArray_thenExceptionIsThrown() { + HandballPlayer duvnjak = new HandballPlayer("Duvnjak", 197); + HandballPlayer hansen = new HandballPlayer("Hansen", 196); + + HandballPlayer[] players = new HandballPlayer[] {duvnjak, hansen}; + + assertThatExceptionOfType(ClassCastException.class).isThrownBy(() -> Arrays.sort(players)); + } + +} diff --git a/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/constantspatterns/ConstantPatternUnitTest.java b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/constantspatterns/ConstantPatternUnitTest.java new file mode 100644 index 0000000000..ba8f237fd3 --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/constantspatterns/ConstantPatternUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.constantspatterns; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.Test; + +public class ConstantPatternUnitTest { + @Test + public void givenTwoNumbersAndAdd_whenCallingCalculatorOperatOneTwoNumbers_thenCorrectAnswerReturned() { + Calculator calculator = new Calculator(); + double expected = 4; + double answer = calculator.operateOnTwoNumbers(2, 2, Calculator.Operation.ADD); + assertEquals(expected, answer); + } + + @Test + public void givenTwoNumbersAndAdd_whenCallingGeometryCalculatorOperatOneTwoNumbers_thenCorrectAnswerReturned() { + GeometryCalculator calculator = new GeometryCalculator(); + double expected = 4; + double answer = calculator.operateOnTwoNumbers(2, 2, GeometryCalculator.Operation.ADD); + assertEquals(expected, answer); + } +} diff --git a/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/iterationcounter/IterationCounterUnitTest.java b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/iterationcounter/IterationCounterUnitTest.java new file mode 100644 index 0000000000..6746e570ca --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/iterationcounter/IterationCounterUnitTest.java @@ -0,0 +1,36 @@ +package com.baeldung.iterationcounter; + +import org.junit.Test; + +import static com.baeldung.iterationcounter.IterationCounter.*; +import static org.assertj.core.api.Assertions.*; + +public class IterationCounterUnitTest { + @Test + public void givenRankings_whenCalculateWithForLoop_thenRankingsCorrect() { + assertThat(getRankingsWithForLoop(IMDB_TOP_MOVIES)) + .containsExactly("1: The Shawshank Redemption", + "2: The Godfather", "3: The Godfather II", "4: The Dark Knight"); + } + + @Test + public void givenRankings_whenCalculateWithForEachLoop_thenRankingsCorrect() { + assertThat(getRankingsWithForEachLoop(IMDB_TOP_MOVIES)) + .containsExactly("1: The Shawshank Redemption", + "2: The Godfather", "3: The Godfather II", "4: The Dark Knight"); + } + + @Test + public void givenRankings_whenCalculateWithFunctionalForEach_thenRankingsCorrect() { + assertThat(getRankingsWithFunctionalForEachLoop(IMDB_TOP_MOVIES)) + .containsExactly("1: The Shawshank Redemption", + "2: The Godfather", "3: The Godfather II", "4: The Dark Knight"); + } + + @Test + public void givenRankings_whenCalculateWithStream_thenRankingsCorrect() { + assertThat(getRankingsWithStream(IMDB_TOP_MOVIES.stream())) + .containsExactly("1: The Shawshank Redemption", + "2: The Godfather", "3: The Godfather II", "4: The Dark Knight"); + } +} diff --git a/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/transientkw/TransientUnitTest.java b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/transientkw/TransientUnitTest.java new file mode 100644 index 0000000000..cf63a0ddda --- /dev/null +++ b/core-java-modules/core-java-lang-3/src/test/java/com/baeldung/transientkw/TransientUnitTest.java @@ -0,0 +1,35 @@ +package com.baeldung.transientkw; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import org.junit.jupiter.api.Test; + +class TransientUnitTest { + + @Test + void givenTransient_whenSerDe_thenVerifyValues() throws Exception { + Book book = new Book(); + book.setBookName("Java Reference"); + book.setDescription("will not be saved"); + book.setCopies(25); + + BookSerDe.serialize(book); + Book book2 = BookSerDe.deserialize(); + + assertEquals("Java Reference", book2.getBookName()); + assertNull(book2.getDescription()); + assertEquals(0, book2.getCopies()); + } + + @Test + void givenFinalTransient_whenSerDe_thenValuePersisted() throws Exception { + Book book = new Book(); + + BookSerDe.serialize(book); + Book book2 = BookSerDe.deserialize(); + + assertEquals("Fiction", book2.getBookCategory()); + } + +} diff --git a/core-java-modules/core-java-lang-math-2/README.md b/core-java-modules/core-java-lang-math-2/README.md index 69ee00b5a5..5e1dc5af0e 100644 --- a/core-java-modules/core-java-lang-math-2/README.md +++ b/core-java-modules/core-java-lang-math-2/README.md @@ -9,9 +9,9 @@ - [Check If Two Rectangles Overlap In Java](https://www.baeldung.com/java-check-if-two-rectangles-overlap) - [Calculate the Distance Between Two Points in Java](https://www.baeldung.com/java-distance-between-two-points) - [Find the Intersection of Two Lines in Java](https://www.baeldung.com/java-intersection-of-two-lines) -- [Round Up to the Nearest Hundred](https://www.baeldung.com/java-round-up-nearest-hundred) +- [Round Up to the Nearest Hundred in Java](https://www.baeldung.com/java-round-up-nearest-hundred) - [Convert Latitude and Longitude to a 2D Point in Java](https://www.baeldung.com/java-convert-latitude-longitude) - [Debugging with Eclipse](https://www.baeldung.com/eclipse-debugging) - [Matrix Multiplication in Java](https://www.baeldung.com/java-matrix-multiplication) -- [Largest Power of 2 That Is Less Than the Given Number](https://www.baeldung.com/java-largest-power-of-2-less-than-number) -- More articles: [[<-- Prev]](/core-java-modules/core-java-lang-math) +- [Largest Power of 2 That Is Less Than the Given Number with Java](https://www.baeldung.com/java-largest-power-of-2-less-than-number) +- More articles: [[<-- Prev]](/core-java-modules/core-java-lang-math)[[Next -->]](/core-java-modules/core-java-lang-math-3) diff --git a/core-java-modules/core-java-lang-math-3/README.md b/core-java-modules/core-java-lang-math-3/README.md new file mode 100644 index 0000000000..1dd3a3c7e0 --- /dev/null +++ b/core-java-modules/core-java-lang-math-3/README.md @@ -0,0 +1,8 @@ +========= + +## Core Java 8 Cookbooks and Examples - Part 3 + +### Relevant articles: + +- [Evaluating a Math Expression in Java](https://www.baeldung.com/java-evaluate-math-expression-string) +- More articles: [[<-- Prev]](/core-java-modules/core-java-lang-math-2) diff --git a/core-java-modules/core-java-lang-math-3/pom.xml b/core-java-modules/core-java-lang-math-3/pom.xml new file mode 100644 index 0000000000..27c2372ab6 --- /dev/null +++ b/core-java-modules/core-java-lang-math-3/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + core-java-lang-math-3 + 0.0.1-SNAPSHOT + core-java-lang-math-3 + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + ../ + + + + + net.objecthunter + exp4j + 0.4.8 + + + + com.fathzer + javaluator + 3.0.3 + + + + + + + + + diff --git a/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/math/evaluate/EvalauteMathExpressionsUnitTest.java b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/math/evaluate/EvalauteMathExpressionsUnitTest.java new file mode 100644 index 0000000000..a251e8d545 --- /dev/null +++ b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/math/evaluate/EvalauteMathExpressionsUnitTest.java @@ -0,0 +1,91 @@ +package com.baeldung.math.evaluate; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import com.fathzer.soft.javaluator.DoubleEvaluator; +import com.fathzer.soft.javaluator.StaticVariableSet; + +import net.objecthunter.exp4j.Expression; +import net.objecthunter.exp4j.ExpressionBuilder; + +public class EvalauteMathExpressionsUnitTest { + + @Test + public void givenSimpleExpression_whenCallEvaluateMethod_thenSuccess() { + Expression expression = new ExpressionBuilder("3+2").build(); + double result = expression.evaluate(); + Assertions.assertEquals(5, result); + } + + @Test + public void givenTwoVariables_whenCallEvaluateMethod_thenSuccess() { + Expression expression = new ExpressionBuilder("3x+2y").variables("x", "y") + .build() + .setVariable("x", 2) + .setVariable("y", 3); + double result = expression.evaluate(); + Assertions.assertEquals(12, result); + } + + @Test + public void givenMathFunctions_whenCallEvaluateMethod_thenSuccess() { + Expression expression = new ExpressionBuilder("sin(x)*sin(x)+cos(x)*cos(x)").variables("x") + .build() + .setVariable("x", 0.5); + double result = expression.evaluate(); + Assertions.assertEquals(1, result); + } + + @Test + public void givenExpression_whenCallEvaluateMethod_thenSuccess() { + String expression = "3+2"; + DoubleEvaluator eval = new DoubleEvaluator(); + Double result = eval.evaluate(expression); + Assertions.assertEquals(5, result); + } + + @Test + public void givenVariables_whenCallEvaluateMethod_thenSuccess() { + String expression = "3*x+2*y"; + DoubleEvaluator eval = new DoubleEvaluator(); + StaticVariableSet variables = new StaticVariableSet(); + variables.set("x", 2.0); + variables.set("y", 3.0); + Double result = eval.evaluate(expression, variables); + Assertions.assertEquals(12, result); + } + + @Test + public void givenMathFunction_whenCallEvaluateMethod_thenSuccess() { + String expression = "sin(x)*sin(x)+cos(x)*cos(x)"; + DoubleEvaluator eval = new DoubleEvaluator(); + StaticVariableSet variables = new StaticVariableSet(); + variables.set("x", 0.5); + Double result = eval.evaluate(expression, variables); + Assertions.assertEquals(1, result); + } + + @Test + public void givenJavaScriptingApiAndSimpleExpression_whenCallEvalMethod_thenSuccess() throws ScriptException { + ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); + ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("JavaScript"); + String expression = "3+2"; + Integer result = (Integer) scriptEngine.eval(expression); + Assertions.assertEquals(5, result); + } + + @Test + public void givenJavaScriptingApi_whenCallEvalMethod_thenSuccess() throws ScriptException { + ScriptEngineManager scriptEngineManager = new ScriptEngineManager(); + ScriptEngine scriptEngine = scriptEngineManager.getEngineByName("JavaScript"); + String expression = "x=2; y=3; 3*x+2*y;"; + Double result = (Double) scriptEngine.eval(expression); + Assertions.assertEquals(12, result); + } + +} diff --git a/core-java-modules/core-java-lang-oop-generics/README.md b/core-java-modules/core-java-lang-oop-generics/README.md index 74b9df7c65..9c9080ece3 100644 --- a/core-java-modules/core-java-lang-oop-generics/README.md +++ b/core-java-modules/core-java-lang-oop-generics/README.md @@ -7,3 +7,4 @@ This module contains articles about generics in Java - [Type Erasure in Java Explained](https://www.baeldung.com/java-type-erasure) - [Raw Types in Java](https://www.baeldung.com/raw-types-java) - [Super Type Tokens in Java Generics](https://www.baeldung.com/java-super-type-tokens) +- [Java Warning “unchecked conversion”](https://www.baeldung.com/java-unchecked-conversion) diff --git a/core-java-modules/core-java-lang-oop-generics/pom.xml b/core-java-modules/core-java-lang-oop-generics/pom.xml index 65a0aeac59..1a538edac9 100644 --- a/core-java-modules/core-java-lang-oop-generics/pom.xml +++ b/core-java-modules/core-java-lang-oop-generics/pom.xml @@ -13,4 +13,32 @@ core-java-lang-oop-generics jar + + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + + + + 1.8 + 1.8 + + \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop-generics/src/main/java/com/baeldung/uncheckedconversion/UncheckedConversion.java b/core-java-modules/core-java-lang-oop-generics/src/main/java/com/baeldung/uncheckedconversion/UncheckedConversion.java new file mode 100644 index 0000000000..9ad4a92077 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-generics/src/main/java/com/baeldung/uncheckedconversion/UncheckedConversion.java @@ -0,0 +1,45 @@ +package com.baeldung.uncheckedconversion; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; + +public class UncheckedConversion { + public static List getRawList() { + List result = new ArrayList(); + result.add("I am the 1st String."); + result.add("I am the 2nd String."); + result.add("I am the 3rd String."); + return result; + } + + public static List getRawListWithMixedTypes() { + List result = new ArrayList(); + result.add("I am the 1st String."); + result.add("I am the 2nd String."); + result.add("I am the 3rd String."); + result.add(new Date()); + return result; + } + + public static List castList(Class clazz, Collection rawCollection) { + List result = new ArrayList<>(rawCollection.size()); + for (Object o : rawCollection) { + try { + result.add(clazz.cast(o)); + } catch (ClassCastException e) { + // log the exception or other error handling + } + } + return result; + } + + public static List castList2(Class clazz, Collection rawCollection) throws ClassCastException { + List result = new ArrayList<>(rawCollection.size()); + for (Object o : rawCollection) { + result.add(clazz.cast(o)); + } + return result; + } +} diff --git a/core-java-modules/core-java-lang-oop-generics/src/test/java/com/baeldung/uncheckedconversion/UncheckedConversionUnitTest.java b/core-java-modules/core-java-lang-oop-generics/src/test/java/com/baeldung/uncheckedconversion/UncheckedConversionUnitTest.java new file mode 100644 index 0000000000..37b9a878d3 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-generics/src/test/java/com/baeldung/uncheckedconversion/UncheckedConversionUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.uncheckedconversion; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.List; + +public class UncheckedConversionUnitTest { + + @Test + public void givenRawList_whenAssignToTypedList_shouldHaveCompilerWarning() { + List fromRawList = UncheckedConversion.getRawList(); + Assert.assertEquals(3, fromRawList.size()); + Assert.assertEquals("I am the 1st String.", fromRawList.get(0)); + } + + @Test(expected = ClassCastException.class) + public void givenRawList_whenListHasMixedType_shouldThrowClassCastException() { + List fromRawList = UncheckedConversion.getRawListWithMixedTypes(); + Assert.assertEquals(4, fromRawList.size()); + Assert.assertFalse(fromRawList.get(3).endsWith("String.")); + } + + @Test + public void givenRawList_whenAssignToTypedListAfterCallingCastList_shouldOnlyHaveElementsWithExpectedType() { + List rawList = UncheckedConversion.getRawListWithMixedTypes(); + List strList = UncheckedConversion.castList(String.class, rawList); + Assert.assertEquals(4, rawList.size()); + Assert.assertEquals("One element with the wrong type has been filtered out.", 3, strList.size()); + Assert.assertTrue(strList.stream().allMatch(el -> el.endsWith("String."))); + } + + @Test(expected = ClassCastException.class) + public void givenRawListWithWrongType_whenAssignToTypedListAfterCallingCastList2_shouldThrowException() { + List rawList = UncheckedConversion.getRawListWithMixedTypes(); + UncheckedConversion.castList2(String.class, rawList); + } + +} diff --git a/core-java-modules/core-java-lang-oop-types/README.md b/core-java-modules/core-java-lang-oop-types/README.md index 459352c490..6c649877b3 100644 --- a/core-java-modules/core-java-lang-oop-types/README.md +++ b/core-java-modules/core-java-lang-oop-types/README.md @@ -12,3 +12,4 @@ This module contains articles about types in Java - [Attaching Values to Java Enum](https://www.baeldung.com/java-enum-values) - [A Guide to Java Enums](https://www.baeldung.com/a-guide-to-java-enums) - [Determine if an Object is of Primitive Type](https://www.baeldung.com/java-object-primitive-type) +- [Extending Enums in Java](https://www.baeldung.com/java-extending-enums) diff --git a/core-java-modules/core-java-lang-oop-types/pom.xml b/core-java-modules/core-java-lang-oop-types/pom.xml index ee167bbae2..c4efd9b8d2 100644 --- a/core-java-modules/core-java-lang-oop-types/pom.xml +++ b/core-java-modules/core-java-lang-oop-types/pom.xml @@ -12,12 +12,20 @@ core-java-lang-oop-types core-java-lang-oop-types jar - + org.apache.commons commons-lang3 ${commons-lang3.version} + + commons-codec + commons-codec + ${commons-codec.version} + + + 1.15 + \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/Application.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/Application.java new file mode 100644 index 0000000000..ad3d861d6a --- /dev/null +++ b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/Application.java @@ -0,0 +1,35 @@ +package com.baeldung.enums.extendenum; + +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.EnumMap; +import java.util.Map; + +public class Application { + private static final Map OPERATION_MAP; + + static { + OPERATION_MAP = new EnumMap<>(ImmutableOperation.class); + OPERATION_MAP.put(ImmutableOperation.TO_LOWER, String::toLowerCase); + OPERATION_MAP.put(ImmutableOperation.INVERT_CASE, StringUtils::swapCase); + OPERATION_MAP.put(ImmutableOperation.REMOVE_WHITESPACES, input -> input.replaceAll("\\s", "")); + + if (Arrays.stream(ImmutableOperation.values()).anyMatch(it -> !OPERATION_MAP.containsKey(it))) { + throw new IllegalStateException("Unmapped enum constant found!"); + } + } + + public String applyImmutableOperation(ImmutableOperation operation, String input) { + return OPERATION_MAP.get(operation).apply(input); + } + + public String getDescription(StringOperation stringOperation) { + return stringOperation.getDescription(); + } + + public String applyOperation(StringOperation operation, String input) { + return operation.apply(input); + } + +} diff --git a/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/ApplicationWithEx.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/ApplicationWithEx.java new file mode 100644 index 0000000000..e9cbad6b7c --- /dev/null +++ b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/ApplicationWithEx.java @@ -0,0 +1,26 @@ +package com.baeldung.enums.extendenum; + +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.EnumMap; +import java.util.Map; + +public class ApplicationWithEx { + private static final Map OPERATION_MAP; + + static { + OPERATION_MAP = new EnumMap<>(ImmutableOperation.class); + OPERATION_MAP.put(ImmutableOperation.TO_LOWER, String::toLowerCase); + OPERATION_MAP.put(ImmutableOperation.INVERT_CASE, StringUtils::swapCase); + // ImmutableOperation.REMOVE_WHITESPACES is not mapped + + if (Arrays.stream(ImmutableOperation.values()).anyMatch(it -> !OPERATION_MAP.containsKey(it))) { + throw new IllegalStateException("Unmapped enum constant found!"); + } + } + + public String applyImmutableOperation(ImmutableOperation operation, String input) { + return OPERATION_MAP.get(operation).apply(input); + } +} diff --git a/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/BasicStringOperation.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/BasicStringOperation.java new file mode 100644 index 0000000000..267b02daf4 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/BasicStringOperation.java @@ -0,0 +1,33 @@ +package com.baeldung.enums.extendenum; + +public enum BasicStringOperation implements StringOperation { + TRIM("Removing leading and trailing spaces.") { + @Override + public String apply(String input) { + return input.trim(); + } + }, + TO_UPPER("Changing all characters into upper case.") { + @Override + public String apply(String input) { + return input.toUpperCase(); + } + }, + REVERSE("Reversing the given string.") { + @Override + public String apply(String input) { + return new StringBuilder(input).reverse().toString(); + } + }; + + private String description; + + public String getDescription() { + return description; + } + + BasicStringOperation(String description) { + this.description = description; + } +} + diff --git a/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/ExtendedStringOperation.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/ExtendedStringOperation.java new file mode 100644 index 0000000000..6184837b26 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/ExtendedStringOperation.java @@ -0,0 +1,31 @@ +package com.baeldung.enums.extendenum; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.codec.digest.DigestUtils; + +public enum ExtendedStringOperation implements StringOperation { + MD5_ENCODE("Encoding the given string using the MD5 algorithm.") { + @Override + public String apply(String input) { + return DigestUtils.md5Hex(input); + } + }, + BASE64_ENCODE("Encoding the given string using the BASE64 algorithm.") { + @Override + public String apply(String input) { + return new String(new Base64().encode(input.getBytes())); + } + }; + + private String description; + + ExtendedStringOperation(String description) { + this.description = description; + } + + + @Override + public String getDescription() { + return description; + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/ImmutableOperation.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/ImmutableOperation.java new file mode 100644 index 0000000000..66f26a4806 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/ImmutableOperation.java @@ -0,0 +1,6 @@ +package com.baeldung.enums.extendenum; + +public enum ImmutableOperation { + REMOVE_WHITESPACES, TO_LOWER, INVERT_CASE +} + diff --git a/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/Operator.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/Operator.java new file mode 100644 index 0000000000..a65fea4f92 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/Operator.java @@ -0,0 +1,5 @@ +package com.baeldung.enums.extendenum; + +public interface Operator { + String apply(String input); +} diff --git a/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/StringOperation.java b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/StringOperation.java new file mode 100644 index 0000000000..faf4f38274 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-types/src/main/java/com/baeldung/enums/extendenum/StringOperation.java @@ -0,0 +1,7 @@ +package com.baeldung.enums.extendenum; + +public interface StringOperation { + String getDescription(); + + String apply(String input); +} diff --git a/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/extendenum/ExtendEnumUnitTest.java b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/extendenum/ExtendEnumUnitTest.java new file mode 100644 index 0000000000..0b5ed1e826 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-types/src/test/java/com/baeldung/enums/extendenum/ExtendEnumUnitTest.java @@ -0,0 +1,43 @@ +package com.baeldung.enums.extendenum; + +import org.junit.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class ExtendEnumUnitTest { + private Application app = new Application(); + + @Test + public void givenAStringAndOperation_whenApplyOperation_thenGetExpectedResult() { + String input = " hello"; + String expectedToUpper = " HELLO"; + String expectedReverse = "olleh "; + String expectedTrim = "hello"; + String expectedBase64 = "IGhlbGxv"; + String expectedMd5 = "292a5af68d31c10e31ad449bd8f51263"; + assertEquals(expectedTrim, app.applyOperation(BasicStringOperation.TRIM, input)); + assertEquals(expectedToUpper, app.applyOperation(BasicStringOperation.TO_UPPER, input)); + assertEquals(expectedReverse, app.applyOperation(BasicStringOperation.REVERSE, input)); + assertEquals(expectedBase64, app.applyOperation(ExtendedStringOperation.BASE64_ENCODE, input)); + assertEquals(expectedMd5, app.applyOperation(ExtendedStringOperation.MD5_ENCODE, input)); + } + + @Test + public void givenAStringAndImmutableOperation_whenApplyOperation_thenGetExpectedResult() { + String input = " He ll O "; + String expectedToLower = " he ll o "; + String expectedRmWhitespace = "HellO"; + String expectedInvertCase = " hE LL o "; + assertEquals(expectedToLower, app.applyImmutableOperation(ImmutableOperation.TO_LOWER, input)); + assertEquals(expectedRmWhitespace, app.applyImmutableOperation(ImmutableOperation.REMOVE_WHITESPACES, input)); + assertEquals(expectedInvertCase, app.applyImmutableOperation(ImmutableOperation.INVERT_CASE, input)); + } + + @Test + public void givenUnmappedImmutableOperationValue_whenAppStarts_thenGetException() { + Throwable throwable = assertThrows(ExceptionInInitializerError.class, () -> { + ApplicationWithEx appEx = new ApplicationWithEx(); + }); + assertTrue(throwable.getCause() instanceof IllegalStateException); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-lang/src/main/java/com/baeldung/finalize/CrashedFinalizable.java b/core-java-modules/core-java-lang/src/main/java/com/baeldung/finalize/CrashedFinalizable.java new file mode 100644 index 0000000000..d5ee27591b --- /dev/null +++ b/core-java-modules/core-java-lang/src/main/java/com/baeldung/finalize/CrashedFinalizable.java @@ -0,0 +1,28 @@ +package com.baeldung.finalize; + +import java.lang.ref.ReferenceQueue; +import java.lang.reflect.Field; + +public class CrashedFinalizable { + public static void main(String[] args) throws ReflectiveOperationException { + for (int i = 0; ; i++) { + new CrashedFinalizable(); + if ((i % 1_000_000) == 0) { + Class finalizerClass = Class.forName("java.lang.ref.Finalizer"); + Field queueStaticField = finalizerClass.getDeclaredField("queue"); + queueStaticField.setAccessible(true); + ReferenceQueue referenceQueue = (ReferenceQueue) queueStaticField.get(null); + + Field queueLengthField = ReferenceQueue.class.getDeclaredField("queueLength"); + queueLengthField.setAccessible(true); + long queueLength = (long) queueLengthField.get(referenceQueue); + System.out.format("There are %d references in the queue%n", queueLength); + } + } + } + + @Override + protected void finalize() { + System.out.print(""); + } +} diff --git a/core-java-modules/core-java-networking-2/README.md b/core-java-modules/core-java-networking-2/README.md index fa49c35bf8..9def4c8eb6 100644 --- a/core-java-modules/core-java-networking-2/README.md +++ b/core-java-modules/core-java-networking-2/README.md @@ -14,4 +14,5 @@ This module contains articles about networking in Java - [Handling java.net.ConnectException](https://www.baeldung.com/java-net-connectexception) - [Getting MAC addresses in Java](https://www.baeldung.com/java-mac-address) - [Sending Emails with Attachments in Java](https://www.baeldung.com/java-send-emails-attachments) +- [Finding a Free Port in Java](https://www.baeldung.com/java-free-port) - [[<-- Prev]](/core-java-modules/core-java-networking) diff --git a/core-java-modules/core-java-networking-3/README.md b/core-java-modules/core-java-networking-3/README.md new file mode 100644 index 0000000000..a81e85751d --- /dev/null +++ b/core-java-modules/core-java-networking-3/README.md @@ -0,0 +1,8 @@ +## Core Java Networking (Part 3) + +This module contains articles about networking in Java + +### Relevant Articles + +- TODO: add link once live +- [[<-- Prev]](/core-java-modules/core-java-networking-2) diff --git a/core-java-modules/core-java-networking-3/pom.xml b/core-java-modules/core-java-networking-3/pom.xml new file mode 100644 index 0000000000..d72981f862 --- /dev/null +++ b/core-java-modules/core-java-networking-3/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + core-java-networking-3 + core-java-networking-3 + jar + + + com.baeldung.core-java-modules + core-java-modules + 0.0.1-SNAPSHOT + ../pom.xml + + + + + org.springframework + spring-core + ${spring.core.version} + + + org.eclipse.jetty + jetty-server + ${jetty.embeded.version} + + + org.apache.tomcat.embed + tomcat-embed-core + ${tomcat.embeded.version} + + + org.assertj + assertj-core + ${assertj.version} + test + + + + + core-java-networking-3 + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + + 5.2.8.RELEASE + 9.4.31.v20200723 + 10.0.0-M7 + 3.11.1 + + + diff --git a/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/socket/FindFreePortUnitTest.java b/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/socket/FindFreePortUnitTest.java new file mode 100644 index 0000000000..95530ef292 --- /dev/null +++ b/core-java-modules/core-java-networking-3/src/test/java/com/baeldung/socket/FindFreePortUnitTest.java @@ -0,0 +1,150 @@ +package com.baeldung.socket; + +import org.apache.catalina.LifecycleException; +import org.apache.catalina.startup.Tomcat; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.util.SocketUtils; + +import java.io.IOException; +import java.net.ServerSocket; + +import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; + +public class FindFreePortUnitTest { + + private static int FREE_PORT_NUMBER; + private static int[] FREE_PORT_RANGE; + + @BeforeAll + public static void getExplicitFreePortNumberAndRange() { + try (ServerSocket serverSocket = new ServerSocket(0)) { + FREE_PORT_NUMBER = serverSocket.getLocalPort(); + FREE_PORT_RANGE = new int[] {FREE_PORT_NUMBER, FREE_PORT_NUMBER + 1, FREE_PORT_NUMBER + 2}; + } catch (IOException e) { + fail("No free port is available"); + } + } + + @Test + public void givenExplicitFreePort_whenCreatingServerSocket_thenThatPortIsAssigned() { + try (ServerSocket serverSocket = new ServerSocket(FREE_PORT_NUMBER)) { + assertThat(serverSocket).isNotNull(); + assertThat(serverSocket.getLocalPort()).isEqualTo(FREE_PORT_NUMBER); + } catch (IOException e) { + fail("Port is not available"); + } + } + + @Test + public void givenExplicitOccupiedPort_whenCreatingServerSocket_thenExceptionIsThrown() { + try (ServerSocket serverSocket = new ServerSocket(FREE_PORT_NUMBER)) { + new ServerSocket(FREE_PORT_NUMBER); + fail("Same port cannot be used twice"); + } catch (IOException e) { + assertThat(e).hasMessageContaining("Address already in use"); + } + } + + @Test + public void givenExplicitPortRange_whenCreatingServerSocket_thenOnePortIsAssigned() { + for (int port : FREE_PORT_RANGE) { + try (ServerSocket serverSocket = new ServerSocket(port)) { + assertThat(serverSocket).isNotNull(); + assertThat(serverSocket.getLocalPort()).isEqualTo(port); + return; + } catch (IOException e) { + assertThat(e).hasMessageContaining("Address already in use"); + } + } + fail("No free port in the range found"); + } + + @Test + public void givenPortZero_whenCreatingServerSocket_thenFreePortIsAssigned() { + try (ServerSocket serverSocket = new ServerSocket(0)) { + assertThat(serverSocket).isNotNull(); + assertThat(serverSocket.getLocalPort()).isGreaterThan(0); + } catch (IOException e) { + fail("Port is not available"); + } + } + + @Test + public void givenAvailableTcpPort_whenCreatingServerSocket_thenThatPortIsAssigned() { + int port = SocketUtils.findAvailableTcpPort(); + try (ServerSocket serverSocket = new ServerSocket(port)) { + assertThat(serverSocket).isNotNull(); + assertThat(serverSocket.getLocalPort()).isEqualTo(port); + } catch (IOException e) { + fail("Port is not available"); + } + } + + @Test + public void givenNoPortDefined_whenCreatingJettyServer_thenFreePortIsAssigned() throws Exception { + Server jettyServer = new Server(); + ServerConnector serverConnector = new ServerConnector(jettyServer); + jettyServer.addConnector(serverConnector); + try { + jettyServer.start(); + assertThat(serverConnector.getLocalPort()).isGreaterThan(0); + } catch (Exception e) { + fail("Failed to start Jetty server"); + } finally { + jettyServer.stop(); + jettyServer.destroy(); + } + } + + @Test + public void givenExplicitFreePort_whenCreatingJettyServer_thenThatPortIsAssigned() throws Exception { + Server jettyServer = new Server(); + ServerConnector serverConnector = new ServerConnector(jettyServer); + serverConnector.setPort(FREE_PORT_NUMBER); + jettyServer.addConnector(serverConnector); + try { + jettyServer.start(); + assertThat(serverConnector.getLocalPort()).isEqualTo(FREE_PORT_NUMBER); + } catch (Exception e) { + fail("Failed to start Jetty server"); + } finally { + jettyServer.stop(); + jettyServer.destroy(); + } + } + + @Test + public void givenPortZero_whenCreatingTomcatServer_thenFreePortIsAssigned() throws Exception { + Tomcat tomcatServer = new Tomcat(); + tomcatServer.setPort(0); + try { + tomcatServer.start(); + assertThat(tomcatServer.getConnector().getLocalPort()).isGreaterThan(0); + } catch (LifecycleException e) { + fail("Failed to start Tomcat server"); + } finally { + tomcatServer.stop(); + tomcatServer.destroy(); + } + } + + @Test + public void givenExplicitFreePort_whenCreatingTomcatServer_thenThatPortIsAssigned() throws Exception { + Tomcat tomcatServer = new Tomcat(); + tomcatServer.setPort(FREE_PORT_NUMBER); + try { + tomcatServer.start(); + assertThat(tomcatServer.getConnector().getLocalPort()).isEqualTo(FREE_PORT_NUMBER); + } catch (LifecycleException e) { + fail("Failed to start Tomcat server"); + } finally { + tomcatServer.stop(); + tomcatServer.destroy(); + } + } + +} diff --git a/core-java-modules/core-java-os/src/main/java/com/baeldung/java9/process/OutputStreamExample.java b/core-java-modules/core-java-os/src/main/java/com/baeldung/java9/process/OutputStreamExample.java index 37378f9d6c..fc6d907bfd 100644 --- a/core-java-modules/core-java-os/src/main/java/com/baeldung/java9/process/OutputStreamExample.java +++ b/core-java-modules/core-java-os/src/main/java/com/baeldung/java9/process/OutputStreamExample.java @@ -6,8 +6,7 @@ import java.util.logging.Logger; public class OutputStreamExample { public static void main(String[] args) { - Logger log = Logger.getLogger(OutputStreamExample.class.getName()); - log.log(Level.INFO, Integer.toString(sum(1,2))); + System.out.println(sum(1,2)); } public static int sum(int a, int b) { diff --git a/core-java-modules/core-java-os/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsUnitTest.java b/core-java-modules/core-java-os/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsUnitTest.java index 8cefceef1d..a7a23fb6fc 100644 --- a/core-java-modules/core-java-os/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsUnitTest.java +++ b/core-java-modules/core-java-os/src/test/java/com/baeldung/java9/process/ProcessAPIEnhancementsUnitTest.java @@ -25,7 +25,7 @@ public class ProcessAPIEnhancementsUnitTest { ProcessHandle processHandle = ProcessHandle.current(); ProcessHandle.Info processInfo = processHandle.info(); assertNotNull(processHandle.pid()); - assertEquals(false, processInfo.arguments() + assertEquals(true, processInfo.arguments() .isPresent()); assertEquals(true, processInfo.command() .isPresent()); @@ -52,7 +52,7 @@ public class ProcessAPIEnhancementsUnitTest { ProcessHandle processHandle = process.toHandle(); ProcessHandle.Info processInfo = processHandle.info(); assertNotNull(processHandle.pid()); - assertEquals(false, processInfo.arguments() + assertEquals(true, processInfo.arguments() .isPresent()); assertEquals(true, processInfo.command() .isPresent()); @@ -61,7 +61,7 @@ public class ProcessAPIEnhancementsUnitTest { .contains("java")); assertEquals(true, processInfo.startInstant() .isPresent()); - assertEquals(true, processInfo.totalCpuDuration() + assertEquals(false, processInfo.totalCpuDuration() .isPresent()); assertEquals(true, processInfo.user() .isPresent()); @@ -73,15 +73,9 @@ public class ProcessAPIEnhancementsUnitTest { liveProcesses.filter(ProcessHandle::isAlive) .forEach(ph -> { assertNotNull(ph.pid()); - assertEquals(true, ph.info() - .command() - .isPresent()); assertEquals(true, ph.info() .startInstant() .isPresent()); - assertEquals(true, ph.info() - .totalCpuDuration() - .isPresent()); assertEquals(true, ph.info() .user() .isPresent()); diff --git a/core-java-modules/core-java-os/src/test/java/com/baeldung/java9/process/ProcessUnderstandingUnitTest.java b/core-java-modules/core-java-os/src/test/java/com/baeldung/java9/process/ProcessUnderstandingUnitTest.java index 6ad07c5c3a..69b65852cc 100644 --- a/core-java-modules/core-java-os/src/test/java/com/baeldung/java9/process/ProcessUnderstandingUnitTest.java +++ b/core-java-modules/core-java-os/src/test/java/com/baeldung/java9/process/ProcessUnderstandingUnitTest.java @@ -5,10 +5,10 @@ import static org.junit.Assert.assertTrue; import static org.junit.jupiter.api.Assertions.*; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.lang.String; -import java.util.Optional; import java.util.concurrent.TimeUnit; import java.lang.Integer; @@ -16,28 +16,6 @@ import org.junit.jupiter.api.Test; class ProcessUnderstandingUnitTest { - @Test - public void givenSourceProgram_whenExecutedFromAnotherProgram_thenSourceProgramOutput3() throws IOException { - Process process = Runtime.getRuntime() - .exec("javac -cp src src\\main\\java\\com\\baeldung\\java9\\process\\OutputStreamExample.java"); - process = Runtime.getRuntime() - .exec("java -cp src/main/java com.baeldung.java9.process.OutputStreamExample"); - BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream())); - int value = Integer.parseInt(output.readLine()); - assertEquals(3, value); - } - - @Test - public void givenSourceProgram_whenReadingInputStream_thenFirstLineEquals3() throws IOException { - Process process = Runtime.getRuntime() - .exec("javac -cp src src\\main\\java\\com\\baeldung\\java9\\process\\OutputStreamExample.java"); - process = Runtime.getRuntime() - .exec("java -cp src/main/java com.baeldung.java9.process.OutputStreamExample"); - BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream())); - int value = Integer.parseInt(output.readLine()); - assertEquals(3, value); - } - @Test public void givenSubProcess_whenEncounteringError_thenErrorStreamNotNull() throws IOException { Process process = Runtime.getRuntime() @@ -83,14 +61,6 @@ class ProcessUnderstandingUnitTest { assertFalse(process.isAlive()); } - @Test - public void givenProcessNotCreated_fromWithinJavaApplicationDestroying_thenProcessNotAlive() { - Optional optionalProcessHandle = ProcessHandle.of(5232); - ProcessHandle processHandle = optionalProcessHandle.get(); - processHandle.destroy(); - assertFalse(processHandle.isAlive()); - } - //@Test - windows specific public void givenSubProcess_whenCurrentThreadWaitsIndefinitelyuntilSubProcessEnds_thenProcessWaitForReturnsGrt0() throws IOException, InterruptedException { ProcessBuilder builder = new ProcessBuilder("notepad.exe"); @@ -118,4 +88,21 @@ class ProcessUnderstandingUnitTest { .filter(ph -> (ph.pid() > 10000 && ph.pid() < 50000)) .count()) > 0); } + + @Test + public void givenSourceProgram_whenReadingInputStream_thenFirstLineEquals3() throws IOException { + + Runtime.getRuntime() + .exec("javac -cp src src/main/java/com/baeldung/java9/process/OutputStreamExample.java" + .replace("/", File.separator)); + + Process process = Runtime.getRuntime() + .exec("java -cp src/main/java com.baeldung.java9.process.OutputStreamExample" + .replace("/", File.separator)); + + BufferedReader output = new BufferedReader(new InputStreamReader(process.getInputStream())); + int value = Integer.parseInt(output.readLine()); + + assertEquals(3, value); + } } diff --git a/core-java-modules/core-java-os/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java b/core-java-modules/core-java-os/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java index 8fc5f9f160..d35cf6a665 100644 --- a/core-java-modules/core-java-os/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java +++ b/core-java-modules/core-java-os/src/test/java/com/baeldung/processbuilder/ProcessBuilderUnitTest.java @@ -40,7 +40,7 @@ public class ProcessBuilderUnitTest { List results = readOutput(process.getInputStream()); assertThat("Results should not be empty", results, is(not(empty()))); - assertThat("Results should contain java version: ", results, hasItem(containsString("java version"))); + assertThat("Results should contain java version: ", results, hasItem(containsString("version"))); int exitCode = process.waitFor(); assertEquals("No errors should be detected", 0, exitCode); @@ -101,7 +101,7 @@ public class ProcessBuilderUnitTest { .collect(Collectors.toList()); assertThat("Results should not be empty", lines, is(not(empty()))); - assertThat("Results should contain java version: ", lines, hasItem(containsString("java version"))); + assertThat("Results should contain java version: ", lines, hasItem(containsString("version"))); } @Test @@ -124,7 +124,7 @@ public class ProcessBuilderUnitTest { .collect(Collectors.toList()); assertThat("Results should not be empty", lines, is(not(empty()))); - assertThat("Results should contain java version: ", lines, hasItem(containsString("java version"))); + assertThat("Results should contain java version: ", lines, hasItem(containsString("version"))); } @Test diff --git a/core-java-modules/core-java-os/src/test/java/com/baeldung/screenshot/ScreenshotUnitTest.java b/core-java-modules/core-java-os/src/test/java/com/baeldung/screenshot/ScreenshotUnitTest.java index 6bd0e7dff7..bf271ef2cc 100644 --- a/core-java-modules/core-java-os/src/test/java/com/baeldung/screenshot/ScreenshotUnitTest.java +++ b/core-java-modules/core-java-os/src/test/java/com/baeldung/screenshot/ScreenshotUnitTest.java @@ -1,3 +1,5 @@ +package com.baeldung.screenshot; + import javax.imageio.ImageIO; import java.awt.Component; import java.awt.GraphicsDevice; @@ -7,10 +9,13 @@ import java.awt.Robot; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.io.File; + +import org.junit.Ignore; import org.junit.Test; import static org.junit.Assert.assertTrue; +@Ignore public class ScreenshotUnitTest { @Test @@ -38,6 +43,7 @@ public class ScreenshotUnitTest { assertTrue(imageFile.exists()); } + // This methods needs a component as a parameter and can only be run from an application with a GUI @Test public void givenComponent_whenTakeScreenshot_thenSaveToFile(Component component) throws Exception { Rectangle componentRect = component.getBounds(); diff --git a/core-java-modules/core-java-reflection-2/README.md b/core-java-modules/core-java-reflection-2/README.md index 1668eeade3..9ed14f08dc 100644 --- a/core-java-modules/core-java-reflection-2/README.md +++ b/core-java-modules/core-java-reflection-2/README.md @@ -3,3 +3,4 @@ - [Reading the Value of ‘private’ Fields from a Different Class in Java](https://www.baeldung.com/java-reflection-read-private-field-value) - [Set Field Value With Reflection](https://www.baeldung.com/java-set-private-field-value) - [Checking If a Method is Static Using Reflection in Java](https://www.baeldung.com/java-check-method-is-static) +- [Checking if a Java Class is ‘abstract’ Using Reflection](https://www.baeldung.com/java-reflection-is-class-abstract) diff --git a/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/check/abstractclass/AbstractExample.java b/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/check/abstractclass/AbstractExample.java new file mode 100644 index 0000000000..e8ad3bc3bd --- /dev/null +++ b/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/check/abstractclass/AbstractExample.java @@ -0,0 +1,15 @@ +package com.baeldung.reflection.check.abstractclass; + +import java.time.LocalDate; +import java.time.LocalTime; + +public abstract class AbstractExample { + + public static String getAuthorName() { + return "Umang Budhwar"; + } + + public abstract LocalDate getLocalDate(); + + public abstract LocalTime getLocalTime(); +} diff --git a/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/check/abstractclass/InterfaceExample.java b/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/check/abstractclass/InterfaceExample.java new file mode 100644 index 0000000000..d226611084 --- /dev/null +++ b/core-java-modules/core-java-reflection-2/src/main/java/com/baeldung/reflection/check/abstractclass/InterfaceExample.java @@ -0,0 +1,4 @@ +package com.baeldung.reflection.check.abstractclass; + +public interface InterfaceExample { +} diff --git a/core-java-modules/core-java-reflection-2/src/test/java/com/baeldung/reflection/check/abstractclass/AbstractExampleUnitTest.java b/core-java-modules/core-java-reflection-2/src/test/java/com/baeldung/reflection/check/abstractclass/AbstractExampleUnitTest.java new file mode 100644 index 0000000000..d9a955ca6d --- /dev/null +++ b/core-java-modules/core-java-reflection-2/src/test/java/com/baeldung/reflection/check/abstractclass/AbstractExampleUnitTest.java @@ -0,0 +1,36 @@ +package com.baeldung.reflection.check.abstractclass; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Modifier; +import java.util.Date; + +class AbstractExampleUnitTest { + + @Test + void givenAbstractClass_whenCheckModifierIsAbstract_thenTrue() { + Class clazz = AbstractExample.class; + Assertions.assertTrue(Modifier.isAbstract(clazz.getModifiers())); + } + + @Test + void givenInterface_whenCheckModifierIsAbstract_thenTrue() { + Class clazz = InterfaceExample.class; + Assertions.assertTrue(Modifier.isAbstract(clazz.getModifiers())); + } + + @Test + void givenAbstractClass_whenCheckIsAbstractClass_thenTrue() { + Class clazz = AbstractExample.class; + int mod = clazz.getModifiers(); + Assertions.assertTrue(Modifier.isAbstract(mod) && !Modifier.isInterface(mod)); + } + + @Test + void givenConcreteClass_whenCheckIsAbstractClass_thenFalse() { + Class clazz = Date.class; + int mod = clazz.getModifiers(); + Assertions.assertFalse(Modifier.isAbstract(mod) && !Modifier.isInterface(mod)); + } +} diff --git a/core-java-modules/core-java-regex/README.md b/core-java-modules/core-java-regex/README.md index ad8ba1e4ae..92321fa656 100644 --- a/core-java-modules/core-java-regex/README.md +++ b/core-java-modules/core-java-regex/README.md @@ -9,7 +9,7 @@ - [Guide to Escaping Characters in Java RegExps](http://www.baeldung.com/java-regexp-escape-char) - [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) +- [How to Use Regular Expressions to Replace Tokens in Strings in Java](https://www.baeldung.com/java-regex-token-replacement) - [Regular Expressions \s and \s+ in Java](https://www.baeldung.com/java-regex-s-splus) - [Validate Phone Numbers With Java Regex](https://www.baeldung.com/java-regex-validate-phone-numbers) - [How to Count the Number of Matches for a Regex?](https://www.baeldung.com/java-count-regex-matches) diff --git a/core-java-modules/core-java-security-2/README.md b/core-java-modules/core-java-security-2/README.md index ba8cce46a0..9b99d624c9 100644 --- a/core-java-modules/core-java-security-2/README.md +++ b/core-java-modules/core-java-security-2/README.md @@ -10,4 +10,9 @@ This module contains articles about core Java Security - [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) - [How to Read PEM File to Get Public and Private Keys](https://www.baeldung.com/java-read-pem-file-keys) +- [Listing the Available Cipher Algorithms](https://www.baeldung.com/java-list-cipher-algorithms) +- [Get a List of Trusted Certificates in Java](https://www.baeldung.com/java-list-trusted-certificates) +- [Security Context Basics: User, Subject and Principal](https://www.baeldung.com/security-context-basics) +- [Java AES Encryption and Decryption](https://www.baeldung.com/java-aes-encryption-decryption) +- [InvalidAlgorithmParameterException: Wrong IV Length](https://www.baeldung.com/java-invalidalgorithmparameter-exception) - More articles: [[<-- prev]](/core-java-modules/core-java-security) diff --git a/core-java-modules/core-java-security-2/pom.xml b/core-java-modules/core-java-security-2/pom.xml index 890b4147ca..895509410d 100644 --- a/core-java-modules/core-java-security-2/pom.xml +++ b/core-java-modules/core-java-security-2/pom.xml @@ -53,7 +53,7 @@ 1.11 - 3.10.0 + 3.18.0 2.3.1 diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/aes/AESUtil.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/aes/AESUtil.java new file mode 100644 index 0000000000..2952eef625 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/aes/AESUtil.java @@ -0,0 +1,156 @@ +package com.baeldung.aes; + +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.BadPaddingException; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKeyFactory; +import javax.crypto.SealedObject; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.util.Base64; + +public class AESUtil { + + public static String encrypt(String algorithm, String input, SecretKey key, IvParameterSpec iv) + throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, + InvalidKeyException, BadPaddingException, IllegalBlockSizeException { + Cipher cipher = Cipher.getInstance(algorithm); + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + byte[] cipherText = cipher.doFinal(input.getBytes()); + return Base64.getEncoder() + .encodeToString(cipherText); + } + + public static String decrypt(String algorithm, String cipherText, SecretKey key, IvParameterSpec iv) + throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, + InvalidKeyException, BadPaddingException, IllegalBlockSizeException { + Cipher cipher = Cipher.getInstance(algorithm); + cipher.init(Cipher.DECRYPT_MODE, key, iv); + byte[] plainText = cipher.doFinal(Base64.getDecoder() + .decode(cipherText)); + return new String(plainText); + } + + public static SecretKey generateKey(int n) throws NoSuchAlgorithmException { + KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); + keyGenerator.init(n); + SecretKey key = keyGenerator.generateKey(); + return key; + } + + public static SecretKey getKeyFromPassword(String password, String salt) + throws NoSuchAlgorithmException, InvalidKeySpecException { + SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256"); + KeySpec spec = new PBEKeySpec(password.toCharArray(), salt.getBytes(), 65536, 256); + SecretKey secret = new SecretKeySpec(factory.generateSecret(spec) + .getEncoded(), "AES"); + return secret; + } + + public static IvParameterSpec generateIv() { + byte[] iv = new byte[16]; + new SecureRandom().nextBytes(iv); + return new IvParameterSpec(iv); + } + + public static void encryptFile(String algorithm, SecretKey key, IvParameterSpec iv, + File inputFile, File outputFile) throws IOException, NoSuchPaddingException, + NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, + BadPaddingException, IllegalBlockSizeException { + Cipher cipher = Cipher.getInstance(algorithm); + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + FileInputStream inputStream = new FileInputStream(inputFile); + FileOutputStream outputStream = new FileOutputStream(outputFile); + byte[] buffer = new byte[64]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + byte[] output = cipher.update(buffer, 0, bytesRead); + if (output != null) { + outputStream.write(output); + } + } + byte[] outputBytes = cipher.doFinal(); + if (outputBytes != null) { + outputStream.write(outputBytes); + } + inputStream.close(); + outputStream.close(); + } + + public static void decryptFile(String algorithm, SecretKey key, IvParameterSpec iv, + File encryptedFile, File decryptedFile) throws IOException, NoSuchPaddingException, + NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException, + BadPaddingException, IllegalBlockSizeException { + Cipher cipher = Cipher.getInstance(algorithm); + cipher.init(Cipher.DECRYPT_MODE, key, iv); + FileInputStream inputStream = new FileInputStream(encryptedFile); + FileOutputStream outputStream = new FileOutputStream(decryptedFile); + byte[] buffer = new byte[64]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + byte[] output = cipher.update(buffer, 0, bytesRead); + if (output != null) { + outputStream.write(output); + } + } + byte[] output = cipher.doFinal(); + if (output != null) { + outputStream.write(output); + } + inputStream.close(); + outputStream.close(); + } + + public static SealedObject encryptObject(String algorithm, Serializable object, SecretKey key, + IvParameterSpec iv) throws NoSuchPaddingException, NoSuchAlgorithmException, + InvalidAlgorithmParameterException, InvalidKeyException, IOException, IllegalBlockSizeException { + Cipher cipher = Cipher.getInstance(algorithm); + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + SealedObject sealedObject = new SealedObject(object, cipher); + return sealedObject; + } + + public static Serializable decryptObject(String algorithm, SealedObject sealedObject, SecretKey key, + IvParameterSpec iv) throws NoSuchPaddingException, NoSuchAlgorithmException, + InvalidAlgorithmParameterException, InvalidKeyException, ClassNotFoundException, + BadPaddingException, IllegalBlockSizeException, IOException { + Cipher cipher = Cipher.getInstance(algorithm); + cipher.init(Cipher.DECRYPT_MODE, key, iv); + Serializable unsealObject = (Serializable) sealedObject.getObject(cipher); + return unsealObject; + } + + public static String encryptPasswordBased(String plainText, SecretKey key, IvParameterSpec iv) + throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, + InvalidKeyException, BadPaddingException, IllegalBlockSizeException { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.ENCRYPT_MODE, key, iv); + return Base64.getEncoder() + .encodeToString(cipher.doFinal(plainText.getBytes())); + } + + public static String decryptPasswordBased(String cipherText, SecretKey key, IvParameterSpec iv) + throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidAlgorithmParameterException, + InvalidKeyException, BadPaddingException, IllegalBlockSizeException { + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING"); + cipher.init(Cipher.DECRYPT_MODE, key, iv); + return new String(cipher.doFinal(Base64.getDecoder() + .decode(cipherText))); + } + +} diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/aes/Student.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/aes/Student.java new file mode 100644 index 0000000000..13cd1c5e9d --- /dev/null +++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/aes/Student.java @@ -0,0 +1,40 @@ +package com.baeldung.aes; + +import java.io.Serializable; +import java.util.Objects; + +public class Student implements Serializable { + private String name; + private int age; + + public Student(String name, int age) { + this.name = name; + this.age = age; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + Student student = (Student) o; + return age == student.age && Objects.equals(name, student.name); + } +} diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/egd/JavaSecurityEgdTester.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/egd/JavaSecurityEgdTester.java new file mode 100644 index 0000000000..347d3b4cba --- /dev/null +++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/egd/JavaSecurityEgdTester.java @@ -0,0 +1,23 @@ +package com.baeldung.egd; + +import java.security.SecureRandom; + +/** + * JavaSecurityEgdTester - run this with JVM parameter java.security.egd, e.g.: + * java -Djava.security.egd=file:/dev/urandom -cp . com.baeldung.egd.JavaSecurityEgdTester + */ +public class JavaSecurityEgdTester { + public static final double NANOSECS = 1000000000.0; + public static final String JAVA_SECURITY_EGD = "java.security.egd"; + + public static void main(String[] args) { + SecureRandom secureRandom = new SecureRandom(); + long start = System.nanoTime(); + byte[] randomBytes = new byte[256]; + secureRandom.nextBytes(randomBytes); + double duration = (System.nanoTime() - start) / NANOSECS; + + String message = String.format("java.security.egd=%s took %.3f seconds and used the %s algorithm", System.getProperty(JAVA_SECURITY_EGD), duration, secureRandom.getAlgorithm()); + System.out.println(message); + } +} diff --git a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java index 0f28408083..699e9141a4 100644 --- a/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java +++ b/core-java-modules/core-java-security-2/src/main/java/com/baeldung/hashing/SHACommonUtils.java @@ -3,7 +3,7 @@ package com.baeldung.hashing; class SHACommonUtils { public static String bytesToHex(byte[] hash) { - StringBuffer hexString = new StringBuffer(); + StringBuilder hexString = new StringBuilder(2 * hash.length); for (byte h : hash) { String hex = Integer.toHexString(0xff & h); if (hex.length() == 1) diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/aes/AESUtilUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/aes/AESUtilUnitTest.java new file mode 100644 index 0000000000..531c20ca79 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/aes/AESUtilUnitTest.java @@ -0,0 +1,101 @@ +package com.baeldung.aes; + +import org.assertj.core.api.WithAssertions; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import javax.crypto.SealedObject; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.io.File; +import java.io.IOException; +import java.nio.file.Paths; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.spec.InvalidKeySpecException; + +class AESUtilUnitTest implements WithAssertions { + + @Test + void givenString_whenEncrypt_thenSuccess() + throws NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, + BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException { + // given + String input = "baeldung"; + SecretKey key = AESUtil.generateKey(128); + IvParameterSpec ivParameterSpec = AESUtil.generateIv(); + String algorithm = "AES/CBC/PKCS5Padding"; + + // when + String cipherText = AESUtil.encrypt(algorithm, input, key, ivParameterSpec); + String plainText = AESUtil.decrypt(algorithm, cipherText, key, ivParameterSpec); + + // then + Assertions.assertEquals(input, plainText); + } + + @Test + void givenFile_whenEncrypt_thenSuccess() + throws NoSuchAlgorithmException, IOException, IllegalBlockSizeException, InvalidKeyException, + BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException { + // given + SecretKey key = AESUtil.generateKey(128); + String algorithm = "AES/CBC/PKCS5Padding"; + IvParameterSpec ivParameterSpec = AESUtil.generateIv(); + File inputFile = Paths.get("src/test/resources/baeldung.txt") + .toFile(); + File encryptedFile = new File("classpath:baeldung.encrypted"); + File decryptedFile = new File("document.decrypted"); + + // when + AESUtil.encryptFile(algorithm, key, ivParameterSpec, inputFile, encryptedFile); + AESUtil.decryptFile(algorithm, key, ivParameterSpec, encryptedFile, decryptedFile); + + // then + assertThat(inputFile).hasSameTextualContentAs(decryptedFile); + encryptedFile.delete(); + decryptedFile.delete(); + } + + @Test + void givenObject_whenEncrypt_thenSuccess() + throws NoSuchAlgorithmException, IllegalBlockSizeException, InvalidKeyException, + InvalidAlgorithmParameterException, NoSuchPaddingException, IOException, BadPaddingException, + ClassNotFoundException { + // given + Student student = new Student("Baeldung", 20); + SecretKey key = AESUtil.generateKey(128); + IvParameterSpec ivParameterSpec = AESUtil.generateIv(); + String algorithm = "AES/CBC/PKCS5Padding"; + + // when + SealedObject sealedObject = AESUtil.encryptObject(algorithm, student, key, ivParameterSpec); + Student object = (Student) AESUtil.decryptObject(algorithm, sealedObject, key, ivParameterSpec); + + // then + assertThat(student).isEqualTo(object); + } + + @Test + void givenPassword_whenEncrypt_thenSuccess() + throws InvalidKeySpecException, NoSuchAlgorithmException, IllegalBlockSizeException, + InvalidKeyException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchPaddingException { + // given + String plainText = "www.baeldung.com"; + String password = "baeldung"; + String salt = "12345678"; + IvParameterSpec ivParameterSpec = AESUtil.generateIv(); + SecretKey key = AESUtil.getKeyFromPassword(password, salt); + + // when + String cipherText = AESUtil.encryptPasswordBased(plainText, key, ivParameterSpec); + String decryptedCipherText = AESUtil.decryptPasswordBased(cipherText, key, ivParameterSpec); + + // then + Assertions.assertEquals(plainText, decryptedCipherText); + } +} diff --git a/core-java-modules/core-java-security-2/src/test/java/com/baeldung/trustedcert/CertificatesUnitTest.java b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/trustedcert/CertificatesUnitTest.java new file mode 100644 index 0000000000..4f40c3c195 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/test/java/com/baeldung/trustedcert/CertificatesUnitTest.java @@ -0,0 +1,94 @@ +package com.baeldung.trustedcert; + +import org.junit.jupiter.api.Test; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.PKIXParameters; +import java.security.cert.TrustAnchor; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class CertificatesUnitTest { + + private static final String GODADDY_CA_ALIAS = "godaddyrootg2ca [jdk]"; + + @Test + public void whenLoadingCacertsKeyStore_thenCertificatesArePresent() throws Exception { + KeyStore keyStore = loadKeyStore(); + PKIXParameters params = new PKIXParameters(keyStore); + + Set trustAnchors = params.getTrustAnchors(); + List certificates = trustAnchors.stream() + .map(TrustAnchor::getTrustedCert) + .collect(Collectors.toList()); + + assertFalse(certificates.isEmpty()); + } + + @Test + public void whenLoadingDefaultKeyStore_thenCertificatesArePresent() throws Exception { + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init((KeyStore)null); + + List trustManagers = Arrays.asList(trustManagerFactory.getTrustManagers()); + List certificates = trustManagers.stream() + .filter(X509TrustManager.class::isInstance) + .map(X509TrustManager.class::cast) + .map(trustManager -> Arrays.asList(trustManager.getAcceptedIssuers())) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + + assertFalse(certificates.isEmpty()); + } + + @Test + public void whenLoadingKeyStore_thenGoDaddyCALabelIsPresent() throws Exception { + KeyStore keyStore = loadKeyStore(); + + Enumeration aliasEnumeration = keyStore.aliases(); + List aliases = Collections.list(aliasEnumeration); + + assertTrue(aliases.contains(GODADDY_CA_ALIAS)); + } + + @Test + public void whenLoadingKeyStore_thenGoDaddyCertificateIsPresent() throws Exception { + KeyStore keyStore = loadKeyStore(); + + Certificate goDaddyCertificate = keyStore.getCertificate(GODADDY_CA_ALIAS); + + assertNotNull(goDaddyCertificate); + } + + private KeyStore loadKeyStore() throws CertificateException, NoSuchAlgorithmException, IOException, KeyStoreException { + String relativeCacertsPath = "/lib/security/cacerts".replace("/", File.separator); + String filename = System.getProperty("java.home") + relativeCacertsPath; + FileInputStream is = new FileInputStream(filename); + + KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); + String password = "changeit"; + keystore.load(is, password.toCharArray()); + + return keystore; + } +} diff --git a/core-java-modules/core-java-security-2/src/test/resources/baeldung.txt b/core-java-modules/core-java-security-2/src/test/resources/baeldung.txt new file mode 100644 index 0000000000..dc6988d2f9 --- /dev/null +++ b/core-java-modules/core-java-security-2/src/test/resources/baeldung.txt @@ -0,0 +1,2 @@ +Hello Baeldung +This is AES file encryption sample \ No newline at end of file diff --git a/core-java-modules/core-java-string-algorithms-2/README.md b/core-java-modules/core-java-string-algorithms-2/README.md index 94ace77d66..dbfbb3ef3c 100644 --- a/core-java-modules/core-java-string-algorithms-2/README.md +++ b/core-java-modules/core-java-string-algorithms-2/README.md @@ -11,6 +11,6 @@ This module contains articles about string-related algorithms. - [Join Array of Primitives with Separator in Java](https://www.baeldung.com/java-join-primitive-array) - [Pad a String with Zeros or Spaces in Java](https://www.baeldung.com/java-pad-string) - [Remove Leading and Trailing Characters from a String](https://www.baeldung.com/java-remove-trailing-characters) -- [Counting Words in a String](https://www.baeldung.com/java-word-counting) +- [Counting Words in a String with Java](https://www.baeldung.com/java-word-counting) - [Finding the Difference Between Two Strings in Java](https://www.baeldung.com/java-difference-between-two-strings) - More articles: [[<-- prev]](../core-java-string-algorithms) diff --git a/core-java-modules/core-java-string-algorithms-2/pom.xml b/core-java-modules/core-java-string-algorithms-2/pom.xml index a635cd8022..2a84cebb4c 100644 --- a/core-java-modules/core-java-string-algorithms-2/pom.xml +++ b/core-java-modules/core-java-string-algorithms-2/pom.xml @@ -61,7 +61,6 @@ - 3.8.1 3.6.1 1.2 diff --git a/core-java-modules/core-java-string-algorithms-3/pom.xml b/core-java-modules/core-java-string-algorithms-3/pom.xml index 2725ba84c6..610956588e 100644 --- a/core-java-modules/core-java-string-algorithms-3/pom.xml +++ b/core-java-modules/core-java-string-algorithms-3/pom.xml @@ -59,7 +59,6 @@ - 3.8.1 3.6.1 28.1-jre diff --git a/core-java-modules/core-java-string-algorithms/README.md b/core-java-modules/core-java-string-algorithms/README.md index 70a4b5ffaf..c3eafda23d 100644 --- a/core-java-modules/core-java-string-algorithms/README.md +++ b/core-java-modules/core-java-string-algorithms/README.md @@ -3,14 +3,14 @@ This module contains articles about string-related algorithms. ### Relevant Articles: -- [Check If a String Is a Palindrome](https://www.baeldung.com/java-palindrome) +- [Check if a String is a Palindrome in Java](https://www.baeldung.com/java-palindrome) - [Count Occurrences of a Char in a String](https://www.baeldung.com/java-count-chars) - [Using indexOf to Find All Occurrences of a Word in a String](https://www.baeldung.com/java-indexOf-find-string-occurrences) - [Removing Stopwords from a String in Java](https://www.baeldung.com/java-string-remove-stopwords) - [Removing Repeated Characters from a String](https://www.baeldung.com/java-remove-repeated-char) - [How to Reverse a String in Java](https://www.baeldung.com/java-reverse-string) - [Check If a String Is a Pangram in Java](https://www.baeldung.com/java-string-pangram) -- [Check If a String Contains Multiple Keywords](https://www.baeldung.com/string-contains-multiple-words) +- [Check If a String Contains Multiple Keywords in Java](https://www.baeldung.com/string-contains-multiple-words) - [Checking If a String Is a Repeated Substring](https://www.baeldung.com/java-repeated-substring) - [Remove Emojis from a Java String](https://www.baeldung.com/java-string-remove-emojis) - More articles: [[next -->]](../core-java-string-algorithms-2) diff --git a/core-java-modules/core-java-string-algorithms/pom.xml b/core-java-modules/core-java-string-algorithms/pom.xml index 85879d74e2..6ba9ae7bb3 100644 --- a/core-java-modules/core-java-string-algorithms/pom.xml +++ b/core-java-modules/core-java-string-algorithms/pom.xml @@ -65,7 +65,6 @@ - 3.8.1 27.0.1-jre 0.4.0 3.6.1 diff --git a/core-java-modules/core-java-string-apis/README.md b/core-java-modules/core-java-string-apis/README.md index fc36ba8640..c9aa40de7a 100644 --- a/core-java-modules/core-java-string-apis/README.md +++ b/core-java-modules/core-java-string-apis/README.md @@ -8,5 +8,5 @@ This module contains articles about string APIs. - [Guide to java.util.Formatter](https://www.baeldung.com/java-string-formatter) - [Guide to StreamTokenizer](https://www.baeldung.com/java-streamtokenizer) - [CharSequence vs. String in Java](https://www.baeldung.com/java-char-sequence-string) -- [StringBuilder and StringBuffer in Java](https://www.baeldung.com/java-string-builder-string-buffer) +- [StringBuilder vs StringBuffer in Java](https://www.baeldung.com/java-string-builder-string-buffer) - [Generate a Secure Random Password in Java](https://www.baeldung.com/java-generate-secure-password) diff --git a/core-java-modules/core-java-string-operations-2/pom.xml b/core-java-modules/core-java-string-operations-2/pom.xml index db32bf97a1..5865d9a776 100644 --- a/core-java-modules/core-java-string-operations-2/pom.xml +++ b/core-java-modules/core-java-string-operations-2/pom.xml @@ -112,7 +112,6 @@ 3.6.1 2.0.0.Final - 3.8.1 28.2-jre 6.0.2.Final 3.0.0 diff --git a/core-java-modules/core-java-string-operations-3/README.md b/core-java-modules/core-java-string-operations-3/README.md index 4e46849c11..7f391ee056 100644 --- a/core-java-modules/core-java-string-operations-3/README.md +++ b/core-java-modules/core-java-string-operations-3/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Version Comparison in Java](https://www.baeldung.com/java-comparing-versions) +- [Java (String) or .toString()?](https://www.baeldung.com/java-string-casting-vs-tostring) diff --git a/core-java-modules/core-java-string-operations-3/src/main/java/com/baeldung/tostring/StringCastUtils.java b/core-java-modules/core-java-string-operations-3/src/main/java/com/baeldung/tostring/StringCastUtils.java new file mode 100644 index 0000000000..e96c87dfe4 --- /dev/null +++ b/core-java-modules/core-java-string-operations-3/src/main/java/com/baeldung/tostring/StringCastUtils.java @@ -0,0 +1,17 @@ +package com.baeldung.tostring; + +public class StringCastUtils { + public static String castToString(Object object) { + if (object instanceof String) { + return (String) object; + } + return null; + } + + public static String getStringRepresentation(Object object) { + if (object != null) { + return object.toString(); + } + return null; + } +} diff --git a/core-java-modules/core-java-string-operations-3/src/test/java/com/baeldung/tostring/ToStringUnitTest.java b/core-java-modules/core-java-string-operations-3/src/test/java/com/baeldung/tostring/ToStringUnitTest.java new file mode 100644 index 0000000000..51a27e1b5c --- /dev/null +++ b/core-java-modules/core-java-string-operations-3/src/test/java/com/baeldung/tostring/ToStringUnitTest.java @@ -0,0 +1,104 @@ +package com.baeldung.tostring; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; + +public class ToStringUnitTest { + @Test + public void givenString_whenCastToObjectAndString_thenSameAndNoException() { + String input = "baeldung"; + + Object obj = input; + String str = (String) obj; + + assertEquals(obj, str); + assertEquals(str, input); + assertSame(input, str); + } + + @Test(expected = ClassCastException.class) + public void givenIntegerObject_whenCastToObjectAndString_thenCastClassException() { + Integer input = 1234; + + Object obj = input; + String str = (String) obj; + } + + @Test + public void givenNullInteger_whenCastToObjectAndString_thenSameAndNoException() { + Integer input = null; + + Object obj = input; + String str = (String) obj; + + assertEquals(obj, str); + assertEquals(str, input); + assertSame(input, str); + } + + @Test(expected = NullPointerException.class) + public void givenNullInteger_whenToString_thenNullPointerException() { + Integer input = null; + + String str = input.toString(); + } + + @Test + public void givenInteger_whenCastToObject_thenToStringEquals() { + Integer input = 1234; + + Object obj = input; + + assertEquals("1234", input.toString()); + assertEquals("1234", obj.toString()); + assertEquals(input.toString(), obj.toString()); + } + + @Test + public void givenString_whenToString_thenSame() { + String str = "baeldung"; + + assertEquals("baeldung", str.toString()); + assertSame(str, str.toString()); + } + + @Test + public void givenString_whenCastToObject_thenCastToStringReturnsSame() { + String input = "baeldung"; + + Object obj = input; + + assertSame(input, StringCastUtils.castToString(obj)); + } + + @Test + public void givenInteger_whenCastToObject_thenCastToStringReturnsNull() { + Integer input = 1234; + + Object obj = input; + + assertEquals(null, StringCastUtils.castToString(obj)); + } + + @Test + public void givenIntegerNull_whenCastToObject_thenCastToStringReturnsNull() { + Integer input = null; + + Object obj = input; + + assertEquals(null, StringCastUtils.castToString(obj)); + } + + @Test + public void givenIntegerNotNull_whenCastToObject_thenGetToStringReturnsString() { + Integer input = 1234; + + Object obj = input; + + assertEquals("1234", StringCastUtils.getStringRepresentation(obj)); + assertNotSame("1234", StringCastUtils.getStringRepresentation(obj)); + } +} diff --git a/core-java-modules/core-java-string-operations/pom.xml b/core-java-modules/core-java-string-operations/pom.xml index c5791e929e..9632988392 100644 --- a/core-java-modules/core-java-string-operations/pom.xml +++ b/core-java-modules/core-java-string-operations/pom.xml @@ -60,7 +60,6 @@ - 3.9 3.6.1 1.10 diff --git a/core-java-modules/core-java-time-measurements/pom.xml b/core-java-modules/core-java-time-measurements/pom.xml index 67b8d7179a..3197b1ae6a 100644 --- a/core-java-modules/core-java-time-measurements/pom.xml +++ b/core-java-modules/core-java-time-measurements/pom.xml @@ -92,10 +92,11 @@ 3.6.1 2.10 + 1.18.12 3.6.1 1.8.9 - 2.0.0 + 2.0.7 1.44 2.22.1 diff --git a/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/ElapsedTimeUnitTest.java b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/ElapsedTimeManualTest.java similarity index 84% rename from core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/ElapsedTimeUnitTest.java rename to core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/ElapsedTimeManualTest.java index 1d92684ef4..211222c665 100644 --- a/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/ElapsedTimeUnitTest.java +++ b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/ElapsedTimeManualTest.java @@ -9,7 +9,7 @@ import java.util.concurrent.TimeUnit; import org.apache.commons.lang3.time.StopWatch; import org.junit.Test; -public class ElapsedTimeUnitTest { +public class ElapsedTimeManualTest { @Test public void givenRunningTask_whenMeasuringTimeWithCurrentTimeMillis_thenGetElapsedTime() throws InterruptedException { @@ -50,17 +50,25 @@ public class ElapsedTimeUnitTest { assertEquals(true, (2000L <= timeElapsed) && (timeElapsed <= 3000L)); } - + + /* + The below test depends on the elapsed time, which isn't ideal in a test. + Also, it slows down test execution artificially. + */ @Test public void givenRunningTask_whenMeasuringTimeWithInstantClass_thenGetElapsedTime() throws InterruptedException { Instant start = Instant.now(); - + System.out.println("start: " + start); + simulateRunningTask(); - + Instant finish = Instant.now(); - + + System.out.println("start: " + start); + System.out.println("finish: " + finish); long timeElapsed = Duration.between(start, finish).toMillis(); - + + System.out.println("elapsed: " + timeElapsed); assertEquals(true, (2000L <= timeElapsed) && (timeElapsed <= 3000L)); } diff --git a/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/InstantUnitTest.java b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/InstantUnitTest.java index 8400748710..608199197a 100644 --- a/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/InstantUnitTest.java +++ b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/InstantUnitTest.java @@ -10,8 +10,8 @@ import java.time.Instant; import java.time.ZoneId; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.when; import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.when; @RunWith(PowerMockRunner.class) @PrepareForTest({ Instant.class }) diff --git a/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/LocalDateTimeUnitTest.java b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/LocalDateTimeUnitTest.java index 04c1a0b74e..52dc9ba1c6 100644 --- a/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/LocalDateTimeUnitTest.java +++ b/core-java-modules/core-java-time-measurements/src/test/java/com/baeldung/time/LocalDateTimeUnitTest.java @@ -18,19 +18,6 @@ import static org.powermock.api.mockito.PowerMockito.mockStatic; @PrepareForTest({ LocalDateTime.class }) public class LocalDateTimeUnitTest { - @Test - public void givenLocalDateTimeMock_whenNow_thenGetFixedLocalDateTime() { - Clock clock = Clock.fixed(Instant.parse("2014-12-22T10:15:30.00Z"), ZoneId.of("UTC")); - LocalDateTime dateTime = LocalDateTime.now(clock); - mockStatic(LocalDateTime.class); - when(LocalDateTime.now()).thenReturn(dateTime); - String dateTimeExpected = "2014-12-22T10:15:30"; - - LocalDateTime now = LocalDateTime.now(); - - assertThat(now).isEqualTo(dateTimeExpected); - } - @Test public void givenFixedClock_whenNow_thenGetFixedLocalDateTime() { Clock clock = Clock.fixed(Instant.parse("2014-12-22T10:15:30.00Z"), ZoneId.of("UTC")); diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index a6aecef741..2d342c4216 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -29,10 +29,12 @@ core-java-arrays-convert core-java-arrays-operations-basic core-java-arrays-operations-advanced - + + core-java-char core-java-collections core-java-collections-2 core-java-collections-3 + core-java-collections-4 core-java-collections-array-list core-java-collections-list core-java-collections-list-2 @@ -45,6 +47,7 @@ core-java-concurrency-advanced core-java-concurrency-advanced-2 core-java-concurrency-advanced-3 + core-java-concurrency-advanced-4 core-java-concurrency-basic core-java-concurrency-basic-2 core-java-concurrency-collections @@ -60,10 +63,12 @@ core-java-exceptions-2 core-java-exceptions-3 core-java-function + core-java-functional core-java-io core-java-io-2 core-java-io-3 + core-java-io-4 core-java-io-apis core-java-io-conversions core-java-io-conversions-2 @@ -79,6 +84,7 @@ core-java-lang-3 core-java-lang-math core-java-lang-math-2 + core-java-lang-math-3 core-java-lang-oop-constructors core-java-lang-oop-patterns core-java-lang-oop-generics diff --git a/core-kotlin-modules/core-kotlin-advanced/README.md b/core-kotlin-modules/core-kotlin-advanced/README.md deleted file mode 100644 index 2e99e3b078..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## Core Kotlin Advanced - -This module contains articles about advanced topics in Kotlin. - -### Relevant articles: -- [Building DSLs in Kotlin](https://www.baeldung.com/kotlin-dsl) -- [Regular Expressions in Kotlin](https://www.baeldung.com/kotlin-regular-expressions) -- [Idiomatic Logging in Kotlin](https://www.baeldung.com/kotlin-logging) -- [Mapping of Data Objects in Kotlin](https://www.baeldung.com/kotlin-data-objects) -- [Reflection with Kotlin](https://www.baeldung.com/kotlin-reflection) -- [Kotlin Contracts](https://www.baeldung.com/kotlin-contracts) diff --git a/core-kotlin-modules/core-kotlin-advanced/pom.xml b/core-kotlin-modules/core-kotlin-advanced/pom.xml deleted file mode 100644 index 5ddfef23cc..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - 4.0.0 - core-kotlin-advanced - core-kotlin-advanced - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - - - org.assertj - assertj-core - ${assertj.version} - test - - - org.jetbrains.kotlin - kotlin-test - ${kotlin.version} - test - - - - - 1.3.30 - 3.10.0 - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/contract/CallsInPlaceEffect.kt b/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/contract/CallsInPlaceEffect.kt deleted file mode 100644 index ca0b13cdc7..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/contract/CallsInPlaceEffect.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.baeldung.contract - -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.InvocationKind -import kotlin.contracts.contract - -@ExperimentalContracts -inline fun myRun(block: () -> R): R { - contract { - callsInPlace(block, InvocationKind.EXACTLY_ONCE) - } - return block() -} - -@ExperimentalContracts -fun callsInPlace() { - val i: Int - myRun { - i = 1 // Without contract initialization is forbidden due to possible re-assignment - } - println(i) // Without contract variable might be uninitialized -} - diff --git a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/contract/ReturnsEffect.kt b/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/contract/ReturnsEffect.kt deleted file mode 100644 index 56f667af82..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/contract/ReturnsEffect.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.baeldung.contract - -import kotlin.contracts.ExperimentalContracts -import kotlin.contracts.contract - -data class Request(val arg: String) - -class Service { - - @ExperimentalContracts - fun process(request: Request?) { - validate(request) - println(request.arg) - } - -} - -@ExperimentalContracts -private fun validate(request: Request?) { - contract { - returns() implies (request != null) - } - if (request == null) { - throw IllegalArgumentException("Undefined request") - } -} - -data class MyEvent(val message: String) - -@ExperimentalContracts -fun processEvent(event: Any?) { - if (isInterested(event)) { - println(event.message) // Compiler makes smart cast here with the help of contract - } -} - -@ExperimentalContracts -fun isInterested(event: Any?): Boolean { - contract { - returns(true) implies (event is MyEvent) - } - return event is MyEvent -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/datamapping/User.kt b/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/datamapping/User.kt deleted file mode 100644 index fdbf95f7ba..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/datamapping/User.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.baeldung.datamapping - -data class User( - val firstName: String, - val lastName: String, - val street: String, - val houseNumber: String, - val phone: String, - val age: Int, - val password: String) \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/datamapping/UserExtensions.kt b/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/datamapping/UserExtensions.kt deleted file mode 100644 index 1f3d7f3b47..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/datamapping/UserExtensions.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.datamapping - -import kotlin.reflect.full.memberProperties - -fun User.toUserView() = UserView( - name = "$firstName $lastName", - address = "$street $houseNumber", - telephone = phone, - age = age -) - -fun User.toUserViewReflection() = with(::UserView) { - val propertiesByName = User::class.memberProperties.associateBy { it.name } - callBy(parameters.associate { parameter -> - parameter to when (parameter.name) { - UserView::name.name -> "$firstName $lastName" - UserView::address.name -> "$street $houseNumber" - UserView::telephone.name -> phone - else -> propertiesByName[parameter.name]?.get(this@toUserViewReflection) - } - }) -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/datamapping/UserView.kt b/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/datamapping/UserView.kt deleted file mode 100644 index e1b6de6b57..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/datamapping/UserView.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.datamapping - -data class UserView( - val name: String, - val address: String, - val telephone: String, - val age: Int -) \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/dsl/SqlDsl.kt b/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/dsl/SqlDsl.kt deleted file mode 100644 index 207e9dbd53..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/dsl/SqlDsl.kt +++ /dev/null @@ -1,114 +0,0 @@ -package com.baeldung.dsl - -abstract class Condition { - - fun and(initializer: Condition.() -> Unit) { - addCondition(And().apply(initializer)) - } - - fun or(initializer: Condition.() -> Unit) { - addCondition(Or().apply(initializer)) - } - - infix fun String.eq(value: Any?) { - addCondition(Eq(this, value)) - } - - protected abstract fun addCondition(condition: Condition) -} - -open class CompositeCondition(private val sqlOperator: String) : Condition() { - private val conditions = mutableListOf() - - override fun addCondition(condition: Condition) { - conditions += condition - } - - override fun toString(): String { - return if (conditions.size == 1) { - conditions.first().toString() - } else { - conditions.joinToString(prefix = "(", postfix = ")", separator = " $sqlOperator ") { - "$it" - } - } - } -} - -class And : CompositeCondition("and") - -class Or : CompositeCondition("or") - -class Eq(private val column: String, private val value: Any?) : Condition() { - - init { - if (value != null && value !is Number && value !is String) { - throw IllegalArgumentException("Only , numbers and strings values can be used in the 'where' clause") - } - } - - override fun addCondition(condition: Condition) { - throw IllegalStateException("Can't add a nested condition to the sql 'eq'") - } - - override fun toString(): String { - return when (value) { - null -> "$column is null" - is String -> "$column = '$value'" - else -> "$column = $value" - } - } -} - -class SqlSelectBuilder { - - private val columns = mutableListOf() - private lateinit var table: String - private var condition: Condition? = null - - fun select(vararg columns: String) { - if (columns.isEmpty()) { - throw IllegalArgumentException("At least one column should be defined") - } - if (this.columns.isNotEmpty()) { - throw IllegalStateException("Detected an attempt to re-define columns to fetch. Current columns list: " - + "${this.columns}, new columns list: $columns") - } - this.columns.addAll(columns) - } - - fun from(table: String) { - this.table = table - } - - fun where(initializer: Condition.() -> Unit) { - condition = And().apply(initializer) - } - - fun build(): String { - if (!::table.isInitialized) { - throw IllegalStateException("Failed to build an sql select - target table is undefined") - } - return toString() - } - - override fun toString(): String { - val columnsToFetch = - if (columns.isEmpty()) { - "*" - } else { - columns.joinToString(", ") - } - val conditionString = - if (condition == null) { - "" - } else { - " where $condition" - } - return "select $columnsToFetch from $table$conditionString" - } -} - -fun query(initializer: SqlSelectBuilder.() -> Unit): SqlSelectBuilder { - return SqlSelectBuilder().apply(initializer) -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerAsExtensionOnAny.kt b/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerAsExtensionOnAny.kt deleted file mode 100644 index 01edf5e871..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerAsExtensionOnAny.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.logging - -import org.slf4j.Logger - -open class LoggerAsExtensionOnAny { - val logger = logger() - - fun log(s: String) { - logger().info(s) - logger.info(s) - } -} - -class ExtensionSubclass : LoggerAsExtensionOnAny() - -fun T.logger(): Logger = getLogger(getClassForLogging(javaClass)) - -fun main(args: Array) { - LoggerAsExtensionOnAny().log("test") - ExtensionSubclass().log("sub") - "foo".logger().info("foo") - 1.logger().info("uh-oh!") - SomeOtherClass().logger() -} - -class SomeOtherClass { - fun logger(): String { - return "foo" - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerAsExtensionOnMarkerInterface.kt b/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerAsExtensionOnMarkerInterface.kt deleted file mode 100644 index 8210361345..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerAsExtensionOnMarkerInterface.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.logging - -import org.slf4j.Logger -import org.slf4j.LoggerFactory - -interface Logging - -inline fun T.logger(): Logger = - //Wrong logger name! - //LoggerFactory.getLogger(javaClass.name + " w/interface") - LoggerFactory.getLogger(getClassForLogging(T::class.java).name + " w/interface") - -open class LoggerAsExtensionOnMarkerInterface : Logging { - companion object : Logging { - val logger = logger() - } - - fun log(s: String) { - logger().info(s) - logger.info(s) - } -} - -class MarkerExtensionSubclass : LoggerAsExtensionOnMarkerInterface() - -fun main(args: Array) { - LoggerAsExtensionOnMarkerInterface().log("test") - MarkerExtensionSubclass().log("sub") - "foo".logger().info("foo") -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerAsProperty.kt b/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerAsProperty.kt deleted file mode 100644 index 60ac0800e2..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerAsProperty.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.logging - -open class LoggerAsProperty { - private val logger = getLogger(javaClass) - - fun log(s: String) { - logger.info(s) - } - -} - -class PropertySubclass : LoggerAsProperty() - -fun main(args: Array) { - LoggerAsProperty().log("test") - PropertySubclass().log("sub") -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerAsPropertyDelegate.kt b/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerAsPropertyDelegate.kt deleted file mode 100644 index 83cde2b446..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerAsPropertyDelegate.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.baeldung.logging - -import org.slf4j.Logger -import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KProperty - -open class LoggerAsPropertyDelegate { - private val lazyLogger by lazyLogger() - protected val logger by LoggerDelegate() - private val logger2 = logger - - companion object { - private val lazyLoggerComp by lazyLogger() - private val loggerComp by LoggerDelegate() - } - - open fun log(s: String) { - logger.info(s) - logger2.info(s) - lazyLogger.info(s) - loggerComp.info(s) - lazyLoggerComp.info(s) - } - -} - -class DelegateSubclass : LoggerAsPropertyDelegate() { - override fun log(s: String) { - logger.info("-- in sub") - super.log(s) - } -} - -fun lazyLogger(forClass: Class<*>): Lazy = - lazy { getLogger(getClassForLogging(forClass)) } - -fun T.lazyLogger(): Lazy = lazyLogger(javaClass) - -fun main(args: Array) { - LoggerAsPropertyDelegate().log("test") - DelegateSubclass().log("sub") -} - -class LoggerDelegate : ReadOnlyProperty { - override fun getValue(thisRef: R, property: KProperty<*>) = - getLogger(getClassForLogging(thisRef.javaClass)) -} diff --git a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerInCompanionObject.kt b/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerInCompanionObject.kt deleted file mode 100644 index 6a44675e45..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/LoggerInCompanionObject.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.baeldung.logging - -open class LoggerInCompanionObject { - companion object { - private val loggerWithExplicitClass = getLogger(LoggerInCompanionObject::class.java) - @Suppress("JAVA_CLASS_ON_COMPANION") - private val loggerWithWrongClass = getLogger(javaClass) - @Suppress("JAVA_CLASS_ON_COMPANION") - private val logger = getLogger(javaClass.enclosingClass) - } - - fun log(s: String) { - loggerWithExplicitClass.info(s) - loggerWithWrongClass.info(s) - logger.info(s) - } - - class Inner { - companion object { - private val loggerWithExplicitClass = getLogger(Inner::class.java) - @Suppress("JAVA_CLASS_ON_COMPANION") - @JvmStatic - private val loggerWithWrongClass = getLogger(javaClass) - @Suppress("JAVA_CLASS_ON_COMPANION") - @JvmStatic - private val logger = getLogger(javaClass.enclosingClass) - } - - fun log(s: String) { - loggerWithExplicitClass.info(s) - loggerWithWrongClass.info(s) - logger.info(s) - } - } - -} - -class CompanionSubclass : LoggerInCompanionObject() - -fun main(args: Array) { - LoggerInCompanionObject().log("test") - LoggerInCompanionObject.Inner().log("test") - CompanionSubclass().log("sub") -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/Util.kt b/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/Util.kt deleted file mode 100644 index 44dba53cb7..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/main/kotlin/com/baeldung/logging/Util.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.logging - -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import kotlin.reflect.full.companionObject - -fun getLogger(forClass: Class<*>): Logger = LoggerFactory.getLogger(forClass) - -fun getClassForLogging(javaClass: Class): Class<*> { - return javaClass.enclosingClass?.takeIf { - it.kotlin.companionObject?.java == javaClass - } ?: javaClass -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/datamapping/UserTest.kt b/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/datamapping/UserTest.kt deleted file mode 100644 index 44d350ea38..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/datamapping/UserTest.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.baeldung.datamapping - -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertAll -import kotlin.test.assertEquals - -class UserTest { - - @Test - fun `maps User to UserResponse using extension function`() { - val p = buildUser() - val view = p.toUserView() - assertUserView(view) - } - - @Test - fun `maps User to UserResponse using reflection`() { - val p = buildUser() - val view = p.toUserViewReflection() - assertUserView(view) - } - - private fun buildUser(): User { - return User( - "Java", - "Duke", - "Javastreet", - "42", - "1234567", - 30, - "s3cr37" - ) - } - - private fun assertUserView(pr: UserView) { - assertAll( - { assertEquals("Java Duke", pr.name) }, - { assertEquals("Javastreet 42", pr.address) }, - { assertEquals("1234567", pr.telephone) }, - { assertEquals(30, pr.age) } - ) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/dsl/SqlDslTest.kt b/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/dsl/SqlDslTest.kt deleted file mode 100644 index a370e7f15d..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/dsl/SqlDslTest.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.baeldung.dsl - -import org.assertj.core.api.Assertions.assertThat -import org.junit.Test - -class SqlDslTest { - - @Test - fun `when no columns are specified then star is used`() { - doTest("select * from table1") { - from ("table1") - } - } - - @Test - fun `when no condition is specified then correct query is built`() { - doTest("select column1, column2 from table1") { - select("column1", "column2") - from ("table1") - } - } - - @Test(expected = Exception::class) - fun `when no table is specified then an exception is thrown`() { - query { - select("column1") - }.build() - } - - @Test - fun `when a list of conditions is specified then it's respected`() { - doTest("select * from table1 where (column3 = 4 and column4 is null)") { - from ("table1") - where { - "column3" eq 4 - "column4" eq null - } - } - } - - @Test - fun `when 'or' conditions are specified then they are respected`() { - doTest("select * from table1 where (column3 = 4 or column4 is null)") { - from ("table1") - where { - or { - "column3" eq 4 - "column4" eq null - } - } - } - } - - @Test - fun `when either 'and' or 'or' conditions are specified then they are respected`() { - doTest("select * from table1 where ((column3 = 4 or column4 is null) and column5 = 42)") { - from ("table1") - where { - and { - or { - "column3" eq 4 - "column4" eq null - } - "column5" eq 42 - } - } - } - } - - private fun doTest(expected: String, sql: SqlSelectBuilder.() -> Unit) { - assertThat(query(sql).build()).isEqualTo(expected) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/reflection/JavaReflectionTest.kt b/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/reflection/JavaReflectionTest.kt deleted file mode 100644 index c77774dd81..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/reflection/JavaReflectionTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.reflection - -import org.junit.Ignore -import org.junit.Test -import org.slf4j.LoggerFactory - -@Ignore -class JavaReflectionTest { - private val LOG = LoggerFactory.getLogger(KClassTest::class.java) - - @Test - fun listJavaClassMethods() { - Exception::class.java.methods - .forEach { method -> LOG.info("Method: {}", method) } - } - - @Test - fun listKotlinClassMethods() { - JavaReflectionTest::class.java.methods - .forEach { method -> LOG.info("Method: {}", method) } - } - - @Test - fun listKotlinDataClassMethods() { - data class ExampleDataClass(val name: String, var enabled: Boolean) - - ExampleDataClass::class.java.methods - .forEach { method -> LOG.info("Method: {}", method) } - } - - -} diff --git a/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/reflection/KClassTest.kt b/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/reflection/KClassTest.kt deleted file mode 100644 index f5d83cd13d..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/reflection/KClassTest.kt +++ /dev/null @@ -1,69 +0,0 @@ -package com.baeldung.reflection - -import org.junit.Assert -import org.junit.Ignore -import org.junit.Test -import org.slf4j.LoggerFactory -import java.math.BigDecimal -import kotlin.reflect.full.* - -class KClassTest { - private val LOG = LoggerFactory.getLogger(KClassTest::class.java) - - @Test - fun testKClassDetails() { - val stringClass = String::class - Assert.assertEquals("kotlin.String", stringClass.qualifiedName) - Assert.assertFalse(stringClass.isData) - Assert.assertFalse(stringClass.isCompanion) - Assert.assertFalse(stringClass.isAbstract) - Assert.assertTrue(stringClass.isFinal) - Assert.assertFalse(stringClass.isSealed) - - val listClass = List::class - Assert.assertEquals("kotlin.collections.List", listClass.qualifiedName) - Assert.assertFalse(listClass.isData) - Assert.assertFalse(listClass.isCompanion) - Assert.assertTrue(listClass.isAbstract) - Assert.assertFalse(listClass.isFinal) - Assert.assertFalse(listClass.isSealed) - } - - @Test - fun testGetRelated() { - LOG.info("Companion Object: {}", TestSubject::class.companionObject) - LOG.info("Companion Object Instance: {}", TestSubject::class.companionObjectInstance) - LOG.info("Object Instance: {}", TestObject::class.objectInstance) - - Assert.assertSame(TestObject, TestObject::class.objectInstance) - } - - @Test - fun testNewInstance() { - val listClass = ArrayList::class - - val list = listClass.createInstance() - Assert.assertTrue(list is ArrayList) - } - - @Test - @Ignore - fun testMembers() { - val bigDecimalClass = BigDecimal::class - - LOG.info("Constructors: {}", bigDecimalClass.constructors) - LOG.info("Functions: {}", bigDecimalClass.functions) - LOG.info("Properties: {}", bigDecimalClass.memberProperties) - LOG.info("Extension Functions: {}", bigDecimalClass.memberExtensionFunctions) - } -} - -class TestSubject { - companion object { - val name = "TestSubject" - } -} - -object TestObject { - val answer = 42 -} diff --git a/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/reflection/KMethodTest.kt b/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/reflection/KMethodTest.kt deleted file mode 100644 index b58c199a7c..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/reflection/KMethodTest.kt +++ /dev/null @@ -1,88 +0,0 @@ -package com.baeldung.reflection - -import org.junit.Assert -import org.junit.Test -import java.io.ByteArrayInputStream -import java.nio.charset.Charset -import kotlin.reflect.KMutableProperty -import kotlin.reflect.full.starProjectedType - -class KMethodTest { - - @Test - fun testCallMethod() { - val str = "Hello" - val lengthMethod = str::length - - Assert.assertEquals(5, lengthMethod()) - } - - @Test - fun testReturnType() { - val str = "Hello" - val method = str::byteInputStream - - Assert.assertEquals(ByteArrayInputStream::class.starProjectedType, method.returnType) - Assert.assertFalse(method.returnType.isMarkedNullable) - } - - @Test - fun testParams() { - val str = "Hello" - val method = str::byteInputStream - - method.isSuspend - Assert.assertEquals(1, method.parameters.size) - Assert.assertTrue(method.parameters[0].isOptional) - Assert.assertFalse(method.parameters[0].isVararg) - Assert.assertEquals(Charset::class.starProjectedType, method.parameters[0].type) - } - - @Test - fun testMethodDetails() { - val codePoints = String::codePoints - Assert.assertEquals("codePoints", codePoints.name) - Assert.assertFalse(codePoints.isSuspend) - Assert.assertFalse(codePoints.isExternal) - Assert.assertFalse(codePoints.isInline) - Assert.assertFalse(codePoints.isOperator) - - val byteInputStream = String::byteInputStream - Assert.assertEquals("byteInputStream", byteInputStream.name) - Assert.assertFalse(byteInputStream.isSuspend) - Assert.assertFalse(byteInputStream.isExternal) - Assert.assertTrue(byteInputStream.isInline) - Assert.assertFalse(byteInputStream.isOperator) - } - - val readOnlyProperty: Int = 42 - lateinit var mutableProperty: String - - @Test - fun testPropertyDetails() { - val roProperty = this::readOnlyProperty - Assert.assertEquals("readOnlyProperty", roProperty.name) - Assert.assertFalse(roProperty.isLateinit) - Assert.assertFalse(roProperty.isConst) - Assert.assertFalse(roProperty is KMutableProperty<*>) - - val mProperty = this::mutableProperty - Assert.assertEquals("mutableProperty", mProperty.name) - Assert.assertTrue(mProperty.isLateinit) - Assert.assertFalse(mProperty.isConst) - Assert.assertTrue(mProperty is KMutableProperty<*>) - } - - @Test - fun testProperty() { - val prop = this::mutableProperty - - Assert.assertEquals(String::class.starProjectedType, prop.getter.returnType) - - prop.set("Hello") - Assert.assertEquals("Hello", prop.get()) - - prop.setter("World") - Assert.assertEquals("World", prop.getter()) - } -} diff --git a/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/regex/RegexTest.kt b/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/regex/RegexTest.kt deleted file mode 100644 index 5cb54b4dda..0000000000 --- a/core-kotlin-modules/core-kotlin-advanced/src/test/kotlin/com/baeldung/regex/RegexTest.kt +++ /dev/null @@ -1,123 +0,0 @@ -package com.baeldung.regex - -import org.junit.Test -import kotlin.test.* - -class RegexTest { - - @Test - fun whenRegexIsInstantiated_thenIsEqualToToRegexMethod() { - val pattern = """a([bc]+)d?\\""" - - assertEquals(Regex.fromLiteral(pattern).pattern, pattern) - assertEquals(pattern, Regex(pattern).pattern) - assertEquals(pattern, pattern.toRegex().pattern) - } - - @Test - fun whenRegexMatches_thenResultIsTrue() { - val regex = """a([bc]+)d?""".toRegex() - - assertTrue(regex.containsMatchIn("xabcdy")) - assertTrue(regex.matches("abcd")) - assertFalse(regex matches "xabcdy") - } - - @Test - fun givenCompletelyMatchingRegex_whenMatchResult_thenDestructuring() { - val regex = """a([bc]+)d?""".toRegex() - - assertNull(regex.matchEntire("xabcdy")) - - val matchResult = regex.matchEntire("abbccbbd") - - assertNotNull(matchResult) - assertEquals(matchResult!!.value, matchResult.groupValues[0]) - assertEquals(matchResult.destructured.toList(), matchResult.groupValues.drop(1)) - assertEquals("bbccbb", matchResult.destructured.component1()) - assertNull(matchResult.next()) - } - - @Test - fun givenPartiallyMatchingRegex_whenMatchResult_thenGroups() { - val regex = """a([bc]+)d?""".toRegex() - var matchResult = regex.find("abcb abbd") - - assertNotNull(matchResult) - assertEquals(matchResult!!.value, matchResult.groupValues[0]) - assertEquals("abcb", matchResult.value) - assertEquals(IntRange(0, 3), matchResult.range) - assertEquals(listOf("abcb", "bcb"), matchResult.groupValues) - assertEquals(matchResult.destructured.toList(), matchResult.groupValues.drop(1)) - - matchResult = matchResult.next() - - assertNotNull(matchResult) - assertEquals("abbd", matchResult!!.value) - assertEquals("bb", matchResult.groupValues[1]) - - matchResult = matchResult.next() - - assertNull(matchResult) - } - - @Test - fun givenPartiallyMatchingRegex_whenMatchResult_thenDestructuring() { - val regex = """([\w\s]+) is (\d+) years old""".toRegex() - val matchResult = regex.find("Mickey Mouse is 95 years old") - val (name, age) = matchResult!!.destructured - - assertEquals("Mickey Mouse", name) - assertEquals("95", age) - } - - @Test - fun givenNonMatchingRegex_whenFindCalled_thenNull() { - val regex = """a([bc]+)d?""".toRegex() - val matchResult = regex.find("foo") - - assertNull(matchResult) - } - - @Test - fun givenNonMatchingRegex_whenFindAllCalled_thenEmptySet() { - val regex = """a([bc]+)d?""".toRegex() - val matchResults = regex.findAll("foo") - - assertNotNull(matchResults) - assertTrue(matchResults.none()) - } - - @Test - fun whenReplace_thenReplacement() { - val regex = """(red|green|blue)""".toRegex() - val beautiful = "Roses are red, Violets are blue" - val grim = regex.replace(beautiful, "dark") - val shiny = regex.replaceFirst(beautiful, "rainbow") - - assertEquals("Roses are dark, Violets are dark", grim) - assertEquals("Roses are rainbow, Violets are blue", shiny) - } - - @Test - fun whenComplexReplace_thenReplacement() { - val regex = """(red|green|blue)""".toRegex() - val beautiful = "Roses are red, Violets are blue" - val reallyBeautiful = regex.replace(beautiful) { - matchResult -> matchResult.value.toUpperCase() + "!" - } - - assertEquals("Roses are RED!, Violets are BLUE!", reallyBeautiful) - } - - @Test - fun whenSplit_thenList() { - val regex = """\W+""".toRegex() - val beautiful = "Roses are red, Violets are blue" - - assertEquals(listOf("Roses", "are", "red", "Violets", "are", "blue"), regex.split(beautiful)) - assertEquals(listOf("Roses", "are", "red", "Violets are blue"), regex.split(beautiful, 4)) - assertEquals(regex.toPattern().split(beautiful).asList(), regex.split(beautiful)) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-annotations/README.md b/core-kotlin-modules/core-kotlin-annotations/README.md deleted file mode 100644 index 787b67be11..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/README.md +++ /dev/null @@ -1,8 +0,0 @@ -## Core Kotlin Annotations - -This module contains articles about core Kotlin annotations. - -### Relevant articles: -- [Kotlin Annotations](https://www.baeldung.com/kotlin-annotations) -- [Guide to Kotlin @JvmField](https://www.baeldung.com/kotlin-jvm-field-annotation) -- [Guide to JVM Platform Annotations in Kotlin](https://www.baeldung.com/kotlin-jvm-annotations) diff --git a/core-kotlin-modules/core-kotlin-annotations/pom.xml b/core-kotlin-modules/core-kotlin-annotations/pom.xml deleted file mode 100644 index 77670be151..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - 4.0.0 - core-kotlin-annotations - core-kotlin-annotations - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - - - org.assertj - assertj-core - ${assertj.version} - test - - - org.jetbrains.kotlin - kotlin-test - ${kotlin.version} - test - - - - - 1.3.30 - 3.10.0 - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/annotations/Annotations.kt b/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/annotations/Annotations.kt deleted file mode 100644 index a8f83446dc..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/annotations/Annotations.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.baeldung.annotations - -@Target(AnnotationTarget.FIELD) -annotation class Positive - -@Target(AnnotationTarget.FIELD) -annotation class AllowedNames(val names: Array) diff --git a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/annotations/Item.kt b/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/annotations/Item.kt deleted file mode 100644 index 6864fe416e..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/annotations/Item.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.annotations - -class Item(@Positive val amount: Float, @AllowedNames(["Alice", "Bob"]) val name: String) \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/annotations/Main.kt b/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/annotations/Main.kt deleted file mode 100644 index 2b7f2c5590..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/annotations/Main.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.baeldung.annotations - -fun main(args: Array) { - val item = Item(amount = 1.0f, name = "Bob") - val validator = Validator() - println("Is instance valid? ${validator.isValid(item)}") -} diff --git a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/annotations/Validator.kt b/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/annotations/Validator.kt deleted file mode 100644 index 40139048ab..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/annotations/Validator.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.baeldung.annotations - -/** - * Naive annotation-based validator. - * @author A.Shcherbakov - */ -class Validator() { - - /** - * Return true if every item's property annotated with @Positive is positive and if - * every item's property annotated with @AllowedNames has a value specified in that annotation. - */ - fun isValid(item: Item): Boolean { - val fields = item::class.java.declaredFields - for (field in fields) { - field.isAccessible = true - for (annotation in field.annotations) { - val value = field.get(item) - if (field.isAnnotationPresent(Positive::class.java)) { - val amount = value as Float - if (amount < 0) { - return false - } - } - if (field.isAnnotationPresent(AllowedNames::class.java)) { - val allowedNames = field.getAnnotation(AllowedNames::class.java)?.names - val name = value as String - allowedNames?.let { - if (!it.contains(name)) { - return false - } - } - } - } - } - return true - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/Document.kt b/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/Document.kt deleted file mode 100644 index 55f60bfa81..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/Document.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.jvmannotations - -import java.util.* - -interface Document { - - @JvmDefault - fun getTypeDefault() = "document" - - fun getType() = "document" -} diff --git a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/HtmlDocument.java b/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/HtmlDocument.java deleted file mode 100644 index feb71772cb..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/HtmlDocument.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.baeldung.jvmannotations; - -public class HtmlDocument implements Document { - - @Override - public String getType() { - return "HTML"; - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/Message.kt b/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/Message.kt deleted file mode 100644 index 80180bd924..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/Message.kt +++ /dev/null @@ -1,66 +0,0 @@ -@file:JvmName("MessageHelper") -@file:JvmMultifileClass //used -package com.baeldung.jvmannotations - -import java.util.* - -@JvmName("getMyUsername") -fun getMyName() : String { - return "myUserId" -} - -object MessageBroker { - @JvmStatic - var totalMessagesSent = 0 - - const val maxMessageLength = 0 - - @JvmStatic - fun clearAllMessages() { - } - - @JvmStatic - @JvmOverloads - @Throws(Exception::class) - fun findMessages(sender : String, type : String = "text", maxResults : Int = 10) : List { - if(sender.isEmpty()) { - throw Exception() - } - return ArrayList() - } -} - -class Message { - - // this would cause a compilation error since sender is immutable - // @set:JvmName("setSender") - val sender = "myself" - - // this works as name is overridden - @JvmName("getSenderName") - fun getSender() : String = "from:$sender" - - @get:JvmName("getReceiverName") - @set:JvmName("setReceiverName") - var receiver : String = "" - - @get:JvmName("getContent") - @set:JvmName("setContent") - var text = "" - - // generates a warning - @get:JvmName("getId") - private val id = 0 - - @get:JvmName("hasAttachment") - var hasAttachment = true - - var isEncrypted = true - - fun setReceivers(receiverNames : List) { - } - - @JvmName("setReceiverIds") - fun setReceivers(receiverNames : List) { - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/MessageConverter.kt b/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/MessageConverter.kt deleted file mode 100644 index 3b19b12e10..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/MessageConverter.kt +++ /dev/null @@ -1,6 +0,0 @@ -@file:JvmMultifileClass -@file:JvmName("MessageHelper") //applies to all top level functions / variables / constants -package com.baeldung.jvmannotations - -fun convert(message: Message) { -} diff --git a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/TextDocument.kt b/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/TextDocument.kt deleted file mode 100644 index 41cb0df939..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/TextDocument.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.baeldung.jvmannotations - -import java.util.* -class TextDocument : Document { - override fun getType() = "text" - - fun transformList(list : List) : List { - return list.filter { n -> n.toInt() > 1 } - } - - fun transformListInverseWildcards(list : List<@JvmSuppressWildcards Number>) : List<@JvmWildcard Number> { - return list.filter { n -> n.toInt() > 1 } - } - - var list : List<@JvmWildcard Any> = ArrayList() -} diff --git a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/XmlDocument.kt b/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/XmlDocument.kt deleted file mode 100644 index 00f2582d5f..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmannotations/XmlDocument.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.baeldung.jvmannotations - -import java.util.* - -class XmlDocument(d : Document) : Document by d diff --git a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmfield/JvmSample.kt b/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmfield/JvmSample.kt deleted file mode 100644 index e60894ba88..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/src/main/kotlin/com/baeldung/jvmfield/JvmSample.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.jvmfield - -class JvmSample(text:String) { - @JvmField - val sampleText:String = text -} - -class CompanionSample { - companion object { - @JvmField val MAX_LIMIT = 20 - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-annotations/src/test/kotlin/com/baeldung/annotations/ValidationTest.kt b/core-kotlin-modules/core-kotlin-annotations/src/test/kotlin/com/baeldung/annotations/ValidationTest.kt deleted file mode 100644 index 5c2b6ef47f..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/src/test/kotlin/com/baeldung/annotations/ValidationTest.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.baeldung.annotations - -import org.junit.Test -import kotlin.test.assertTrue -import kotlin.test.assertFalse - -class ValidationTest { - - @Test - fun whenAmountIsOneAndNameIsAlice_thenTrue() { - assertTrue(Validator().isValid(Item(1f, "Alice"))) - } - - @Test - fun whenAmountIsOneAndNameIsBob_thenTrue() { - assertTrue(Validator().isValid(Item(1f, "Bob"))) - } - - - @Test - fun whenAmountIsMinusOneAndNameIsAlice_thenFalse() { - assertFalse(Validator().isValid(Item(-1f, "Alice"))) - } - - @Test - fun whenAmountIsMinusOneAndNameIsBob_thenFalse() { - assertFalse(Validator().isValid(Item(-1f, "Bob"))) - } - - @Test - fun whenAmountIsOneAndNameIsTom_thenFalse() { - assertFalse(Validator().isValid(Item(1f, "Tom"))) - } - - @Test - fun whenAmountIsMinusOneAndNameIsTom_thenFalse() { - assertFalse(Validator().isValid(Item(-1f, "Tom"))) - } - - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-annotations/src/test/kotlin/com/baeldung/jvmannotations/DocumentTest.kt b/core-kotlin-modules/core-kotlin-annotations/src/test/kotlin/com/baeldung/jvmannotations/DocumentTest.kt deleted file mode 100644 index 2ec5402e5a..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/src/test/kotlin/com/baeldung/jvmannotations/DocumentTest.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.baeldung.range - -import org.junit.Test -import kotlin.test.assertEquals - -import com.baeldung.jvmannotations.*; - -class DocumentTest { - - @Test - fun testDefaultMethod() { - - val myDocument = TextDocument() - val myTextDocument = XmlDocument(myDocument) - - assertEquals("text", myDocument.getType()) - assertEquals("text", myTextDocument.getType()) - assertEquals("document", myTextDocument.getTypeDefault()) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-annotations/src/test/kotlin/com/baeldung/jvmfield/JvmSampleTest.kt b/core-kotlin-modules/core-kotlin-annotations/src/test/kotlin/com/baeldung/jvmfield/JvmSampleTest.kt deleted file mode 100644 index 769c0311c4..0000000000 --- a/core-kotlin-modules/core-kotlin-annotations/src/test/kotlin/com/baeldung/jvmfield/JvmSampleTest.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.baeldung.jvmfield - -import org.junit.Before -import org.junit.Test -import kotlin.test.assertTrue - -class JvmSampleTest { - - var sample = "" - - @Before - fun setUp() { - sample = JvmSample("Hello!").sampleText - } - - @Test - fun givenField_whenCheckValue_thenMatchesValue() { - assertTrue(sample == "Hello!") - } - - @Test - fun givenStaticVariable_whenCheckValue_thenMatchesValue() { - // Sample when is treated as a static variable - assertTrue(CompanionSample.MAX_LIMIT == 20) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections-2/README.md b/core-kotlin-modules/core-kotlin-collections-2/README.md deleted file mode 100644 index 64062ee704..0000000000 --- a/core-kotlin-modules/core-kotlin-collections-2/README.md +++ /dev/null @@ -1,7 +0,0 @@ -## Core Kotlin Collections - -This module contains articles about core Kotlin collections. - -## Relevant articles: - -- [Aggregate Operations in Kotlin](https://www.baeldung.com/kotlin/aggregate-operations) diff --git a/core-kotlin-modules/core-kotlin-collections-2/pom.xml b/core-kotlin-modules/core-kotlin-collections-2/pom.xml deleted file mode 100644 index be462eed45..0000000000 --- a/core-kotlin-modules/core-kotlin-collections-2/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - 4.0.0 - core-kotlin-collections-2 - core-kotlin-collections-2 - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - - - org.apache.commons - commons-math3 - ${commons-math3.version} - - - org.assertj - assertj-core - ${assertj.version} - test - - - org.jetbrains.kotlin - kotlin-test - ${kotlin.version} - test - - - - - 1.3.30 - 3.6.1 - 3.10.0 - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections-2/src/main/kotlin/com/baeldung/aggregate/AggregateOperations.kt b/core-kotlin-modules/core-kotlin-collections-2/src/main/kotlin/com/baeldung/aggregate/AggregateOperations.kt deleted file mode 100644 index a09e101b59..0000000000 --- a/core-kotlin-modules/core-kotlin-collections-2/src/main/kotlin/com/baeldung/aggregate/AggregateOperations.kt +++ /dev/null @@ -1,107 +0,0 @@ -package com.baeldung.aggregate - -class AggregateOperations { - private val numbers = listOf(1, 15, 3, 8) - - fun countList(): Int { - return numbers.count() - } - - fun sumList(): Int { - return numbers.sum() - } - - fun averageList(): Double { - return numbers.average() - } - - fun maximumInList(): Int? { - return numbers.max() - } - - fun minimumInList(): Int? { - return numbers.min() - } - - fun maximumByList(): Int? { - return numbers.maxBy { it % 5 } - } - - fun minimumByList(): Int? { - return numbers.minBy { it % 5 } - } - - fun maximumWithList(): String? { - val strings = listOf("Berlin", "Kolkata", "Prague", "Barcelona") - return strings.maxWith(compareBy { it.length % 4 }) - } - - fun minimumWithList(): String? { - val strings = listOf("Berlin", "Kolkata", "Prague", "Barcelona") - return strings.minWith(compareBy { it.length % 4 }) - } - - fun sumByList(): Int { - return numbers.sumBy { it * 5 } - } - - fun sumByDoubleList(): Double { - return numbers.sumByDouble { it.toDouble() / 8 } - } - - fun foldList(): Int { - return numbers.fold(100) { total, it -> - println("total = $total, it = $it") - total - it - } // ((((100 - 1)-15)-3)-8) = 73 - } - - fun foldRightList(): Int { - return numbers.foldRight(100) { it, total -> - println("total = $total, it = $it") - total - it - } // ((((100-8)-3)-15)-1) = 73 - } - - fun foldIndexedList(): Int { - return numbers.foldIndexed(100) { index, total, it -> - println("total = $total, it = $it, index = $index") - if (index.minus(2) >= 0) total - it else total - } // ((100 - 3)-8) = 89 - } - - fun foldRightIndexedList(): Int { - return numbers.foldRightIndexed(100) { index, it, total -> - println("total = $total, it = $it, index = $index") - if (index.minus(2) >= 0) total - it else total - } // ((100 - 8)-3) = 89 - } - - fun reduceList(): Int { - return numbers.reduce { total, it -> - println("total = $total, it = $it") - total - it - } // (((1 - 15)-3)-8) = -25 - } - - fun reduceRightList(): Int { - return numbers.reduceRight() { it, total -> - println("total = $total, it = $it") - total - it - } // ((8-3)-15)-1) = -11 - } - - fun reduceIndexedList(): Int { - return numbers.reduceIndexed { index, total, it -> - println("total = $total, it = $it, index = $index") - if (index.minus(2) >= 0) total - it else total - } // ((1-3)-8) = -10 - } - - fun reduceRightIndexedList(): Int { - return numbers.reduceRightIndexed { index, it, total -> - println("total = $total, it = $it, index = $index") - if (index.minus(2) >= 0) total - it else total - } // ((8-3) = 5 - } -} diff --git a/core-kotlin-modules/core-kotlin-collections-2/src/test/kotlin/com/baeldung/aggregate/AggregateOperationsUnitTest.kt b/core-kotlin-modules/core-kotlin-collections-2/src/test/kotlin/com/baeldung/aggregate/AggregateOperationsUnitTest.kt deleted file mode 100644 index a619759b0a..0000000000 --- a/core-kotlin-modules/core-kotlin-collections-2/src/test/kotlin/com/baeldung/aggregate/AggregateOperationsUnitTest.kt +++ /dev/null @@ -1,104 +0,0 @@ -package com.baeldung.aggregate - -import org.junit.jupiter.api.Test -import kotlin.test.assertEquals - -class AggregateOperationsUnitTest { - - private val classUnderTest: AggregateOperations = AggregateOperations() - - @Test - fun whenCountOfList_thenReturnsValue() { - assertEquals(4, classUnderTest.countList()) - } - - @Test - fun whenSumOfList_thenReturnsTotalValue() { - assertEquals(27, classUnderTest.sumList()) - } - - @Test - fun whenAverageOfList_thenReturnsValue() { - assertEquals(6.75, classUnderTest.averageList()) - } - - @Test - fun whenMaximumOfList_thenReturnsMaximumValue() { - assertEquals(15, classUnderTest.maximumInList()) - } - - @Test - fun whenMinimumOfList_thenReturnsMinimumValue() { - assertEquals(1, classUnderTest.minimumInList()) - } - - @Test - fun whenMaxByList_thenReturnsLargestValue() { - assertEquals(3, classUnderTest.maximumByList()) - } - - @Test - fun whenMinByList_thenReturnsSmallestValue() { - assertEquals(15, classUnderTest.minimumByList()) - } - - @Test - fun whenMaxWithList_thenReturnsLargestValue(){ - assertEquals("Kolkata", classUnderTest.maximumWithList()) - } - - @Test - fun whenMinWithList_thenReturnsSmallestValue(){ - assertEquals("Barcelona", classUnderTest.minimumWithList()) - } - - @Test - fun whenSumByList_thenReturnsIntegerValue(){ - assertEquals(135, classUnderTest.sumByList()) - } - - @Test - fun whenSumByDoubleList_thenReturnsDoubleValue(){ - assertEquals(3.375, classUnderTest.sumByDoubleList()) - } - - @Test - fun whenFoldList_thenReturnsValue(){ - assertEquals(73, classUnderTest.foldList()) - } - - @Test - fun whenFoldRightList_thenReturnsValue(){ - assertEquals(73, classUnderTest.foldRightList()) - } - - @Test - fun whenFoldIndexedList_thenReturnsValue(){ - assertEquals(89, classUnderTest.foldIndexedList()) - } - - @Test - fun whenFoldRightIndexedList_thenReturnsValue(){ - assertEquals(89, classUnderTest.foldRightIndexedList()) - } - - @Test - fun whenReduceList_thenReturnsValue(){ - assertEquals(-25, classUnderTest.reduceList()) - } - - @Test - fun whenReduceRightList_thenReturnsValue(){ - assertEquals(-11, classUnderTest.reduceRightList()) - } - - @Test - fun whenReduceIndexedList_thenReturnsValue(){ - assertEquals(-10, classUnderTest.reduceIndexedList()) - } - - @Test - fun whenReduceRightIndexedList_thenReturnsValue(){ - assertEquals(5, classUnderTest.reduceRightIndexedList()) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/README.md b/core-kotlin-modules/core-kotlin-collections/README.md deleted file mode 100644 index 2ebb748cba..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/README.md +++ /dev/null @@ -1,16 +0,0 @@ -## Core Kotlin Collections - -This module contains articles about core Kotlin collections. - -### Relevant articles: - -- [Split a List Into Parts in Kotlin](https://www.baeldung.com/kotlin-split-list-into-parts) -- [Finding an Element in a List Using Kotlin](https://www.baeldung.com/kotlin-finding-element-in-list) -- [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) -- [Difference between fold and reduce in Kotlin](https://www.baeldung.com/kotlin/fold-vs-reduce) -- [Guide to Sorting in Kotlin](https://www.baeldung.com/kotlin-sort) -- [Working With Lists in Kotlin](https://www.baeldung.com/kotlin/lists) -- [Iterating Collections by Index in Kotlin](https://www.baeldung.com/kotlin/iterating-collections-by-index) diff --git a/core-kotlin-modules/core-kotlin-collections/pom.xml b/core-kotlin-modules/core-kotlin-collections/pom.xml deleted file mode 100644 index 52401d267c..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/pom.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - 4.0.0 - core-kotlin-collections - core-kotlin-collections - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - - - org.apache.commons - commons-math3 - ${commons-math3.version} - - - org.assertj - assertj-core - ${assertj.version} - test - - - org.jetbrains.kotlin - kotlin-test - ${kotlin.version} - test - - - - - 1.3.30 - 3.6.1 - 3.10.0 - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/main/kotlin/com/baeldung/index/IndexedIteration.kt b/core-kotlin-modules/core-kotlin-collections/src/main/kotlin/com/baeldung/index/IndexedIteration.kt deleted file mode 100644 index 07fb595ede..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/main/kotlin/com/baeldung/index/IndexedIteration.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.baeldung.index - -fun main() { - - // Index only - val colors = listOf("Red", "Green", "Blue") - for (i in colors.indices) { - println(colors[i]) - } - - val colorArray = arrayOf("Red", "Green", "Blue") - for (i in colorArray.indices) { - println(colorArray[i]) - } - - (0 until colors.size).forEach { println(colors[it]) } - for (i in 0 until colors.size) { - println(colors[i]) - } - - // Index and Value - colors.forEachIndexed { i, v -> println("The value for index $i is $v") } - for (indexedValue in colors.withIndex()) { - println("The value for index ${indexedValue.index} is ${indexedValue.value}") - } - - for ((i, v) in colors.withIndex()) { - println("The value for index $i is $v") - } - - colors.filterIndexed { i, _ -> i % 2 == 0 } - colors.filterIndexed { _, v -> v == "RED" } -} diff --git a/core-kotlin-modules/core-kotlin-collections/src/main/kotlin/com/baeldung/kotlin/collections/ListExample.kt b/core-kotlin-modules/core-kotlin-collections/src/main/kotlin/com/baeldung/kotlin/collections/ListExample.kt deleted file mode 100644 index a29eabe623..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/main/kotlin/com/baeldung/kotlin/collections/ListExample.kt +++ /dev/null @@ -1,204 +0,0 @@ -package com.baeldung.kotlin.collections - -import kotlin.collections.List - -class ListExample { - - private val countries = listOf("Germany", "India", "Japan", "Brazil", "Australia") - private val cities = mutableListOf("Berlin", "Calcutta", "Seoul", "Sao Paulo", "Sydney") - - fun createList(): List { - val countryList = listOf("Germany", "India", "Japan", "Brazil") - return countryList - } - - fun createMutableList(): MutableList { - val cityList = mutableListOf("Berlin", "Calcutta", "Seoul", "Sao Paulo") - return cityList - } - - fun iterateUsingForEachLoop(): List { - val countryLength = mutableListOf() - countries.forEach { it -> - print("$it ") - println(" Length: ${it.length}") - countryLength.add(it.length) - } - return countryLength - } - - fun iterateUsingForLoop(): List { - val countryLength = mutableListOf() - for (country in countries) { - print("$country ") - println(" Length: ${country.length}") - countryLength.add(country.length) - } - return countryLength - } - - fun iterateUsingForLoopRange(): List { - val countryLength = mutableListOf() - for (i in 0 until countries.size) { - print("${countries[i]} ") - println(" Length: ${countries[i].length}") - countryLength.add(countries[i].length) - } - return countryLength - } - - fun iterateUsingForEachIndexedLoop(): List { - val countryLength = mutableListOf() - countries.forEachIndexed { i, e -> - println("country[$i] = $e") - print(" Index: $i") - println(" Length: ${e.length}") - countryLength.add(e.length) - } - return countryLength - } - - fun iterateUsingListIterator() { - val iterator = countries.listIterator() - while (iterator.hasNext()) { - val country = iterator.next() - print("$country ") - } - println() - - while (iterator.hasPrevious()) { - println("Index: ${iterator.previousIndex()}") - } - } - - fun iterateUsingIterator() { - val iterator = cities.iterator() - iterator.next() - iterator.remove() - println(cities) - } - - fun iterateUsingMutableListIterator() { - val iterator = cities.listIterator(1) - iterator.next() - iterator.add("London") - iterator.next() - iterator.set("Milan") - println(cities) - } - - fun retrieveElementsInList(): String { - println(countries[2]) - return countries[2] - } - - fun retrieveElementsUsingGet(): String { - println(countries.get(3)) - return countries.get(3) - } - - fun retrieveElementsFirstAndLast(): String? { - println(countries.first()) - println(countries.last()) - println(countries.first { it.length > 7 }) - println(countries.last { it.startsWith("J") }) - println(countries.firstOrNull { it.length > 8 }) - return countries.firstOrNull { it.length > 8 } - } - - fun retrieveSubList(): List { - val subList = countries.subList(1, 4) - println(subList) - return subList - } - - fun retrieveListSliceUsingIndices(): List { - val sliceList = countries.slice(1..4) - println(sliceList) - return sliceList - } - - fun retrieveListSliceUsingIndicesList(): List { - val sliceList = countries.slice(listOf(1, 4)) - println(sliceList) - return sliceList - } - - fun countList(): Int { - val count = countries.count() - println(count) - return count - } - - fun countListUsingPredicate(): Int { - val count = countries.count { it.length > 5 } - println(count) - return count - } - - fun countListUsingProperty(): Int { - val size = countries.size - println(size) - return size - } - - fun addToList(): List { - cities.add("Barcelona") - println(cities) - cities.add(3, "London") - println(cities) - cities.addAll(listOf("Singapore", "Moscow")) - println(cities) - cities.addAll(2, listOf("Prague", "Amsterdam")) - println(cities) - return cities - } - - fun removeFromList(): List { - cities.remove("Seoul") - println(cities) - cities.removeAt(1) - println(cities) - return cities - } - - fun replaceFromList(): List { - cities.set(3, "Prague") - println(cities) - cities[4] = "Moscow" - println(cities) - cities.fill("Barcelona") - println(cities) - return cities - } - - fun sortMutableList(): List { - cities.sort() - println(cities) - cities.sortDescending() - println(cities) - return cities - } - - fun sortList(): List { - val sortedCountries = countries.sorted() - println("countries = $countries") - println("sortedCountries = $sortedCountries") - val sortedCountriesDescending = countries.sortedDescending() - println("countries = $countries") - println("sortedCountriesDescending = $sortedCountriesDescending") - return sortedCountriesDescending - } - - fun checkOneElementInList(): Boolean { - return countries.contains("Germany") - } - - fun checkOneElementInListUsingOperator(): Boolean { - return "Spain" in countries - } - - fun checkElementsInList(): Boolean { - return cities.containsAll(listOf("Calcutta", "Sao Paulo", "Sydney")) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/main/kotlin/com/baeldung/sorting/SortingExample.kt b/core-kotlin-modules/core-kotlin-collections/src/main/kotlin/com/baeldung/sorting/SortingExample.kt deleted file mode 100644 index bf3163bc8f..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/main/kotlin/com/baeldung/sorting/SortingExample.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.sorting - -fun sortMethodUsage() { - val sortedValues = mutableListOf(1, 2, 7, 6, 5, 6) - sortedValues.sort() - println(sortedValues) -} - -fun sortByMethodUsage() { - val sortedValues = mutableListOf(1 to "a", 2 to "b", 7 to "c", 6 to "d", 5 to "c", 6 to "e") - sortedValues.sortBy { it.second } - println(sortedValues) -} - -fun sortWithMethodUsage() { - val sortedValues = mutableListOf(1 to "a", 2 to "b", 7 to "c", 6 to "d", 5 to "c", 6 to "e") - sortedValues.sortWith(compareBy({it.second}, {it.first})) - println(sortedValues) -} - -fun > getSimpleComparator() : Comparator { - val ascComparator = naturalOrder() - return ascComparator -} - -fun getComplexComparator() { - val complexComparator = compareBy>({it.first}, {it.second}) -} - -fun nullHandlingUsage() { - val sortedValues = mutableListOf(1 to "a", 2 to null, 7 to "c", 6 to "d", 5 to "c", 6 to "e") - sortedValues.sortWith(nullsLast(compareBy { it.second })) - println(sortedValues) -} - -fun extendedComparatorUsage() { - val students = mutableListOf(21 to "Helen", 21 to "Tom", 20 to "Jim") - - val ageComparator = compareBy> {it.first} - val ageAndNameComparator = ageComparator.thenByDescending {it.second} - println(students.sortedWith(ageAndNameComparator)) -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/CollectionsTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/CollectionsTest.kt deleted file mode 100644 index 67fbb29026..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/CollectionsTest.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.baeldung.collections - -import org.assertj.core.api.Assertions.assertThat -import org.junit.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -class CollectionsTest { - - @Test - fun whenUseDifferentCollections_thenSuccess() { - val theList = listOf("one", "two", "three") - assertTrue(theList.contains("two")) - - val theMutableList = mutableListOf("one", "two", "three") - theMutableList.add("four") - assertTrue(theMutableList.contains("four")) - - val theSet = setOf("one", "two", "three") - assertTrue(theSet.contains("three")) - - val theMutableSet = mutableSetOf("one", "two", "three") - theMutableSet.add("four") - assertTrue(theMutableSet.contains("four")) - - val theMap = mapOf(1 to "one", 2 to "two", 3 to "three") - assertEquals(theMap[2], "two") - - val theMutableMap = mutableMapOf(1 to "one", 2 to "two", 3 to "three") - theMutableMap[4] = "four" - assertEquals(theMutableMap[4], "four") - } - - @Test - fun whenSliceCollection_thenSuccess() { - val theList = listOf("one", "two", "three") - val resultList = theList.slice(1..2) - - assertEquals(2, resultList.size) - assertTrue(resultList.contains("two")) - } - - @Test - fun whenJoinTwoCollections_thenSuccess() { - val firstList = listOf("one", "two", "three") - val secondList = listOf("four", "five", "six") - val resultList = firstList + secondList - - assertEquals(6, resultList.size) - assertTrue(resultList.contains("two")) - assertTrue(resultList.contains("five")) - } - - @Test - fun whenFilterNullValues_thenSuccess() { - val theList = listOf("one", null, "two", null, "three") - val resultList = theList.filterNotNull() - - assertEquals(3, resultList.size) - } - - @Test - fun whenFilterNonPositiveValues_thenSuccess() { - val theList = listOf(1, 2, -3, -4, 5, -6) - val resultList = theList.filter { it > 0 } - //val resultList = theList.filter{ x -> x > 0} - - assertEquals(3, resultList.size) - assertTrue(resultList.contains(1)) - assertFalse(resultList.contains(-4)) - } - - @Test - fun whenDropFirstItems_thenRemoved() { - val theList = listOf("one", "two", "three", "four") - val resultList = theList.drop(2) - - assertEquals(2, resultList.size) - assertFalse(resultList.contains("one")) - assertFalse(resultList.contains("two")) - } - - @Test - fun whenDropFirstItemsBasedOnCondition_thenRemoved() { - val theList = listOf("one", "two", "three", "four") - val resultList = theList.dropWhile { it.length < 4 } - - assertEquals(2, resultList.size) - assertFalse(resultList.contains("one")) - assertFalse(resultList.contains("two")) - } - - @Test - fun whenExcludeItems_thenRemoved() { - val firstList = listOf("one", "two", "three") - val secondList = listOf("one", "three") - val resultList = firstList - secondList - - assertEquals(1, resultList.size) - assertTrue(resultList.contains("two")) - } - - @Test - fun whenSearchForExistingItem_thenFound() { - val theList = listOf("one", "two", "three") - - assertTrue("two" in theList) - } - - @Test - fun whenGroupItems_thenSuccess() { - val theList = listOf(1, 2, 3, 4, 5, 6) - val resultMap = theList.groupBy { it % 3 } - - assertEquals(3, resultMap.size) - print(resultMap[1]) - assertTrue(resultMap[1]!!.contains(1)) - assertTrue(resultMap[2]!!.contains(5)) - } - - @Test - fun whenApplyFunctionToAllItems_thenSuccess() { - val theList = listOf(1, 2, 3, 4, 5, 6) - val resultList = theList.map { it * it } - print(resultList) - assertEquals(4, resultList[1]) - assertEquals(9, resultList[2]) - } - - @Test - fun whenApplyMultiOutputFunctionToAllItems_thenSuccess() { - val theList = listOf("John", "Tom") - val resultList = theList.flatMap { it.toLowerCase().toList() } - print(resultList) - assertEquals(7, resultList.size) - assertTrue(resultList.contains('j')) - } - - @Test - fun whenApplyFunctionToAllItemsWithStartingValue_thenSuccess() { - val theList = listOf(1, 2, 3, 4, 5, 6) - val finalResult = theList.fold(1000, { oldResult, currentItem -> oldResult + (currentItem * currentItem) }) - print(finalResult) - assertEquals(1091, finalResult) - } - - @Test - fun whenApplyingChunked_thenShouldBreakTheCollection() { - val theList = listOf(1, 2, 3, 4, 5) - val chunked = theList.chunked(2) - - assertThat(chunked.size).isEqualTo(3) - assertThat(chunked.first()).contains(1, 2) - assertThat(chunked[1]).contains(3, 4) - assertThat(chunked.last()).contains(5) - } - - @Test - fun whenApplyingChunkedWithTransformation_thenShouldBreakTheCollection() { - val theList = listOf(1, 2, 3, 4, 5) - val chunked = theList.chunked(3) { it.joinToString(", ") } - - assertThat(chunked.size).isEqualTo(2) - assertThat(chunked.first()).isEqualTo("1, 2, 3") - assertThat(chunked.last()).isEqualTo("4, 5") - } - - @Test - fun whenApplyingWindowed_thenShouldCreateSlidingWindowsOfElements() { - val theList = (1..6).toList() - val windowed = theList.windowed(3) - - assertThat(windowed.size).isEqualTo(4) - assertThat(windowed.first()).contains(1, 2, 3) - assertThat(windowed[1]).contains(2, 3, 4) - assertThat(windowed[2]).contains(3, 4, 5) - assertThat(windowed.last()).contains(4, 5, 6) - } - - @Test - fun whenApplyingWindowedWithTwoSteps_thenShouldCreateSlidingWindowsOfElements() { - val theList = (1..6).toList() - val windowed = theList.windowed(size = 3, step = 2) - - assertThat(windowed.size).isEqualTo(2) - assertThat(windowed.first()).contains(1, 2, 3) - assertThat(windowed.last()).contains(3, 4, 5) - } - - @Test - fun whenApplyingPartialWindowedWithTwoSteps_thenShouldCreateSlidingWindowsOfElements() { - val theList = (1..6).toList() - val windowed = theList.windowed(size = 3, step = 2, partialWindows = true) - - assertThat(windowed.size).isEqualTo(3) - assertThat(windowed.first()).contains(1, 2, 3) - assertThat(windowed[1]).contains(3, 4, 5) - assertThat(windowed.last()).contains(5, 6) - } - - @Test - fun whenApplyingTransformingWindows_thenShouldCreateSlidingWindowsOfElements() { - val theList = (1..6).toList() - val windowed = theList.windowed(size = 3, step = 2, partialWindows = true) { it.joinToString(", ") } - - assertThat(windowed.size).isEqualTo(3) - assertThat(windowed.first()).isEqualTo("1, 2, 3") - assertThat(windowed[1]).isEqualTo("3, 4, 5") - assertThat(windowed.last()).isEqualTo("5, 6") - } -} diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/AssociateUnitTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/AssociateUnitTest.kt deleted file mode 100644 index 68f7040c4c..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/AssociateUnitTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.baeldung.collections.transformations - -import org.junit.Assert.assertEquals -import org.junit.Test - -class AssociateUnitTest { - @Test - fun testToMap() { - val input = listOf(Pair("one", 1), Pair("two", 2)) - val map = input.toMap() - assertEquals(mapOf("one" to 1, "two" to 2), map) - } - - @Test - fun testAssociateWith() { - val inputs = listOf("Hi", "there") - val map = inputs.associateWith { k -> k.length } - assertEquals(mapOf("Hi" to 2, "there" to 5), map) - } - - @Test - fun testAssociateBy() { - val inputs = listOf("Hi", "there") - val map = inputs.associateBy { v -> v.length } - assertEquals(mapOf(2 to "Hi", 5 to "there"), map) - } - - @Test - fun testAssociate() { - val inputs = listOf("Hi", "there") - val map = inputs.associate { e -> Pair(e.toUpperCase(), e.reversed()) } - assertEquals(mapOf("HI" to "iH", "THERE" to "ereht"), map) - } - - @Test - fun testAssociateByDuplicateKeys() { - val inputs = listOf("one", "two") - val map = inputs.associateBy { v -> v.length } - assertEquals(mapOf(3 to "two"), map) - } - - @Test - fun testGroupBy() { - val inputs = listOf("one", "two", "three") - val map = inputs.groupBy { v -> v.length } - assertEquals(mapOf(3 to listOf("one", "two"), 5 to listOf("three")), map) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/FilterUnitTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/FilterUnitTest.kt deleted file mode 100644 index 591577e4f3..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/FilterUnitTest.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.baeldung.collections.transformations - -import org.junit.Assert.assertEquals -import org.junit.Test - -class FilterUnitTest { - @Test - fun testFilterWithLambda() { - val input = listOf(1, 2, 3, 4, 5) - val filtered = input.filter { it <= 3 } - assertEquals(listOf(1, 2, 3), filtered) - } - - @Test - fun testFilterWithMethodReference() { - val input = listOf(1, 2, 3, 4, 5) - val filtered = input.filter(this::isSmall) - assertEquals(listOf(1, 2, 3), filtered) - } - - @Test - fun testFilterNotWithMethodReference() { - val input = listOf(1, 2, 3, 4, 5) - val filtered = input.filterNot(this::isSmall) - assertEquals(listOf(4, 5), filtered) - } - - @Test - fun testFilterIndexed() { - val input = listOf(5, 4, 3, 2, 1) - val filtered = input.filterIndexed { index, element -> index < 3 } - assertEquals(listOf(5, 4, 3), filtered) - } - - @Test - fun testFilterNotNull() { - val nullable: List = listOf("Hello", null, "World") - val nonnull: List = nullable.filterNotNull() - assertEquals(listOf("Hello", "World"), nonnull) - } - - private fun isSmall(i: Int) = i <= 3 -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/FlattenUnitTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/FlattenUnitTest.kt deleted file mode 100644 index 69fbceb8e3..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/FlattenUnitTest.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.collections.transformations - -import org.junit.Assert.assertEquals -import org.junit.Test - -class FlattenUnitTest { - @Test - fun testFlatten() { - val inputs = listOf("one", "two", "three") - val characters = inputs.map(String::toList) - val flattened = characters.flatten(); - assertEquals(listOf('o', 'n', 'e', 't', 'w', 'o', 't', 'h', 'r', 'e', 'e'), flattened) - } - - @Test - fun testFlatMap() { - val inputs = listOf("one", "two", "three") - val characters = inputs.flatMap(String::toList) - assertEquals(listOf('o', 'n', 'e', 't', 'w', 'o', 't', 'h', 'r', 'e', 'e'), characters) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/JoinToUnitTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/JoinToUnitTest.kt deleted file mode 100644 index 2ac0cdca50..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/JoinToUnitTest.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.baeldung.collections.transformations - -import org.junit.Assert.assertEquals -import org.junit.Test - -class JoinToUnitTest { - @Test - fun testJoinToString() { - val inputs = listOf("Jan", "Feb", "Mar", "Apr", "May") - - val simpleString = inputs.joinToString() - assertEquals("Jan, Feb, Mar, Apr, May", simpleString) - - val detailedString = inputs.joinToString(separator = ",", prefix="Months: ", postfix=".") - assertEquals("Months: Jan,Feb,Mar,Apr,May.", detailedString) - } - - @Test - fun testJoinToStringLimits() { - val inputs = listOf("Jan", "Feb", "Mar", "Apr", "May") - - val simpleString = inputs.joinToString(limit = 3) - assertEquals("Jan, Feb, Mar, ...", simpleString) - } - - @Test - fun testJoinToStringTransform() { - val inputs = listOf("Jan", "Feb", "Mar", "Apr", "May") - - val simpleString = inputs.joinToString(transform = String::toUpperCase) - assertEquals("JAN, FEB, MAR, APR, MAY", simpleString) - } - - @Test - fun testJoinTo() { - val inputs = listOf("Jan", "Feb", "Mar", "Apr", "May") - - val output = StringBuilder() - output.append("My ") - .append(inputs.size) - .append(" elements: ") - inputs.joinTo(output) - - assertEquals("My 5 elements: Jan, Feb, Mar, Apr, May", output.toString()) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/MapUnitTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/MapUnitTest.kt deleted file mode 100644 index e22fcbe903..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/MapUnitTest.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.baeldung.collections.transformations - -import org.junit.Assert.assertEquals -import org.junit.Test - -class MapUnitTest { - @Test - fun testMapWithLambda() { - val input = listOf("one", "two", "three") - - val reversed = input.map { it.reversed() } - assertEquals(listOf("eno", "owt", "eerht"), reversed) - - val lengths = input.map { it.length } - assertEquals(listOf(3, 3, 5), lengths) - } - - @Test - fun testMapIndexed() { - val input = listOf(3, 2, 1) - val result = input.mapIndexed { index, value -> index * value } - assertEquals(listOf(0, 2, 2), result) - } - - @Test - fun testMapNotNull() { - val input = listOf(1, 2, 3, 4, 5) - val smallSquares = input.mapNotNull { - if (it <= 3) { - it * it - } else { - null - } - } - assertEquals(listOf(1, 4, 9), smallSquares) - } - - @Test - fun mapMapKeys() { - val inputs = mapOf("one" to 1, "two" to 2, "three" to 3) - - val uppercases = inputs.mapKeys { it.key.toUpperCase() } - assertEquals(mapOf("ONE" to 1, "TWO" to 2, "THREE" to 3), uppercases) - } - - @Test - fun mapMapValues() { - val inputs = mapOf("one" to 1, "two" to 2, "three" to 3) - - val squares = inputs.mapValues { it.value * it.value } - assertEquals(mapOf("one" to 1, "two" to 4, "three" to 9), squares) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/ReduceUnitTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/ReduceUnitTest.kt deleted file mode 100644 index 6821b7cdb9..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/ReduceUnitTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.collections.transformations - -import org.junit.Assert.assertEquals -import org.junit.Test - -class ReduceUnitTest { - @Test - fun testJoinToStringAsReduce() { - val inputs = listOf("Jan", "Feb", "Mar", "Apr", "May") - - val result = inputs.reduce { acc, next -> "$acc, $next" } - assertEquals("Jan, Feb, Mar, Apr, May", result) - } - - @Test - fun testFoldToLength() { - val inputs = listOf("Jan", "Feb", "Mar", "Apr", "May") - - val result = inputs.fold(0) { acc, next -> acc + next.length } - assertEquals(15, result) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/ZipUnitTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/ZipUnitTest.kt deleted file mode 100644 index 66aeeceef4..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/collections/transformations/ZipUnitTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.baeldung.collections.transformations - -import org.junit.Assert.assertEquals -import org.junit.Test - -class ZipUnitTest { - @Test - fun testZip() { - val left = listOf("one", "two", "three") - val right = listOf(1, 2, 3) - val zipped = left.zip(right) - assertEquals (listOf(Pair("one", 1), Pair("two", 2), Pair("three", 3)), zipped) - } - - @Test - fun testZipShort() { - val left = listOf("one", "two") - val right = listOf(1, 2, 3) - val zipped = left.zip(right) - assertEquals (listOf(Pair("one", 1), Pair("two", 2)), zipped) - } - - @Test - fun testUnzip() { - val left = listOf("one", "two", "three") - val right = listOf(1, 2, 3) - val zipped = left.zip(right) - - val (newLeft, newRight) = zipped.unzip() - assertEquals(left, newLeft) - assertEquals(right, newRight) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/ChunkedTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/ChunkedTest.kt deleted file mode 100644 index 20797cc633..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/ChunkedTest.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.baeldung.filter - -import org.junit.jupiter.api.Assertions.assertIterableEquals -import org.junit.jupiter.api.Test - -internal class ChunkedTest { - - @Test - fun givenDNAFragmentString_whenChunking_thenProduceListOfChunks() { - val dnaFragment = "ATTCGCGGCCGCCAA" - - val fragments = dnaFragment.chunked(3) - - assertIterableEquals(listOf("ATT", "CGC", "GGC", "CGC", "CAA"), fragments) - } - - @Test - fun givenDNAString_whenChunkingWithTransformer_thenProduceTransformedList() { - val codonTable = mapOf("ATT" to "Isoleucine", "CAA" to "Glutamine", "CGC" to "Arginine", "GGC" to "Glycine") - val dnaFragment = "ATTCGCGGCCGCCAA" - - val proteins = dnaFragment.chunked(3) { codon -> - codonTable[codon.toString()] ?: error("Unknown codon") - } - - assertIterableEquals(listOf("Isoleucine", "Arginine", "Glycine", "Arginine", "Glutamine"), proteins) - } - - @Test - fun givenListOfValues_whenChunking_thenProduceListOfArrays() { - val whole = listOf(1, 4, 7, 4753, 2, 34, 62, 76, 5868, 0) - val chunks = whole.chunked(6) - - val expected = listOf(listOf(1, 4, 7, 4753, 2, 34), listOf(62, 76, 5868, 0)) - - assertIterableEquals(expected, chunks) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/DistinctTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/DistinctTest.kt deleted file mode 100644 index 4cc6f647e1..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/DistinctTest.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.baeldung.filter - -import org.junit.jupiter.api.Assertions.assertIterableEquals -import org.junit.jupiter.api.Test - -internal class DistinctTest { - data class SmallClass(val key: String, val num: Int) - - @Test - fun whenApplyingDistinct_thenReturnListOfNoDuplicateValues() { - val array = arrayOf(1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 5, 6, 7, 8, 9) - val result = array.distinct() - val expected = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9) - - assertIterableEquals(expected, result) - } - - @Test - fun givenArrayOfClassObjects_whenApplyingDistinctOnClassProperty_thenReturnListDistinctOnThatValue() { - - val original = arrayOf( - SmallClass("key1", 1), - SmallClass("key2", 2), - SmallClass("key3", 3), - SmallClass("key4", 3), - SmallClass("er", 9), - SmallClass("er", 10), - SmallClass("er", 11)) - - val actual = original.distinctBy { it.key } - - val expected = listOf( - SmallClass("key1", 1), - SmallClass("key2", 2), - SmallClass("key3", 3), - SmallClass("key4", 3), - SmallClass("er", 9)) - - - assertIterableEquals(expected, actual) - } - - @Test - fun givenArrayOfClassObjects_whenApplyingComplicatedSelector_thenReturnFirstElementToMatchEachSelectorValue() { - val array = arrayOf( - SmallClass("key1", 1), - SmallClass("key2", 2), - SmallClass("key3", 3), - SmallClass("key4", 3), - SmallClass("er", 9), - SmallClass("er", 10), - SmallClass("er", 11), - SmallClass("er", 11), - SmallClass("er", 91), - SmallClass("blob", 22), - SmallClass("dob", 27), - SmallClass("high", 201_434_314)) - - val actual = array.distinctBy { Math.floor(it.num / 10.0) } - - val expected = listOf( - SmallClass("key1", 1), - SmallClass("er", 10), - SmallClass("er", 91), - SmallClass("blob", 22), - SmallClass("high", 201_434_314)) - - assertIterableEquals(expected, actual) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/DropTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/DropTest.kt deleted file mode 100644 index 7c2685f39b..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/DropTest.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.baeldung.filter - -import org.junit.jupiter.api.Assertions.assertIterableEquals -import org.junit.jupiter.api.Test - -internal class DropTest { - - @Test - fun whenDroppingFirstTwoItemsOfArray_thenTwoLess() { - val array = arrayOf(1, 2, 3, 4) - val result = array.drop(2) - val expected = listOf(3, 4) - - assertIterableEquals(expected, result) - } - - @Test - fun whenDroppingMoreItemsOfArray_thenEmptyList() { - val array = arrayOf(1, 2, 3, 4) - val result = array.drop(5) - val expected = listOf() - - assertIterableEquals(expected, result) - } - - @Test - fun givenArray_whenDroppingLastElement_thenReturnListWithoutLastElement() { - val array = arrayOf("1", "2", "3", "4") - val result = array.dropLast(1) - val expected = listOf("1", "2", "3") - - assertIterableEquals(expected, result) - } - - @Test - fun givenArrayOfFloats_whenDroppingLastUntilPredicateIsFalse_thenReturnSubsetListOfFloats() { - val array = arrayOf(1f, 1f, 1f, 1f, 1f, 2f, 1f, 1f, 1f) - val result = array.dropLastWhile { it == 1f } - val expected = listOf(1f, 1f, 1f, 1f, 1f, 2f) - - assertIterableEquals(expected, result) - } - - @Test - fun givenList_whenDroppingMoreThanAvailable_thenThrowException() { - val list = listOf('a', 'e', 'i', 'o', 'u') - val result = list.drop(6) - val expected: List = listOf() - - assertIterableEquals(expected, result) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/FilterTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/FilterTest.kt deleted file mode 100644 index efe6354f25..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/FilterTest.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.baeldung.filter - -import org.apache.commons.math3.primes.Primes -import org.junit.jupiter.api.Assertions.assertIterableEquals -import org.junit.jupiter.api.Test -import kotlin.test.assertTrue - -internal class FilterTest { - - @Test - fun givenAscendingValueMap_whenFilteringOnValue_ThenReturnSubsetOfMap() { - val originalMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3) - val filteredMap = originalMap.filter { it.value < 2 } - val expectedMap = mapOf("key1" to 1) - - assertTrue { expectedMap == filteredMap } - } - - @Test - fun givenSeveralCollections_whenFilteringToAccumulativeList_thenListContainsAllContents() { - val array1 = arrayOf(90, 92, 93, 94, 92, 95, 93) - val array2 = sequenceOf(51, 31, 83, 674_506_111, 256_203_161, 15_485_863) - val list1 = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9) - val primes = mutableListOf() - - val expected = listOf(2, 3, 5, 7, 31, 83, 15_485_863, 256_203_161, 674_506_111) - - val primeCheck = { num: Int -> Primes.isPrime(num) } - - array1.filterTo(primes, primeCheck) - list1.filterTo(primes, primeCheck) - array2.filterTo(primes, primeCheck) - - primes.sort() - - assertIterableEquals(expected, primes) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/SliceTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/SliceTest.kt deleted file mode 100644 index 793fe68427..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/SliceTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.baeldung.filter - -import org.junit.jupiter.api.Assertions.assertIterableEquals -import org.junit.jupiter.api.Assertions.assertThrows -import org.junit.jupiter.api.Test - -internal class SliceTest { - - @Test - fun whenSlicingAnArrayWithDotRange_ThenListEqualsTheSlice() { - val original = arrayOf(1, 2, 3, 2, 1) - val actual = original.slice(1..3) - val expected = listOf(2, 3, 2) - - assertIterableEquals(expected, actual) - } - - @Test - fun whenSlicingAnArrayWithDownToRange_thenListMadeUpOfReverseSlice() { - val original = arrayOf(1, 2, 3, 2, 1) - val actual = original.slice(3 downTo 0) - val expected = listOf(2, 3, 2, 1) - - assertIterableEquals(expected, actual) - } - -// From the 1.3 version of Kotlin APIs, slice doesn't return array of nulls but throw IndexOutOfBoundsException -// @Test -// fun whenSlicingBeyondTheRangeOfTheArray_thenContainManyNulls() { -// val original = arrayOf(12, 3, 34, 4) -// val actual = original.slice(3..8) -// val expected = listOf(4, null, null, null, null, null) -// -// assertIterableEquals(expected, actual) -// } - - @Test - fun whenSlicingBeyondRangeOfArrayWithStep_thenOutOfBoundsException() { - assertThrows(ArrayIndexOutOfBoundsException::class.java) { - val original = arrayOf(12, 3, 34, 4) - original.slice(3..8 step 2) - } - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/TakeTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/TakeTest.kt deleted file mode 100644 index d021177de8..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/filter/TakeTest.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.baeldung.filter - -import org.junit.jupiter.api.Assertions.assertIterableEquals -import org.junit.jupiter.api.Test - -internal class TakeTest { - - @Test - fun `given array of alternating types, when predicating on 'is String', then produce list of array up until predicate is false`() { - val originalArray = arrayOf("val1", 2, "val3", 4, "val5", 6) - val actualList = originalArray.takeWhile { it is String } - val expectedList = listOf("val1") - - assertIterableEquals(expectedList, actualList) - } - - @Test - fun `given array of alternating types, when taking 4 items, then produce list of first 4 items`() { - val originalArray = arrayOf("val1", 2, "val3", 4, "val5", 6) - val actualList = originalArray.take(4) - val expectedList = listOf("val1", 2, "val3", 4) - - println(originalArray.drop(4)) - println(actualList) - - assertIterableEquals(expectedList, actualList) - } - - @Test - fun `when taking more items than available, then return all elements`() { - val originalArray = arrayOf(1, 2) - val actual = originalArray.take(10) - val expected = listOf(1, 2) - - assertIterableEquals(expected, actual) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/findelement/FindAnElementInAListUnitTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/findelement/FindAnElementInAListUnitTest.kt deleted file mode 100644 index 52e7e2a5b5..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/findelement/FindAnElementInAListUnitTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.baeldung.findelement - -import org.junit.jupiter.api.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -class FindAnElementInAListUnitTest { - - var batmans: List = listOf("Christian Bale", "Michael Keaton", "Ben Affleck", "George Clooney") - - @Test - fun whenFindASpecificItem_thenItemIsReturned() { - //Returns the first element matching the given predicate, or null if no such element was found. - val theFirstBatman = batmans.find { actor -> "Michael Keaton".equals(actor) } - assertEquals(theFirstBatman, "Michael Keaton") - } - - @Test - fun whenFilterWithPredicate_thenMatchingItemsAreReturned() { - //Returns a list containing only elements matching the given predicate. - val theCoolestBatmans = batmans.filter { actor -> actor.contains("a") } - assertTrue(theCoolestBatmans.contains("Christian Bale") && theCoolestBatmans.contains("Michael Keaton")) - } - - @Test - fun whenFilterNotWithPredicate_thenMatchingItemsAreReturned() { - //Returns a list containing only elements not matching the given predicate. - val theMehBatmans = batmans.filterNot { actor -> actor.contains("a") } - assertFalse(theMehBatmans.contains("Christian Bale") && theMehBatmans.contains("Michael Keaton")) - assertTrue(theMehBatmans.contains("Ben Affleck") && theMehBatmans.contains("George Clooney")) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/foldvsreduce/FoldAndReduceTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/foldvsreduce/FoldAndReduceTest.kt deleted file mode 100644 index 7b263914c6..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/foldvsreduce/FoldAndReduceTest.kt +++ /dev/null @@ -1,59 +0,0 @@ -package com.baeldung.foldvsreduce - -import org.junit.Test -import org.junit.jupiter.api.assertThrows -import java.lang.RuntimeException -import kotlin.test.assertEquals - -class FoldAndReduceTest { - - @Test - fun testReduceLimitations() { - val numbers: List = listOf(1, 2, 3) - val sum: Number = numbers.reduce { acc, next -> acc + next } - assertEquals(6, sum) - - val emptyList = listOf() - assertThrows { emptyList.reduce { acc, next -> acc + next } } - - // doesn't compile - // val sum = numbers.reduce { acc, next -> acc.toLong() + next.toLong()} - } - - @Test - fun testFold() { - - val numbers: List = listOf(1, 2, 3) - val sum: Int = numbers.fold(0, { acc, next -> acc + next }) - assertEquals(6, sum) - - //change result type - val sumLong: Long = numbers.fold(0L, { acc, next -> acc + next.toLong() }) - assertEquals(6L, sumLong) - - val emptyList = listOf() - val emptySum = emptyList.fold(0, { acc, next -> acc + next }) - assertEquals(0, emptySum) - - //power of changing result type - val (even, odd) = numbers.fold(Pair(listOf(), listOf()), { acc, next -> - if (next % 2 == 0) Pair(acc.first + next, acc.second) - else Pair(acc.first, acc.second + next) - }) - - assertEquals(listOf(2), even) - assertEquals(listOf(1, 3), odd) - } - - @Test - fun testVariationsOfFold() { - val numbers = listOf(1, 2, 3) - val reversed = numbers.foldRight(listOf(), { next, acc -> acc + next}) - assertEquals(listOf(3,2,1), reversed) - - val reversedIndexes = numbers.foldRightIndexed(listOf(), { i, _, acc -> acc + i }) - assertEquals(listOf(2,1,0), reversedIndexes) - } - - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/kotlin/collections/ListExampleUnitTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/kotlin/collections/ListExampleUnitTest.kt deleted file mode 100644 index 71fe3bf1e0..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/kotlin/collections/ListExampleUnitTest.kt +++ /dev/null @@ -1,126 +0,0 @@ -package com.baeldung.kotlin.collections - -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.Assertions.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -class ListExampleUnitTest { - - private val classUnderTest: ListExample = ListExample() - - @Test - fun whenListIsCreated_thenContainsElements() { - assertTrue(classUnderTest.createList().contains("India")) - assertTrue(classUnderTest.createMutableList().contains("Seoul")) - } - - @Test - fun whenIterateUsingForEachLoop_thenSuccess() { - assertEquals(7, classUnderTest.iterateUsingForEachLoop()[0]) - } - - @Test - fun whenIterateUsingForLoop_thenSuccess() { - assertEquals(5, classUnderTest.iterateUsingForLoop()[1]) - } - - @Test - fun whenIterateUsingForLoopRange_thenSuccess() { - assertEquals(6, classUnderTest.iterateUsingForLoopRange()[3]) - } - - @Test - fun whenIterateUsingForEachIndexedLoop_thenSuccess() { - assertEquals(9, classUnderTest.iterateUsingForEachIndexedLoop()[4]) - } - - @Test - fun whenRetrieveElementsInList_thenSuccess() { - assertEquals("Japan", classUnderTest.retrieveElementsInList()) - } - - @Test - fun whenRetrieveElementsUsingGet_thenSuccess() { - assertEquals("Brazil", classUnderTest.retrieveElementsUsingGet()) - } - - @Test - fun whenRetrieveElementsFirstAndLast_thenSuccess() { - assertEquals("Australia", classUnderTest.retrieveElementsFirstAndLast()) - } - - @Test - fun whenRetrieveSubList_thenSuccess() { - assertEquals(3, classUnderTest.retrieveSubList().size) - } - - @Test - fun whenRetrieveListSliceUsingIndices_thenSuccess() { - assertEquals(4, classUnderTest.retrieveListSliceUsingIndices().size) - } - - @Test - fun whenRetrieveListSliceUsingIndicesList_thenSuccess() { - assertEquals(2, classUnderTest.retrieveListSliceUsingIndicesList().size) - } - - @Test - fun whenCountList_thenSuccess() { - assertEquals(5, classUnderTest.countList()) - } - - @Test - fun whenCountListUsingPredicate_thenSuccess() { - assertEquals(3, classUnderTest.countListUsingPredicate()) - } - - @Test - fun whenCountListUsingProperty_thenSuccess() { - assertEquals(5, classUnderTest.countListUsingProperty()) - } - - @Test - fun whenAddToList_thenSuccess() { - assertEquals(11, classUnderTest.addToList().count()) - } - - @Test - fun whenRemoveFromList_thenSuccess() { - val list = classUnderTest.removeFromList() - assertEquals(3, list.size) - assertEquals("Sao Paulo", list[1]) - } - - @Test - fun whenReplaceFromList_thenSuccess() { - val list = classUnderTest.replaceFromList() - assertEquals(5, list.size) - assertEquals("Barcelona", list[1]) - } - - @Test - fun whenSortMutableList_thenSuccess() { - assertEquals("Sydney", classUnderTest.sortMutableList()[0]) - } - - @Test - fun whenSortList_thenSuccess() { - assertEquals("India", classUnderTest.sortList()[1]) - } - - @Test - fun whenCheckOneElementInList_thenSuccess() { - assertTrue(classUnderTest.checkOneElementInList()) - } - - @Test - fun whenCheckOneElementInListUsingOperator_thenSuccess() { - assertFalse(classUnderTest.checkOneElementInListUsingOperator()) - } - - @Test - fun whenCheckElementsInList_thenSuccess() { - assertTrue(classUnderTest.checkElementsInList()) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/listtomap/ListToMapTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/listtomap/ListToMapTest.kt deleted file mode 100644 index 93e4f11fdf..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/listtomap/ListToMapTest.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.baeldung.listtomap - -import org.junit.Test -import kotlin.test.assertTrue - -class ListToMapTest { - - val user1 = User("John", 18, listOf("Hiking, Swimming")) - val user2 = User("Sara", 25, listOf("Chess, Board Games")) - val user3 = User("Dave", 34, listOf("Games, Racing sports")) - val user4 = User("John", 30, listOf("Reading, Poker")) - - @Test - fun givenList_whenConvertToMap_thenResult() { - val myList = listOf(user1, user2, user3) - val myMap = myList.map { it.name to it.age }.toMap() - - assertTrue(myMap.get("John") == 18) - } - - @Test - fun givenList_whenAssociatedBy_thenResult() { - val myList = listOf(user1, user2, user3) - val myMap = myList.associateBy({ it.name }, { it.hobbies }) - - assertTrue(myMap.get("John")!!.contains("Hiking, Swimming")) - } - - @Test - fun givenStringList_whenConvertToMap_thenResult() { - val myList = listOf("a", "b", "c") - val myMap = myList.map { it to it }.toMap() - - assertTrue(myMap.get("a") == "a") - } - - @Test - fun givenStringList_whenAssociate_thenResult() { - val myList = listOf("a", "b", "c", "c", "b") - val myMap = myList.associate{ it to it } - - assertTrue(myMap.get("a") == "a") - } - - @Test - fun givenStringList_whenAssociateTo_thenResult() { - val myList = listOf("a", "b", "c", "c", "b") - val myMap = mutableMapOf() - - myList.associateTo(myMap) {it to it} - - assertTrue(myMap.get("a") == "a") - } - - @Test - fun givenStringList_whenAssociateByTo_thenResult() { - val myList = listOf(user1, user2, user3, user4) - val myMap = mutableMapOf() - - myList.associateByTo(myMap, {it.name}, {it.age}) - - assertTrue(myMap.get("Dave") == 34) - } - - @Test - fun givenStringList_whenAssociateByToUser_thenResult() { - val myList = listOf(user1, user2, user3, user4) - val myMap = mutableMapOf() - - myList.associateByTo(myMap) {it.name} - - assertTrue(myMap.get("Dave")!!.age == 34) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/listtomap/User.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/listtomap/User.kt deleted file mode 100644 index 89eb9ac701..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/listtomap/User.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.listtomap - -data class User(val name: String, val age: Int, val hobbies: List) diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/sorting/SortingExampleKtTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/sorting/SortingExampleKtTest.kt deleted file mode 100644 index 7ac0efa4ef..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/sorting/SortingExampleKtTest.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.sorting - -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test - -class SortingExampleKtTest { - - @Test - fun naturalOrderComparator_ShouldBeAscendingTest() { - val resultingList = listOf(1, 5, 6, 6, 2, 3, 4).sortedWith(getSimpleComparator()) - assertTrue(listOf(1, 2, 3, 4, 5, 6, 6) == resultingList) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/splitlist/SplitListIntoPartsTest.kt b/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/splitlist/SplitListIntoPartsTest.kt deleted file mode 100644 index 627c7eaacf..0000000000 --- a/core-kotlin-modules/core-kotlin-collections/src/test/kotlin/com/baeldung/splitlist/SplitListIntoPartsTest.kt +++ /dev/null @@ -1,99 +0,0 @@ -package com.baeldung.splitlist - -import org.junit.jupiter.api.Test -import kotlin.test.assertEquals - -class SplitListIntoPartsTest { - private val evenList = listOf(0, "a", 1, "b", 2, "c"); - - private val unevenList = listOf(0, "a", 1, "b", 2, "c", 3); - - private fun verifyList(resultList: List>) { - assertEquals("[[0, a], [1, b], [2, c]]", resultList.toString()) - } - - private fun verifyPartialList(resultList: List>) { - assertEquals("[[0, a], [1, b], [2, c], [3]]", resultList.toString()) - } - - @Test - fun whenChunked_thenListIsSplit() { - val resultList = evenList.chunked(2) - verifyList(resultList) - } - - @Test - fun whenUnevenChunked_thenListIsSplit() { - val resultList = unevenList.chunked(2) - verifyPartialList(resultList) - } - - @Test - fun whenWindowed_thenListIsSplit() { - val resultList = evenList.windowed(2, 2) - verifyList(resultList) - } - - @Test - fun whenUnevenPartialWindowed_thenListIsSplit() { - val resultList = unevenList.windowed(2, 2, partialWindows = true) - verifyPartialList(resultList) - } - - @Test - fun whenUnevenWindowed_thenListIsSplit() { - val resultList = unevenList.windowed(2, 2, partialWindows = false) - verifyList(resultList) - } - - @Test - fun whenGroupByWithAscendingNumbers_thenListIsSplit() { - val numberList = listOf(1, 2, 3, 4, 5, 6); - val resultList = numberList.groupBy { (it + 1) / 2 } - assertEquals("[[1, 2], [3, 4], [5, 6]]", resultList.values.toString()) - assertEquals("[1, 2, 3]", resultList.keys.toString()) - } - - @Test - fun whenGroupByWithAscendingNumbersUneven_thenListIsSplit() { - val numberList = listOf(1, 2, 3, 4, 5, 6, 7); - val resultList = numberList.groupBy { (it + 1) / 2 }.values - assertEquals("[[1, 2], [3, 4], [5, 6], [7]]", resultList.toString()) - } - - @Test - fun whenGroupByWithRandomNumbers_thenListIsSplitInWrongWay() { - val numberList = listOf(1, 3, 8, 20, 23, 30); - val resultList = numberList.groupBy { (it + 1) / 2 } - assertEquals("[[1], [3], [8], [20], [23], [30]]", resultList.values.toString()) - assertEquals("[1, 2, 4, 10, 12, 15]", resultList.keys.toString()) - } - - @Test - fun whenWithIndexGroupBy_thenListIsSplit() { - val resultList = evenList.withIndex() - .groupBy { it.index / 2 } - .map { it.value.map { it.value } } - verifyList(resultList) - } - - @Test - fun whenWithIndexGroupByUneven_thenListIsSplit() { - val resultList = unevenList.withIndex() - .groupBy { it.index / 2 } - .map { it.value.map { it.value } } - verifyPartialList(resultList) - } - - @Test - fun whenFoldIndexed_thenListIsSplit() { - val resultList = evenList.foldIndexed(ArrayList>(evenList.size / 2)) { index, acc, item -> - if (index % 2 == 0) { - acc.add(ArrayList(2)) - } - acc.last().add(item) - acc - } - verifyList(resultList) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-concurrency/README.md b/core-kotlin-modules/core-kotlin-concurrency/README.md deleted file mode 100644 index 09d9055a2b..0000000000 --- a/core-kotlin-modules/core-kotlin-concurrency/README.md +++ /dev/null @@ -1,7 +0,0 @@ -## Core Kotlin Concurrency - -This module contains articles about concurrency in Kotlin. - -### Relevant articles: -- [Threads vs Coroutines in Kotlin](https://www.baeldung.com/kotlin-threads-coroutines) -- [Introduction to Kotlin Coroutines](https://www.baeldung.com/kotlin-coroutines) diff --git a/core-kotlin-modules/core-kotlin-concurrency/pom.xml b/core-kotlin-modules/core-kotlin-concurrency/pom.xml deleted file mode 100644 index 7c3b0fb5b6..0000000000 --- a/core-kotlin-modules/core-kotlin-concurrency/pom.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - 4.0.0 - core-kotlin-concurrency - core-kotlin-concurrency - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - - - org.assertj - assertj-core - ${assertj.version} - test - - - org.jetbrains.kotlin - kotlin-test - ${kotlin.version} - test - - - - - 1.3.30 - 3.10.0 - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-concurrency/src/main/kotlin/com/baeldung/threadsvscoroutines/SimpleRunnable.kt b/core-kotlin-modules/core-kotlin-concurrency/src/main/kotlin/com/baeldung/threadsvscoroutines/SimpleRunnable.kt deleted file mode 100644 index 80ffb4077a..0000000000 --- a/core-kotlin-modules/core-kotlin-concurrency/src/main/kotlin/com/baeldung/threadsvscoroutines/SimpleRunnable.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.threadsvscoroutines - -class SimpleRunnable: Runnable { - - override fun run() { - println("${Thread.currentThread()} has run.") - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-concurrency/src/main/kotlin/com/baeldung/threadsvscoroutines/SimpleThread.kt b/core-kotlin-modules/core-kotlin-concurrency/src/main/kotlin/com/baeldung/threadsvscoroutines/SimpleThread.kt deleted file mode 100644 index 6647dac0ef..0000000000 --- a/core-kotlin-modules/core-kotlin-concurrency/src/main/kotlin/com/baeldung/threadsvscoroutines/SimpleThread.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.threadsvscoroutines - -class SimpleThread: Thread() { - - override fun run() { - println("${Thread.currentThread()} has run.") - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-concurrency/src/test/kotlin/com/baeldung/coroutines/CoroutinesUnitTest.kt b/core-kotlin-modules/core-kotlin-concurrency/src/test/kotlin/com/baeldung/coroutines/CoroutinesUnitTest.kt deleted file mode 100644 index 6b9437a8ab..0000000000 --- a/core-kotlin-modules/core-kotlin-concurrency/src/test/kotlin/com/baeldung/coroutines/CoroutinesUnitTest.kt +++ /dev/null @@ -1,178 +0,0 @@ -package com.baeldung.coroutines - -import kotlinx.coroutines.* -import org.junit.Test -import java.util.concurrent.atomic.AtomicInteger -import kotlin.system.measureTimeMillis -import kotlin.test.assertEquals -import kotlin.test.assertTrue - - -class CoroutinesTest { - - @Test - fun givenBuildSequence_whenTakeNElements_thenShouldReturnItInALazyWay() { - //given - val fibonacciSeq = sequence { - var a = 0 - var b = 1 - - yield(1) - - while (true) { - yield(a + b) - - val tmp = a + b - a = b - b = tmp - } - } - - //when - val res = fibonacciSeq.take(5).toList() - - //then - assertEquals(res, listOf(1, 1, 2, 3, 5)) - } - - @Test - fun givenLazySeq_whenTakeNElements_thenShouldReturnAllElements() { - //given - val lazySeq = sequence { - print("START ") - for (i in 1..5) { - yield(i) - print("STEP ") - } - print("END") - } - //when - val res = lazySeq.take(10).toList() - - //then - assertEquals(res, listOf(1, 2, 3, 4, 5)) - } - - @Test - fun givenAsyncCoroutine_whenStartIt_thenShouldExecuteItInTheAsyncWay() { - //given - val res = mutableListOf() - - //when - runBlocking { - val promise = launch(Dispatchers.Default) { expensiveComputation(res) } - res.add("Hello,") - promise.join() - } - - //then - assertEquals(res, listOf("Hello,", "word!")) - } - - - suspend fun expensiveComputation(res: MutableList) { - delay(1000L) - res.add("word!") - } - - @Test - fun givenHugeAmountOfCoroutines_whenStartIt_thenShouldExecuteItWithoutOutOfMemory() { - runBlocking { - //given - val counter = AtomicInteger(0) - val numberOfCoroutines = 100_000 - - //when - val jobs = List(numberOfCoroutines) { - launch(Dispatchers.Default) { - delay(1L) - counter.incrementAndGet() - } - } - jobs.forEach { it.join() } - - //then - assertEquals(counter.get(), numberOfCoroutines) - } - } - - @Test - fun givenCancellableJob_whenRequestForCancel_thenShouldQuit() { - runBlocking { - //given - val job = launch(Dispatchers.Default) { - while (isActive) { - //println("is working") - } - } - - delay(1300L) - - //when - job.cancel() - - //then cancel successfully - - } - } - - @Test(expected = CancellationException::class) - fun givenAsyncAction_whenDeclareTimeout_thenShouldFinishWhenTimedOut() { - runBlocking { - withTimeout(1300L) { - repeat(1000) { i -> - println("Some expensive computation $i ...") - delay(500L) - } - } - } - } - - @Test - fun givenHaveTwoExpensiveAction_whenExecuteThemAsync_thenTheyShouldRunConcurrently() { - runBlocking { - val delay = 1000L - val time = measureTimeMillis { - //given - val one = async(Dispatchers.Default) { someExpensiveComputation(delay) } - val two = async(Dispatchers.Default) { someExpensiveComputation(delay) } - - //when - runBlocking { - one.await() - two.await() - } - } - - //then - assertTrue(time < delay * 2) - } - } - - @Test - fun givenTwoExpensiveAction_whenExecuteThemLazy_thenTheyShouldNotConcurrently() { - runBlocking { - val delay = 1000L - val time = measureTimeMillis { - //given - val one = async(Dispatchers.Default, CoroutineStart.LAZY) { someExpensiveComputation(delay) } - val two = async(Dispatchers.Default, CoroutineStart.LAZY) { someExpensiveComputation(delay) } - - //when - runBlocking { - one.await() - two.await() - } - } - - //then - assertTrue(time > delay * 2) - } - } - - suspend fun someExpensiveComputation(delayInMilliseconds: Long) { - delay(delayInMilliseconds) - } - - -} diff --git a/core-kotlin-modules/core-kotlin-concurrency/src/test/kotlin/com/baeldung/threadsvscoroutines/CoroutineUnitTest.kt b/core-kotlin-modules/core-kotlin-concurrency/src/test/kotlin/com/baeldung/threadsvscoroutines/CoroutineUnitTest.kt deleted file mode 100644 index ff385d0869..0000000000 --- a/core-kotlin-modules/core-kotlin-concurrency/src/test/kotlin/com/baeldung/threadsvscoroutines/CoroutineUnitTest.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.baeldung.threadsvscoroutines - -import kotlinx.coroutines.* -import org.junit.jupiter.api.Test - -class CoroutineUnitTest { - - @Test - fun whenCreateCoroutineWithLaunchWithoutContext_thenRun() = runBlocking { - - val job = launch { - println("${Thread.currentThread()} has run.") - } - - } - - @Test - fun whenCreateCoroutineWithLaunchWithDefaultContext_thenRun() = runBlocking { - - val job = launch(Dispatchers.Default) { - println("${Thread.currentThread()} has run.") - } - } - - @Test - fun whenCreateCoroutineWithLaunchWithUnconfinedContext_thenRun() = runBlocking { - - val job = launch(Dispatchers.Unconfined) { - println("${Thread.currentThread()} has run.") - } - } - - @Test - fun whenCreateCoroutineWithLaunchWithDedicatedThread_thenRun() = runBlocking { - - val job = launch(newSingleThreadContext("dedicatedThread")) { - println("${Thread.currentThread()} has run.") - } - - } - - @Test - fun whenCreateAsyncCoroutine_thenRun() = runBlocking { - - val deferred = async(Dispatchers.IO) { - return@async "${Thread.currentThread()} has run." - } - - val result = deferred.await() - println(result) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-concurrency/src/test/kotlin/com/baeldung/threadsvscoroutines/ThreadUnitTest.kt b/core-kotlin-modules/core-kotlin-concurrency/src/test/kotlin/com/baeldung/threadsvscoroutines/ThreadUnitTest.kt deleted file mode 100644 index 9503751fa3..0000000000 --- a/core-kotlin-modules/core-kotlin-concurrency/src/test/kotlin/com/baeldung/threadsvscoroutines/ThreadUnitTest.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.baeldung.threadsvscoroutines - -import org.junit.jupiter.api.Test -import kotlin.concurrent.thread - -class ThreadUnitTest { - - @Test - fun whenCreateThread_thenRun() { - - val thread = SimpleThread() - thread.start() - } - - @Test - fun whenCreateThreadWithRunnable_thenRun() { - - val threadWithRunnable = Thread(SimpleRunnable()) - threadWithRunnable.start() - } - - @Test - fun whenCreateThreadWithSAMConversions_thenRun() { - - val thread = Thread { - println("${Thread.currentThread()} has run.") - } - thread.start() - } - - @Test - fun whenCreateThreadWithMethodExtension_thenRun() { - - thread(start = true) { - println("${Thread.currentThread()} has run.") - } - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-datastructures/README.md b/core-kotlin-modules/core-kotlin-datastructures/README.md deleted file mode 100644 index 3b22730a76..0000000000 --- a/core-kotlin-modules/core-kotlin-datastructures/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## Core Kotlin - -This module contains articles about data structures in Kotlin - -### Relevant articles: -[Implementing a Binary Tree in Kotlin](https://www.baeldung.com/kotlin-binary-tree) diff --git a/core-kotlin-modules/core-kotlin-datastructures/pom.xml b/core-kotlin-modules/core-kotlin-datastructures/pom.xml deleted file mode 100644 index eae11c17cf..0000000000 --- a/core-kotlin-modules/core-kotlin-datastructures/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - 4.0.0 - core-kotlin-datastructures - core-kotlin-datastructures - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - - - org.junit.platform - junit-platform-runner - ${junit.platform.version} - test - - - - - 1.1.1 - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-datastructures/src/main/kotlin/com/baeldung/binarytree/Main.kt b/core-kotlin-modules/core-kotlin-datastructures/src/main/kotlin/com/baeldung/binarytree/Main.kt deleted file mode 100644 index eee10fbd8b..0000000000 --- a/core-kotlin-modules/core-kotlin-datastructures/src/main/kotlin/com/baeldung/binarytree/Main.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.binarytree - -/** - * Example of how to use the {@link Node} class. - * - */ -fun main(args: Array) { - val tree = Node(4) - val keys = arrayOf(8, 15, 21, 3, 7, 2, 5, 10, 2, 3, 4, 6, 11) - for (key in keys) { - tree.insert(key) - } - val node = tree.find(4)!! - println("Node with value ${node.key} [left = ${node.left?.key}, right = ${node.right?.key}]") - println("Delete node with key = 3") - node.delete(3) - print("Tree content after the node elimination: ") - println(tree.visit().joinToString { it.toString() }) -} diff --git a/core-kotlin-modules/core-kotlin-datastructures/src/main/kotlin/com/baeldung/binarytree/Node.kt b/core-kotlin-modules/core-kotlin-datastructures/src/main/kotlin/com/baeldung/binarytree/Node.kt deleted file mode 100644 index 77bb98f828..0000000000 --- a/core-kotlin-modules/core-kotlin-datastructures/src/main/kotlin/com/baeldung/binarytree/Node.kt +++ /dev/null @@ -1,167 +0,0 @@ -package com.baeldung.binarytree - -/** - * An ADT for a binary search tree. - * Note that this data type is neither immutable nor thread safe. - */ -class Node( - var key: Int, - var left: Node? = null, - var right: Node? = null) { - - /** - * Return a node with given value. If no such node exists, return null. - * @param value - */ - fun find(value: Int): Node? = when { - this.key > value -> left?.find(value) - this.key < value -> right?.find(value) - else -> this - - } - - /** - * Insert a given value into the tree. - * After insertion, the tree should contain a node with the given value. - * If the tree already contains the given value, nothing is performed. - * @param value - */ - fun insert(value: Int) { - if (value > this.key) { - if (this.right == null) { - this.right = Node(value) - } else { - this.right?.insert(value) - } - } else if (value < this.key) { - if (this.left == null) { - this.left = Node(value) - } else { - this.left?.insert(value) - } - } - } - - /** - * Delete the value from the given tree. If the tree does not contain the value, the tree remains unchanged. - * @param value - */ - fun delete(value: Int) { - when { - value > key -> scan(value, this.right, this) - value < key -> scan(value, this.left, this) - else -> removeNode(this, null) - } - } - - /** - * Scan the tree in the search of the given value. - * @param value - * @param node sub-tree that potentially might contain the sought value - * @param parent node's parent - */ - private fun scan(value: Int, node: Node?, parent: Node?) { - if (node == null) { - System.out.println("value " + value - + " seems not present in the tree.") - return - } - when { - value > node.key -> scan(value, node.right, node) - value < node.key -> scan(value, node.left, node) - value == node.key -> removeNode(node, parent) - } - - } - - /** - * Remove the node. - * - * Removal process depends on how many children the node has. - * - * @param node node that is to be removed - * @param parent parent of the node to be removed - */ - private fun removeNode(node: Node, parent: Node?) { - node.left?.let { leftChild -> - run { - node.right?.let { - removeTwoChildNode(node) - } ?: removeSingleChildNode(node, leftChild) - } - } ?: run { - node.right?.let { rightChild -> removeSingleChildNode(node, rightChild) } ?: removeNoChildNode(node, parent) - } - - - } - - /** - * Remove the node without children. - * @param node - * @param parent - */ - private fun removeNoChildNode(node: Node, parent: Node?) { - parent?.let { p -> - if (node == p.left) { - p.left = null - } else if (node == p.right) { - p.right = null - } - } ?: throw IllegalStateException( - "Can not remove the root node without child nodes") - - } - - /** - * Remove a node that has two children. - * - * The process of elimination is to find the biggest key in the left sub-tree and replace the key of the - * node that is to be deleted with that key. - */ - private fun removeTwoChildNode(node: Node) { - val leftChild = node.left!! - leftChild.right?.let { - val maxParent = findParentOfMaxChild(leftChild) - maxParent.right?.let { - node.key = it.key - maxParent.right = null - } ?: throw IllegalStateException("Node with max child must have the right child!") - - } ?: run { - node.key = leftChild.key - node.left = leftChild.left - } - - } - - /** - * Return a node whose right child contains the biggest value in the given sub-tree. - * Assume that the node n has a non-null right child. - * - * @param n - */ - private fun findParentOfMaxChild(n: Node): Node { - return n.right?.let { r -> r.right?.let { findParentOfMaxChild(r) } ?: n } - ?: throw IllegalArgumentException("Right child must be non-null") - - } - - /** - * Remove a parent that has only one child. - * Removal is effectively is just coping the data from the child parent to the parent parent. - * @param parent Node to be deleted. Assume that it has just one child - * @param child Assume it is a child of the parent - */ - private fun removeSingleChildNode(parent: Node, child: Node) { - parent.key = child.key - parent.left = child.left - parent.right = child.right - } - - fun visit(): Array { - val a = left?.visit() ?: emptyArray() - val b = right?.visit() ?: emptyArray() - return a + arrayOf(key) + b - } -} diff --git a/core-kotlin-modules/core-kotlin-datastructures/src/test/kotlin/com/binarytree/NodeTest.kt b/core-kotlin-modules/core-kotlin-datastructures/src/test/kotlin/com/binarytree/NodeTest.kt deleted file mode 100644 index 5a7f7fc50f..0000000000 --- a/core-kotlin-modules/core-kotlin-datastructures/src/test/kotlin/com/binarytree/NodeTest.kt +++ /dev/null @@ -1,320 +0,0 @@ -package com.binarytree - -import org.junit.After -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNull -import org.junit.Before -import org.junit.Test - -class NodeTest { - - @Before - fun setUp() { - } - - @After - fun tearDown() { - } - - /** - * Test suit for finding the node by value - * Partition the tests as follows: - * 1. tree depth: 0, 1, > 1 - * 2. pivot depth location: not present, 0, 1, 2, > 2 - */ - - /** - * Find the node by value - * 1. tree depth: 0 - * 2. pivot depth location: not present - */ - @Test - fun givenDepthZero_whenPivotNotPresent_thenNull() { - val n = Node(1) - assertNull(n.find(2)) - } - - /** - * Find the node by value - * 1. tree depth: 0 - * 2. pivot depth location: 0 - */ - @Test - fun givenDepthZero_whenPivotDepthZero_thenReturnNodeItself() { - val n = Node(1) - assertEquals(n, n.find(1)) - } - - /** - * Find the node by value - * 1. tree depth: 1 - * 2. pivot depth location: not present - */ - @Test - fun givenDepthOne_whenPivotNotPresent_thenNull() { - val n = Node(1, Node(0)) - assertNull(n.find(2)) - } - - /** - * Find the node by value - * 1. tree depth: 1 - * 2. pivot depth location: not present - */ - @Test - fun givenDepthOne_whenPivotAtDepthOne_thenSuccess() { - val n = Node(1, Node(0)) - assertEquals(n.left, n.find(0) - ) - } - - @Test - fun givenDepthTwo_whenPivotAtDepth2_then_Success() { - val left = Node(1, Node(0), Node(2)) - val right = Node(5, Node(4), Node(6)) - val n = Node(3, left, right) - assertEquals(left.left, n.find(0)) - } - - - /** - * Test suit for inserting a value - * Partition the test as follows: - * 1. tree depth: 0, 1, 2, > 2 - * 2. depth to insert: 0, 1, > 1 - * 3. is duplicate: no, yes - * 4. sub-tree: left, right - */ - /** - * Test for inserting a value - * 1. tree depth: 0 - * 2. depth to insert: 1 - * 3. is duplicate: no - * 4. sub-tree: right - */ - @Test - fun givenTreeDepthZero_whenInsertNoDuplicateToRight_thenAddNode() { - val n = Node(1) - n.insert(2) - assertEquals(1, n.key) - with(n.right!!) { - assertEquals(2, key) - assertNull(left) - assertNull(right) - } - assertNull(n.left) - } - - /** - * Test for inserting a value - * 1. tree depth: 0 - * 2. depth to insert: 1 - * 3. is duplicate: no - * 4. sub-tree: right - */ - @Test - fun givenTreeDepthZero_whenInsertNoDuplicateToLeft_thenSuccess() { - val n = Node(1) - n.insert(0) - assertEquals(1, n.key) - with(n.left!!) { - assertEquals(0, key) - assertNull(left) - assertNull(right) - } - assertNull(n.right) - } - - /** - * Test for inserting a value - * 1. tree depth: 0 - * 2. depth to insert: 1 - * 3. is duplicate: yes - */ - @Test - fun givenTreeDepthZero_whenInsertDuplicate_thenSuccess() { - val n = Node(1) - n.insert(1) - assertEquals(1, n.key) - assertNull(n.right) - assertNull(n.left) - } - - - /** - * Test suit for inserting a value - * Partition the test as follows: - * 1. tree depth: 0, 1, 2, > 2 - * 2. depth to insert: 0, 1, > 1 - * 3. is duplicate: no, yes - * 4. sub-tree: left, right - */ - /** - * Test for inserting a value - * 1. tree depth: 1 - * 2. depth to insert: 1 - * 3. is duplicate: no - * 4. sub-tree: right - */ - @Test - fun givenTreeDepthOne_whenInsertNoDuplicateToRight_thenSuccess() { - val n = Node(10, Node(3)) - n.insert(15) - assertEquals(10, n.key) - with(n.right!!) { - assertEquals(15, key) - assertNull(left) - assertNull(right) - } - with(n.left!!) { - assertEquals(3, key) - assertNull(left) - assertNull(right) - } - } - - /** - * Test for inserting a value - * 1. tree depth: 1 - * 2. depth to insert: 1 - * 3. is duplicate: no - * 4. sub-tree: left - */ - @Test - fun givenTreeDepthOne_whenInsertNoDuplicateToLeft_thenAddNode() { - val n = Node(10, null, Node(15)) - n.insert(3) - assertEquals(10, n.key) - with(n.right!!) { - assertEquals(15, key) - assertNull(left) - assertNull(right) - } - with(n.left!!) { - assertEquals(3, key) - assertNull(left) - assertNull(right) - } - } - - /** - * Test for inserting a value - * 1. tree depth: 1 - * 2. depth to insert: 1 - * 3. is duplicate: yes - */ - @Test - fun givenTreeDepthOne_whenInsertDuplicate_thenNoChange() { - val n = Node(10, null, Node(15)) - n.insert(15) - assertEquals(10, n.key) - with(n.right!!) { - assertEquals(15, key) - assertNull(left) - assertNull(right) - } - assertNull(n.left) - } - - /** - * Test suit for removal - * Partition the input as follows: - * 1. tree depth: 0, 1, 2, > 2 - * 2. value to delete: absent, present - * 3. # child nodes: 0, 1, 2 - */ - /** - * Test for removal value - * 1. tree depth: 0 - * 2. value to delete: absent - */ - @Test - fun givenTreeDepthZero_whenValueAbsent_thenNoChange() { - val n = Node(1) - n.delete(0) - assertEquals(1, n.key) - assertNull(n.left) - assertNull(n.right) - } - - /** - * Test for removal - * 1. tree depth: 1 - * 2. value to delete: absent - */ - @Test - fun givenTreeDepthOne_whenValueAbsent_thenNoChange() { - val n = Node(1, Node(0), Node(2)) - n.delete(3) - assertEquals(1, n.key) - assertEquals(2, n.right!!.key) - with(n.left!!) { - assertEquals(0, key) - assertNull(left) - assertNull(right) - } - with(n.right!!) { - assertNull(left) - assertNull(right) - } - } - - /** - * Test suit for removal - * 1. tree depth: 1 - * 2. value to delete: present - * 3. # child nodes: 0 - */ - @Test - fun givenTreeDepthOne_whenNodeToDeleteHasNoChildren_thenChangeTree() { - val n = Node(1, Node(0)) - n.delete(0) - assertEquals(1, n.key) - assertNull(n.left) - assertNull(n.right) - } - - /** - * Test suit for removal - * 1. tree depth: 2 - * 2. value to delete: present - * 3. # child nodes: 1 - */ - @Test - fun givenTreeDepthTwo_whenNodeToDeleteHasOneChild_thenChangeTree() { - val n = Node(2, Node(0, null, Node(1)), Node(3)) - n.delete(0) - assertEquals(2, n.key) - with(n.right!!) { - assertEquals(3, key) - assertNull(left) - assertNull(right) - } - with(n.left!!) { - assertEquals(1, key) - assertNull(left) - assertNull(right) - } - } - - @Test - fun givenTreeDepthThree_whenNodeToDeleteHasTwoChildren_thenChangeTree() { - val l = Node(2, Node(1), Node(5, Node(4), Node(6))) - val r = Node(10, Node(9), Node(11)) - val n = Node(8, l, r) - n.delete(8) - assertEquals(6, n.key) - with(n.left!!) { - assertEquals(2, key) - assertEquals(1, left!!.key) - assertEquals(5, right!!.key) - assertEquals(4, right!!.left!!.key) - } - with(n.right!!) { - assertEquals(10, key) - assertEquals(9, left!!.key) - assertEquals(11, right!!.key) - } - } - -} diff --git a/core-kotlin-modules/core-kotlin-date-time/README.md b/core-kotlin-modules/core-kotlin-date-time/README.md deleted file mode 100644 index a3e358d4e3..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## Core Kotlin Date and Time - -This module contains articles about Kotlin core date/time features. - -### Relevant articles: -[Working with Dates in Kotlin](https://www.baeldung.com/kotlin-dates) diff --git a/core-kotlin-modules/core-kotlin-date-time/pom.xml b/core-kotlin-modules/core-kotlin-date-time/pom.xml deleted file mode 100644 index f3cacefc19..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/pom.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - 4.0.0 - core-kotlin-date-time - core-kotlin-date-time - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - - - org.assertj - assertj-core - ${org.assertj.core.version} - test - - - org.junit.platform - junit-platform-runner - ${junit.platform.version} - test - - - - - 1.1.1 - 3.9.0 - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseDuration.kt b/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseDuration.kt deleted file mode 100644 index 922c3a1988..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseDuration.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.dates.datetime - -import java.time.Duration -import java.time.LocalTime - -class UseDuration { - - fun modifyDates(localTime: LocalTime, duration: Duration): LocalTime { - return localTime.plus(duration) - } - - fun getDifferenceBetweenDates(localTime1: LocalTime, localTime2: LocalTime): Duration { - return Duration.between(localTime1, localTime2) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDate.kt b/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDate.kt deleted file mode 100644 index 81d50a70b2..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDate.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.dates.datetime - -import java.time.DayOfWeek -import java.time.LocalDate -import java.time.LocalDateTime -import java.time.temporal.ChronoUnit -import java.time.temporal.TemporalAdjusters - -class UseLocalDate { - - fun getLocalDateUsingFactoryOfMethod(year: Int, month: Int, dayOfMonth: Int): LocalDate { - return LocalDate.of(year, month, dayOfMonth) - } - - fun getLocalDateUsingParseMethod(representation: String): LocalDate { - return LocalDate.parse(representation) - } - - fun getLocalDateFromClock(): LocalDate { - return LocalDate.now() - } - - fun getNextDay(localDate: LocalDate): LocalDate { - return localDate.plusDays(1) - } - - fun getPreviousDay(localDate: LocalDate): LocalDate { - return localDate.minus(1, ChronoUnit.DAYS) - } - - fun getDayOfWeek(localDate: LocalDate): DayOfWeek { - return localDate.dayOfWeek - } - - fun getFirstDayOfMonth(): LocalDate { - return LocalDate.now().with(TemporalAdjusters.firstDayOfMonth()) - } - - fun getStartOfDay(localDate: LocalDate): LocalDateTime { - return localDate.atStartOfDay() - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDateTime.kt b/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDateTime.kt deleted file mode 100644 index 5d0eb6a911..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalDateTime.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.baeldung.dates.datetime - -import java.time.LocalDateTime - -class UseLocalDateTime { - - fun getLocalDateTimeUsingParseMethod(representation: String): LocalDateTime { - return LocalDateTime.parse(representation) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalTime.kt b/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalTime.kt deleted file mode 100644 index 24402467e8..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseLocalTime.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.baeldung.dates.datetime - -import java.time.LocalTime -import java.time.temporal.ChronoUnit - -class UseLocalTime { - - fun getLocalTimeUsingFactoryOfMethod(hour: Int, min: Int, seconds: Int): LocalTime { - return LocalTime.of(hour, min, seconds) - } - - fun getLocalTimeUsingParseMethod(timeRepresentation: String): LocalTime { - return LocalTime.parse(timeRepresentation) - } - - fun getLocalTimeFromClock(): LocalTime { - return LocalTime.now() - } - - fun addAnHour(localTime: LocalTime): LocalTime { - return localTime.plus(1, ChronoUnit.HOURS) - } - - fun getHourFromLocalTime(localTime: LocalTime): Int { - return localTime.hour - } - - fun getLocalTimeWithMinuteSetToValue(localTime: LocalTime, minute: Int): LocalTime { - return localTime.withMinute(minute) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UsePeriod.kt b/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UsePeriod.kt deleted file mode 100644 index d15e02eb37..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UsePeriod.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.dates.datetime - -import java.time.LocalDate -import java.time.Period - -class UsePeriod { - - fun modifyDates(localDate: LocalDate, period: Period): LocalDate { - return localDate.plus(period) - } - - fun getDifferenceBetweenDates(localDate1: LocalDate, localDate2: LocalDate): Period { - return Period.between(localDate1, localDate2) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseZonedDateTime.kt b/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseZonedDateTime.kt deleted file mode 100644 index e2f3a207c4..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/main/kotlin/com/baeldung/dates/datetime/UseZonedDateTime.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.dates.datetime - -import java.time.LocalDateTime -import java.time.ZoneId -import java.time.ZonedDateTime - -class UseZonedDateTime { - - fun getZonedDateTime(localDateTime: LocalDateTime, zoneId: ZoneId): ZonedDateTime { - return ZonedDateTime.of(localDateTime, zoneId) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/CreateDateUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/CreateDateUnitTest.kt deleted file mode 100644 index af5e08ea2d..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/CreateDateUnitTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.baeldung.kotlin.dates - -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test -import java.time.LocalDate -import java.time.format.DateTimeFormatter - -class CreateDateUnitTest { - - @Test - fun givenString_whenDefaultFormat_thenCreated() { - - var date = LocalDate.parse("2018-12-31") - - assertThat(date).isEqualTo("2018-12-31") - } - - @Test - fun givenString_whenCustomFormat_thenCreated() { - - var formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy") - var date = LocalDate.parse("31-12-2018", formatter) - - assertThat(date).isEqualTo("2018-12-31") - } - - @Test - fun givenYMD_whenUsingOf_thenCreated() { - var date = LocalDate.of(2018, 12, 31) - - assertThat(date).isEqualTo("2018-12-31") - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/ExtractDateUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/ExtractDateUnitTest.kt deleted file mode 100644 index d297f4b6c3..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/ExtractDateUnitTest.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.baeldung.kotlin.dates - -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test -import java.time.DayOfWeek -import java.time.LocalDate -import java.time.Month - -class ExtractDateUnitTest { - - @Test - fun givenDate_thenExtractedYMD() { - var date = LocalDate.parse("2018-12-31") - - assertThat(date.year).isEqualTo(2018) - assertThat(date.month).isEqualTo(Month.DECEMBER) - assertThat(date.dayOfMonth).isEqualTo(31) - } - - @Test - fun givenDate_thenExtractedEraDowDoy() { - var date = LocalDate.parse("2018-12-31") - - assertThat(date.era.toString()).isEqualTo("CE") - assertThat(date.dayOfWeek).isEqualTo(DayOfWeek.MONDAY) - assertThat(date.dayOfYear).isEqualTo(365) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/FormatDateUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/FormatDateUnitTest.kt deleted file mode 100644 index f7ca414aee..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/FormatDateUnitTest.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.baeldung.kotlin.dates - -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test -import java.time.LocalDate -import java.time.format.DateTimeFormatter - -class FormatDateUnitTest { - - @Test - fun givenDate_whenDefaultFormat_thenFormattedString() { - - var date = LocalDate.parse("2018-12-31") - - assertThat(date.toString()).isEqualTo("2018-12-31") - } - - @Test - fun givenDate_whenCustomFormat_thenFormattedString() { - - var date = LocalDate.parse("2018-12-31") - - var formatter = DateTimeFormatter.ofPattern("dd-MMMM-yyyy") - var formattedDate = date.format(formatter) - - assertThat(formattedDate).isEqualTo("31-December-2018") - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/PeriodDateUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/PeriodDateUnitTest.kt deleted file mode 100644 index e8ca2971e8..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/PeriodDateUnitTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.baeldung.kotlin.dates - -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test -import java.time.LocalDate -import java.time.Period - -class PeriodDateUnitTest { - - @Test - fun givenYMD_thenCreatePeriod() { - var period = Period.of(1, 2, 3) - - assertThat(period.toString()).isEqualTo("P1Y2M3D") - } - - @Test - fun givenPeriod_whenAdd_thenModifiedDate() { - var period = Period.of(1, 2, 3) - - var date = LocalDate.of(2018, 6, 25) - var modifiedDate = date.plus(period) - - assertThat(modifiedDate).isEqualTo("2019-08-28") - } - - @Test - fun givenPeriod_whenSubtracted_thenModifiedDate() { - var period = Period.of(1, 2, 3) - - var date = LocalDate.of(2018, 6, 25) - var modifiedDate = date.minus(period) - - assertThat(modifiedDate).isEqualTo("2017-04-22") - } - - @Test - fun givenTwoDate_whenUsingBetween_thenDiffOfDates() { - - var date1 = LocalDate.parse("2018-06-25") - var date2 = LocalDate.parse("2018-12-25") - - var period = Period.between(date1, date2) - - assertThat(period.toString()).isEqualTo("P6M") - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateTimeUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateTimeUnitTest.kt deleted file mode 100644 index f3615a527c..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateTimeUnitTest.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.kotlin.datetime - -import com.baeldung.dates.datetime.UseLocalDateTime -import org.junit.Assert.assertEquals -import org.junit.Test -import java.time.LocalDate -import java.time.LocalTime -import java.time.Month - -class UseLocalDateTimeUnitTest { - - var useLocalDateTime = UseLocalDateTime() - - @Test - fun givenString_whenUsingParse_thenLocalDateTime() { - assertEquals(LocalDate.of(2016, Month.MAY, 10), useLocalDateTime.getLocalDateTimeUsingParseMethod("2016-05-10T06:30") - .toLocalDate()) - assertEquals(LocalTime.of(6, 30), useLocalDateTime.getLocalDateTimeUsingParseMethod("2016-05-10T06:30") - .toLocalTime()) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateUnitTest.kt deleted file mode 100644 index e6353c9dab..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalDateUnitTest.kt +++ /dev/null @@ -1,59 +0,0 @@ -package com.baeldung.kotlin.datetime - -import com.baeldung.dates.datetime.UseLocalDate -import org.junit.Assert -import org.junit.Test -import java.time.DayOfWeek -import java.time.LocalDate -import java.time.LocalDateTime - -class UseLocalDateUnitTest { - - var useLocalDate = UseLocalDate() - - @Test - fun givenValues_whenUsingFactoryOf_thenLocalDate() { - Assert.assertEquals("2016-05-10", useLocalDate.getLocalDateUsingFactoryOfMethod(2016, 5, 10) - .toString()) - } - - @Test - fun givenString_whenUsingParse_thenLocalDate() { - Assert.assertEquals("2016-05-10", useLocalDate.getLocalDateUsingParseMethod("2016-05-10") - .toString()) - } - - @Test - fun whenUsingClock_thenLocalDate() { - Assert.assertEquals(LocalDate.now(), useLocalDate.getLocalDateFromClock()) - } - - @Test - fun givenDate_whenUsingPlus_thenNextDay() { - Assert.assertEquals(LocalDate.now() - .plusDays(1), useLocalDate.getNextDay(LocalDate.now())) - } - - @Test - fun givenDate_whenUsingMinus_thenPreviousDay() { - Assert.assertEquals(LocalDate.now() - .minusDays(1), useLocalDate.getPreviousDay(LocalDate.now())) - } - - @Test - fun givenToday_whenUsingGetDayOfWeek_thenDayOfWeek() { - Assert.assertEquals(DayOfWeek.SUNDAY, useLocalDate.getDayOfWeek(LocalDate.parse("2016-05-22"))) - } - - @Test - fun givenToday_whenUsingWithTemporalAdjuster_thenFirstDayOfMonth() { - Assert.assertEquals(1, useLocalDate.getFirstDayOfMonth() - .dayOfMonth.toLong()) - } - - @Test - fun givenLocalDate_whenUsingAtStartOfDay_thenReturnMidnight() { - Assert.assertEquals(LocalDateTime.parse("2016-05-22T00:00:00"), useLocalDate.getStartOfDay(LocalDate.parse("2016-05-22"))) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalTimeUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalTimeUnitTest.kt deleted file mode 100644 index 1afe03ca48..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseLocalTimeUnitTest.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.baeldung.kotlin.datetime - -import com.baeldung.dates.datetime.UseLocalTime -import org.junit.Assert -import org.junit.Test -import java.time.LocalTime - -class UseLocalTimeUnitTest { - - internal var useLocalTime = UseLocalTime() - - @Test - fun givenValues_whenUsingFactoryOf_thenLocalTime() { - Assert.assertEquals("07:07:07", useLocalTime.getLocalTimeUsingFactoryOfMethod(7, 7, 7).toString()) - } - - @Test - fun givenString_whenUsingParse_thenLocalTime() { - Assert.assertEquals("06:30", useLocalTime.getLocalTimeUsingParseMethod("06:30").toString()) - } - - @Test - fun givenTime_whenAddHour_thenLocalTime() { - Assert.assertEquals("07:30", useLocalTime.addAnHour(LocalTime.of(6, 30)).toString()) - } - - @Test - fun getHourFromLocalTime() { - Assert.assertEquals(1, useLocalTime.getHourFromLocalTime(LocalTime.of(1, 1)).toLong()) - } - - @Test - fun getLocalTimeWithMinuteSetToValue() { - Assert.assertEquals(LocalTime.of(10, 20), useLocalTime.getLocalTimeWithMinuteSetToValue(LocalTime.of(10, 10), 20)) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UsePeriodUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UsePeriodUnitTest.kt deleted file mode 100644 index 36e1e5533a..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UsePeriodUnitTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.kotlin.datetime - -import com.baeldung.dates.datetime.UsePeriod -import org.junit.Assert -import org.junit.Test -import java.time.LocalDate -import java.time.Period - -class UsePeriodUnitTest { - - var usingPeriod = UsePeriod() - - @Test - fun givenPeriodAndLocalDate_thenCalculateModifiedDate() { - val period = Period.ofDays(1) - val localDate = LocalDate.parse("2007-05-10") - Assert.assertEquals(localDate.plusDays(1), usingPeriod.modifyDates(localDate, period)) - } - - @Test - fun givenDates_thenGetPeriod() { - val localDate1 = LocalDate.parse("2007-05-10") - val localDate2 = LocalDate.parse("2007-05-15") - - Assert.assertEquals(Period.ofDays(5), usingPeriod.getDifferenceBetweenDates(localDate1, localDate2)) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseZonedDateTimeUnitTest.kt b/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseZonedDateTimeUnitTest.kt deleted file mode 100644 index aa2cdaa4f3..0000000000 --- a/core-kotlin-modules/core-kotlin-date-time/src/test/kotlin/com/baeldung/dates/datetime/UseZonedDateTimeUnitTest.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.kotlin.datetime - -import com.baeldung.dates.datetime.UseZonedDateTime -import org.junit.Assert -import org.junit.Test -import java.time.LocalDateTime -import java.time.ZoneId - -class UseZonedDateTimeUnitTest { - - internal var zonedDateTime = UseZonedDateTime() - - @Test - fun givenZoneId_thenZonedDateTime() { - val zoneId = ZoneId.of("Europe/Paris") - val zonedDatetime = zonedDateTime.getZonedDateTime(LocalDateTime.parse("2016-05-20T06:30"), zoneId) - Assert.assertEquals(zoneId, ZoneId.from(zonedDatetime)) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-design-patterns/README.md b/core-kotlin-modules/core-kotlin-design-patterns/README.md deleted file mode 100644 index 4bdc164a47..0000000000 --- a/core-kotlin-modules/core-kotlin-design-patterns/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## Core Kotlin Design Patterns - -This module contains articles about design patterns in Kotlin - -### Relevant articles: -- [Creational Design Patterns in Kotlin: Builder](https://www.baeldung.com/kotlin-builder-pattern) diff --git a/core-kotlin-modules/core-kotlin-design-patterns/pom.xml b/core-kotlin-modules/core-kotlin-design-patterns/pom.xml deleted file mode 100644 index c112602bc2..0000000000 --- a/core-kotlin-modules/core-kotlin-design-patterns/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - 4.0.0 - core-kotlin-design-patterns - core-kotlin-design-patterns - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - - - org.junit.platform - junit-platform-runner - ${junit.platform.version} - test - - - - - 1.1.1 - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrder.kt b/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrder.kt deleted file mode 100644 index 3a8a4b9857..0000000000 --- a/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrder.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.builder - -class FoodOrder private constructor( - val bread: String?, - val condiments: String?, - val meat: String?, - val fish: String? -) { - data class Builder( - var bread: String? = null, - var condiments: String? = null, - var meat: String? = null, - var fish: String? = null) { - - fun bread(bread: String) = apply { this.bread = bread } - fun condiments(condiments: String) = apply { this.condiments = condiments } - fun meat(meat: String) = apply { this.meat = meat } - fun fish(fish: String) = apply { this.fish = fish } - fun build() = FoodOrder(bread, condiments, meat, fish) - } -} - diff --git a/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrderApply.kt b/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrderApply.kt deleted file mode 100644 index 0a68832b00..0000000000 --- a/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrderApply.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.builder - -class FoodOrderApply { - var bread: String? = null - var condiments: String? = null - var meat: String? = null - var fish: String? = null -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrderNamed.kt b/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrderNamed.kt deleted file mode 100644 index 0e4219b40e..0000000000 --- a/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/FoodOrderNamed.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.baeldung.builder - -data class FoodOrderNamed( - val bread: String? = null, - val condiments: String? = null, - val meat: String? = null, - val fish: String? = null) diff --git a/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/Main.kt b/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/Main.kt deleted file mode 100644 index cc348e3fbf..0000000000 --- a/core-kotlin-modules/core-kotlin-design-patterns/src/main/kotlin/com/baeldung/builder/Main.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.baeldung.builder - -fun main(args: Array) { - FoodOrder.Builder() - .bread("bread") - .condiments("condiments") - .meat("meat") - .fish("bread").let { println(it) } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-design-patterns/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt b/core-kotlin-modules/core-kotlin-design-patterns/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt deleted file mode 100644 index a6687b6e0a..0000000000 --- a/core-kotlin-modules/core-kotlin-design-patterns/src/test/kotlin/com/baeldung/builder/BuilderPatternUnitTest.kt +++ /dev/null @@ -1,140 +0,0 @@ -package com.baeldung.builder - -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Test - -internal class BuilderPatternUnitTest { - - @Test - fun whenBuildingFoodOrderSettingValues_thenFieldsNotNull() { - - val foodOrder = FoodOrder.Builder() - .bread("white bread") - .meat("bacon") - .fish("salmon") - .condiments("olive oil") - .build() - - Assertions.assertNotNull(foodOrder.bread) - Assertions.assertNotNull(foodOrder.meat) - Assertions.assertNotNull(foodOrder.condiments) - Assertions.assertNotNull(foodOrder.fish) - } - - @Test - fun whenBuildingFoodOrderSettingValues_thenFieldsContainsValues() { - - val foodOrder = FoodOrder.Builder() - .bread("white bread") - .meat("bacon") - .fish("salmon") - .condiments("olive oil") - .build() - - Assertions.assertEquals("white bread", foodOrder.bread) - Assertions.assertEquals("bacon", foodOrder.meat) - Assertions.assertEquals("olive oil", foodOrder.condiments) - Assertions.assertEquals("salmon", foodOrder.fish) - } - - @Test - fun whenBuildingFoodOrderWithoutSettingValues_thenFieldsNull() { - - val foodOrder = FoodOrder.Builder() - .build() - - Assertions.assertNull(foodOrder.bread) - Assertions.assertNull(foodOrder.meat) - Assertions.assertNull(foodOrder.condiments) - Assertions.assertNull(foodOrder.fish) - } - - - @Test - fun whenBuildingFoodOrderNamedSettingValues_thenFieldsNotNull() { - - val foodOrder = FoodOrderNamed( - meat = "bacon", - fish = "salmon", - condiments = "olive oil", - bread = "white bread" - ) - - Assertions.assertNotNull(foodOrder.bread) - Assertions.assertNotNull(foodOrder.meat) - Assertions.assertNotNull(foodOrder.condiments) - Assertions.assertNotNull(foodOrder.fish) - } - - @Test - fun whenBuildingFoodOrderNamedSettingValues_thenFieldsContainsValues() { - - val foodOrder = FoodOrderNamed( - meat = "bacon", - fish = "salmon", - condiments = "olive oil", - bread = "white bread" - ) - - Assertions.assertEquals("white bread", foodOrder.bread) - Assertions.assertEquals("bacon", foodOrder.meat) - Assertions.assertEquals("olive oil", foodOrder.condiments) - Assertions.assertEquals("salmon", foodOrder.fish) - } - - @Test - fun whenBuildingFoodOrderNamedWithoutSettingValues_thenFieldsNull() { - - val foodOrder = FoodOrderNamed() - - Assertions.assertNull(foodOrder.bread) - Assertions.assertNull(foodOrder.meat) - Assertions.assertNull(foodOrder.condiments) - Assertions.assertNull(foodOrder.fish) - } - - - @Test - fun whenBuildingFoodOrderApplySettingValues_thenFieldsNotNull() { - - val foodOrder = FoodOrderApply().apply { - meat = "bacon" - fish = "salmon" - condiments = "olive oil" - bread = "white bread" - } - - Assertions.assertNotNull(foodOrder.bread) - Assertions.assertNotNull(foodOrder.meat) - Assertions.assertNotNull(foodOrder.condiments) - Assertions.assertNotNull(foodOrder.fish) - } - - @Test - fun whenBuildingFoodOrderApplySettingValues_thenFieldsContainsValues() { - - val foodOrder = FoodOrderApply().apply { - meat = "bacon" - fish = "salmon" - condiments = "olive oil" - bread = "white bread" - } - - Assertions.assertEquals("white bread", foodOrder.bread) - Assertions.assertEquals("bacon", foodOrder.meat) - Assertions.assertEquals("olive oil", foodOrder.condiments) - Assertions.assertEquals("salmon", foodOrder.fish) - } - - @Test - fun whenBuildingFoodOrderApplyWithoutSettingValues_thenFieldsNull() { - - val foodOrder = FoodOrderApply() - - Assertions.assertNull(foodOrder.bread) - Assertions.assertNull(foodOrder.meat) - Assertions.assertNull(foodOrder.condiments) - Assertions.assertNull(foodOrder.fish) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-io/README.md b/core-kotlin-modules/core-kotlin-io/README.md deleted file mode 100644 index 89f9534d4b..0000000000 --- a/core-kotlin-modules/core-kotlin-io/README.md +++ /dev/null @@ -1,9 +0,0 @@ -## Core Kotlin I/O - -This module contains articles about core Kotlin I/O. - -### Relevant articles: -- [InputStream to String in Kotlin](https://www.baeldung.com/kotlin-inputstream-to-string) -- [Console I/O in Kotlin](https://www.baeldung.com/kotlin-console-io) -- [Reading from a File in Kotlin](https://www.baeldung.com/kotlin-read-file) -- [Writing to a File in Kotlin](https://www.baeldung.com/kotlin-write-file) diff --git a/core-kotlin-modules/core-kotlin-io/pom.xml b/core-kotlin-modules/core-kotlin-io/pom.xml deleted file mode 100644 index 9443cd0d5b..0000000000 --- a/core-kotlin-modules/core-kotlin-io/pom.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - 4.0.0 - core-kotlin-io - core-kotlin-io - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - - - org.junit.jupiter - junit-jupiter - ${junit-jupiter.version} - test - - - org.mockito - mockito-core - ${mockito.version} - test - - - org.assertj - assertj-core - ${assertj.version} - test - - - org.jetbrains.kotlin - kotlin-test - ${kotlin.version} - test - - - - - 5.4.2 - 2.27.0 - 3.10.0 - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-io/src/main/kotlin/com/baeldung/filesystem/FileReader.kt b/core-kotlin-modules/core-kotlin-io/src/main/kotlin/com/baeldung/filesystem/FileReader.kt deleted file mode 100644 index 886a3fc51e..0000000000 --- a/core-kotlin-modules/core-kotlin-io/src/main/kotlin/com/baeldung/filesystem/FileReader.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.filesystem - -import java.io.File - -class FileReader { - - fun readFileLineByLineUsingForEachLine(fileName: String) = File(fileName).forEachLine { println(it) } - - fun readFileAsLinesUsingUseLines(fileName: String): List = File(fileName) - .useLines { it.toList() } - - fun readFileAsLinesUsingBufferedReader(fileName: String): List = File(fileName).bufferedReader().readLines() - - fun readFileAsLinesUsingReadLines(fileName: String): List = File(fileName).readLines() - - fun readFileAsTextUsingInputStream(fileName: String) = - File(fileName).inputStream().readBytes().toString(Charsets.UTF_8) - - fun readFileDirectlyAsText(fileName: String): String = File(fileName).readText(Charsets.UTF_8) - - fun readFileUsingGetResource(fileName: String) = this::class.java.getResource(fileName).readText(Charsets.UTF_8) - - fun readFileAsLinesUsingGetResourceAsStream(fileName: String) = this::class.java.getResourceAsStream(fileName).bufferedReader().readLines() -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-io/src/main/kotlin/com/baeldung/filesystem/FileWriter.kt b/core-kotlin-modules/core-kotlin-io/src/main/kotlin/com/baeldung/filesystem/FileWriter.kt deleted file mode 100644 index 6dc9b95f1f..0000000000 --- a/core-kotlin-modules/core-kotlin-io/src/main/kotlin/com/baeldung/filesystem/FileWriter.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.filesystem - -import java.io.File - -class FileWriter { - - fun writeFileUsingPrintWriter(fileName: String, fileContent: String) = - File(fileName).printWriter().use { out -> out.print(fileContent) } - - fun writeFileUsingBufferedWriter(fileName: String, fileContent: String) = - File(fileName).bufferedWriter().use { out -> out.write(fileContent) } - - fun writeFileDirectly(fileName: String, fileContent: String) = - File(fileName).writeText(fileContent) - - fun writeFileDirectlyAsBytes(fileName: String, fileContent: String) = - File(fileName).writeBytes(fileContent.toByteArray()) - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-io/src/main/kotlin/com/baeldung/inputstream/InputStreamExtension.kt b/core-kotlin-modules/core-kotlin-io/src/main/kotlin/com/baeldung/inputstream/InputStreamExtension.kt deleted file mode 100644 index e94a2e84ee..0000000000 --- a/core-kotlin-modules/core-kotlin-io/src/main/kotlin/com/baeldung/inputstream/InputStreamExtension.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.baeldung.inputstream - -import java.io.InputStream - -fun InputStream.readUpToChar(stopChar: Char): String { - val stringBuilder = StringBuilder() - var currentChar = this.read().toChar() - while (currentChar != stopChar) { - stringBuilder.append(currentChar) - currentChar = this.read().toChar() - if (this.available() <= 0) { - stringBuilder.append(currentChar) - break - } - } - return stringBuilder.toString() -} - diff --git a/core-kotlin-modules/core-kotlin-io/src/test/kotlin/com/baeldung/console/ConsoleIOUnitTest.kt b/core-kotlin-modules/core-kotlin-io/src/test/kotlin/com/baeldung/console/ConsoleIOUnitTest.kt deleted file mode 100644 index c73096fce6..0000000000 --- a/core-kotlin-modules/core-kotlin-io/src/test/kotlin/com/baeldung/console/ConsoleIOUnitTest.kt +++ /dev/null @@ -1,79 +0,0 @@ -package com.baeldung.console - -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.Test -import org.mockito.Mockito.`when` -import org.mockito.Mockito.mock -import java.io.BufferedReader -import java.io.ByteArrayInputStream -import java.io.ByteArrayOutputStream -import java.io.Console -import java.io.InputStreamReader -import java.io.PrintStream -import java.util.* - - -class ConsoleIOUnitTest { - - @Test - fun givenText_whenPrint_thenPrintText() { - val expectedTest = "Hello from Kotlin" - val out = ByteArrayOutputStream() - System.setOut(PrintStream(out)) - - print(expectedTest) - out.flush() - val printedText = String(out.toByteArray()) - - assertThat(printedText).isEqualTo(expectedTest) - } - - @Test - fun givenInput_whenRead_thenReadText() { - val expectedTest = "Hello from Kotlin" - val input = ByteArrayInputStream(expectedTest.toByteArray()) - System.setIn(input) - - val readText = readLine() - - assertThat(readText).isEqualTo(expectedTest) - } - - @Test - fun givenInput_whenReadWithScanner_thenReadText() { - val expectedTest = "Hello from Kotlin" - val scanner = Scanner(ByteArrayInputStream(expectedTest.toByteArray())) - - val readText = scanner.nextLine() - - assertThat(readText).isEqualTo(expectedTest) - } - - @Test - fun givenInput_whenReadWithBufferedReader_thenReadText() { - val expectedTest = "Hello from Kotlin" - val reader = BufferedReader(InputStreamReader(ByteArrayInputStream(expectedTest.toByteArray()))) - - val readText = reader.readLine() - - assertThat(readText).isEqualTo(expectedTest) - } - - @Test - fun givenInput_whenReadWithConsole_thenReadText() { - val expectedTest = "Hello from Kotlin" - val console = mock(Console::class.java) - `when`(console.readLine()).thenReturn(expectedTest) - - val readText = console.readLine() - - assertThat(readText).isEqualTo(expectedTest) - } - - @AfterEach - fun resetIO() { - System.setOut(System.out) - System.setIn(System.`in`) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-io/src/test/kotlin/com/baeldung/filesystem/FileReaderTest.kt b/core-kotlin-modules/core-kotlin-io/src/test/kotlin/com/baeldung/filesystem/FileReaderTest.kt deleted file mode 100644 index ad541c446e..0000000000 --- a/core-kotlin-modules/core-kotlin-io/src/test/kotlin/com/baeldung/filesystem/FileReaderTest.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.baeldung.filesystem - -import org.junit.jupiter.api.Test -import kotlin.test.assertTrue - -internal class FileReaderTest { - - private val fileName = "src/test/resources/Kotlin.in" - - private val fileReader = FileReader() - - @Test - fun whenReadFileLineByLineUsingForEachLine_thenCorrect() { - fileReader.readFileLineByLineUsingForEachLine(fileName) - } - - @Test - fun whenReadFileAsLinesUsingUseLines_thenCorrect() { - val lines = fileReader.readFileAsLinesUsingUseLines(fileName) - - assertTrue { lines.contains("1. Concise") } - } - - @Test - fun whenReadFileAsLinesUsingBufferedReader_thenCorrect() { - val lines = fileReader.readFileAsLinesUsingBufferedReader(fileName) - - assertTrue { lines.contains("2. Safe") } - } - - @Test - fun whenReadFileAsLinesUsingReadLines_thenCorrect() { - val lines = fileReader.readFileAsLinesUsingReadLines(fileName) - - assertTrue { lines.contains("3. Interoperable") } - } - - @Test - fun whenReadFileAsTextUsingInputStream_thenCorrect() { - val text = fileReader.readFileAsTextUsingInputStream(fileName) - - assertTrue { text.contains("4. Tool-friendly") } - } - - @Test - fun whenReadDirectlyAsText_thenCorrect() { - val text = fileReader.readFileDirectlyAsText(fileName) - - assertTrue { text.contains("Hello to Kotlin") } - } - - @Test - fun whenReadFileAsTextUsingGetResource_thenCorrect() { - val text = fileReader.readFileUsingGetResource("/Kotlin.in") - - assertTrue { text.contains("1. Concise") } - } - - @Test - fun whenReadFileUsingGetResourceAsStream_thenCorrect() { - val lines = fileReader.readFileAsLinesUsingGetResourceAsStream("/Kotlin.in") - - assertTrue { lines.contains("3. Interoperable") } - } - - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-io/src/test/kotlin/com/baeldung/filesystem/FileWriterTest.kt b/core-kotlin-modules/core-kotlin-io/src/test/kotlin/com/baeldung/filesystem/FileWriterTest.kt deleted file mode 100644 index 91c66a4fee..0000000000 --- a/core-kotlin-modules/core-kotlin-io/src/test/kotlin/com/baeldung/filesystem/FileWriterTest.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.baeldung.filesystem - -import org.junit.jupiter.api.Test -import java.io.File -import kotlin.test.assertEquals - -internal class FileWriterTest { - - private val fileName = "src/test/resources/Kotlin.out" - - private val fileContent = "Kotlin\nConcise, Safe, Interoperable, Tool-friendly" - - private val fileWriter = FileWriter() - - @Test - fun whenWrittenWithPrintWriter_thenCorrect() { - fileWriter.writeFileUsingPrintWriter(fileName, fileContent) - - assertEquals(fileContent, File(fileName).readText()) - } - - @Test - fun whenWrittenWithBufferedWriter_thenCorrect() { - fileWriter.writeFileUsingBufferedWriter(fileName, fileContent) - - assertEquals(fileContent, File(fileName).readText()) - } - - @Test - fun whenWrittenDirectly_thenCorrect() { - fileWriter.writeFileDirectly(fileName, fileContent) - - assertEquals(fileContent, File(fileName).readText()) - } - - @Test - fun whenWrittenDirectlyAsBytes_thenCorrect() { - fileWriter.writeFileDirectlyAsBytes(fileName, fileContent) - - assertEquals(fileContent, File(fileName).readText()) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-io/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt b/core-kotlin-modules/core-kotlin-io/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt deleted file mode 100644 index a0eb26b762..0000000000 --- a/core-kotlin-modules/core-kotlin-io/src/test/kotlin/com/baeldung/inputstream/InputStreamToStringTest.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.baeldung.inputstream - -import kotlinx.io.core.use -import org.junit.Test -import java.io.BufferedReader -import java.io.File -import kotlin.test.assertEquals - -class InputStreamToStringTest { - - private val fileName = "src/test/resources/inputstream2string.txt" - private val endOfLine = System.lineSeparator() - private val fileFullContent = "Computer programming can be a hassle$endOfLine" + - "It's like trying to take a defended castle" - - @Test - fun whenReadFileWithBufferedReader_thenFullFileContentIsReadAsString() { - val file = File(fileName) - val inputStream = file.inputStream() - val content = inputStream.bufferedReader().use(BufferedReader::readText) - assertEquals(fileFullContent, content) - } - - @Test - fun whenReadFileWithBufferedReaderReadText_thenFullFileContentIsReadAsString() { - val file = File(fileName) - val inputStream = file.inputStream() - val reader = BufferedReader(inputStream.reader()) - var content: String - try { - content = reader.readText() - } finally { - reader.close() - } - assertEquals(fileFullContent, content) - } - - @Test - fun whenReadFileWithBufferedReaderManually_thenFullFileContentIsReadAsString() { - val file = File(fileName) - val inputStream = file.inputStream() - val reader = BufferedReader(inputStream.reader()) - val content = StringBuilder() - try { - var line = reader.readLine() - while (line != null) { - content.append(line) - line = reader.readLine() - } - } finally { - reader.close() - } - assertEquals(fileFullContent.replace(endOfLine, ""), content.toString()) - - } - - @Test - fun whenReadFileUpToStopChar_thenPartBeforeStopCharIsReadAsString() { - val file = File(fileName) - val inputStream = file.inputStream() - val content = inputStream.use { it.readUpToChar(' ') } - assertEquals("Computer", content) - } - - @Test - fun whenReadFileWithoutContainingStopChar_thenFullFileContentIsReadAsString() { - val file = File(fileName) - val inputStream = file.inputStream() - val content = inputStream.use { it.readUpToChar('-') } - assertEquals(fileFullContent, content) - } - -} - diff --git a/core-kotlin-modules/core-kotlin-io/src/test/resources/Kotlin.in b/core-kotlin-modules/core-kotlin-io/src/test/resources/Kotlin.in deleted file mode 100644 index d140d4429e..0000000000 --- a/core-kotlin-modules/core-kotlin-io/src/test/resources/Kotlin.in +++ /dev/null @@ -1,5 +0,0 @@ -Hello to Kotlin. Its: -1. Concise -2. Safe -3. Interoperable -4. Tool-friendly \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-io/src/test/resources/Kotlin.out b/core-kotlin-modules/core-kotlin-io/src/test/resources/Kotlin.out deleted file mode 100644 index 63d15d2528..0000000000 --- a/core-kotlin-modules/core-kotlin-io/src/test/resources/Kotlin.out +++ /dev/null @@ -1,2 +0,0 @@ -Kotlin -Concise, Safe, Interoperable, Tool-friendly \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-io/src/test/resources/inputstream2string.txt b/core-kotlin-modules/core-kotlin-io/src/test/resources/inputstream2string.txt deleted file mode 100644 index 40ef9fc5f3..0000000000 --- a/core-kotlin-modules/core-kotlin-io/src/test/resources/inputstream2string.txt +++ /dev/null @@ -1,2 +0,0 @@ -Computer programming can be a hassle -It's like trying to take a defended castle \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-io/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/core-kotlin-modules/core-kotlin-io/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker deleted file mode 100644 index ca6ee9cea8..0000000000 --- a/core-kotlin-modules/core-kotlin-io/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker +++ /dev/null @@ -1 +0,0 @@ -mock-maker-inline \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-2/README.md b/core-kotlin-modules/core-kotlin-lang-2/README.md deleted file mode 100644 index e7f232856b..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/README.md +++ /dev/null @@ -1,16 +0,0 @@ -## Core Kotlin Lang - -This module contains articles about core features in the Kotlin language. - -### Relevant articles: -- [Kotlin return, break, continue Keywords](https://www.baeldung.com/kotlin-return-break-continue) -- [Infix Functions in Kotlin](https://www.baeldung.com/kotlin-infix-functions) -- [Lambda Expressions in Kotlin](https://www.baeldung.com/kotlin-lambda-expressions) -- [Creating Java static final Equivalents in Kotlin](https://www.baeldung.com/kotlin-java-static-final) -- [Lazy Initialization in Kotlin](https://www.baeldung.com/kotlin-lazy-initialization) -- [Comprehensive Guide to Null Safety in Kotlin](https://www.baeldung.com/kotlin-null-safety) -- [Kotlin Scope Functions](https://www.baeldung.com/kotlin-scope-functions) -- [If-Else Expression in Kotlin](https://www.baeldung.com/kotlin/if-else-expression) -- [Checking Whether a lateinit var Is Initialized in Kotlin](https://www.baeldung.com/kotlin/checking-lateinit) -- [Not-Null Assertion (!!) Operator in Kotlin](https://www.baeldung.com/kotlin/not-null-assertion) -- [[<-- Prev]](/core-kotlin-modules/core-kotlin-lang) diff --git a/core-kotlin-modules/core-kotlin-lang-2/pom.xml b/core-kotlin-modules/core-kotlin-lang-2/pom.xml deleted file mode 100644 index 753147728d..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - 4.0.0 - core-kotlin-lang-2 - core-kotlin-lang-2 - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/main/java/com/baeldung/lazy/ClassWithHeavyInitialization.java b/core-kotlin-modules/core-kotlin-lang-2/src/main/java/com/baeldung/lazy/ClassWithHeavyInitialization.java deleted file mode 100644 index 273749e17e..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/main/java/com/baeldung/lazy/ClassWithHeavyInitialization.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.lazy; - -public class ClassWithHeavyInitialization { - private ClassWithHeavyInitialization() { - } - - private static class LazyHolder { - public static final ClassWithHeavyInitialization INSTANCE = new ClassWithHeavyInitialization(); - } - - public static ClassWithHeavyInitialization getInstance() { - return LazyHolder.INSTANCE; - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/main/kotlin/com/baeldung/ifelseexpression/IfElseExpressionExample.kt b/core-kotlin-modules/core-kotlin-lang-2/src/main/kotlin/com/baeldung/ifelseexpression/IfElseExpressionExample.kt deleted file mode 100644 index f4e42a4f4f..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/main/kotlin/com/baeldung/ifelseexpression/IfElseExpressionExample.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.baeldung.ifelseexpression - -fun ifStatementUsage(): String { - val number = 15 - - if (number > 0) { - return "Positive number" - } - return "Positive number not found" -} - -fun ifElseStatementUsage(): String { - val number = -50 - - if (number > 0) { - return "Positive number" - } else { - return "Negative number" - } -} - -fun ifElseExpressionUsage(): String { - val number = -50 - - val result = if (number > 0) { - "Positive number" - } else { - "Negative number" - } - return result -} - -fun ifElseExpressionSingleLineUsage(): String { - val number = -50 - val result = if (number > 0) "Positive number" else "Negative number" - - return result -} - -fun ifElseMultipleExpressionUsage(): Int { - val x = 24 - val y = 73 - - val result = if (x > y) { - println("$x is greater than $y") - x - } else { - println("$x is less than or equal to $y") - y - } - return result -} - -fun ifElseLadderExpressionUsage(): String { - val number = 60 - - val result = if (number < 0) { - "Negative number" - } else if (number in 0..9) { - "Single digit number" - } else if (number in 10..99) { - "Double digit number" - } else { - "Number has more digits" - } - return result -} - -fun ifElseNestedExpressionUsage(): Int { - val x = 37 - val y = 89 - val z = 6 - - val result = if (x > y) { - if (x > z) - x - else - z - } else { - if (y > z) - y - else - z - } - return result -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/main/kotlin/com/baeldung/lambda/Lambda.kt b/core-kotlin-modules/core-kotlin-lang-2/src/main/kotlin/com/baeldung/lambda/Lambda.kt deleted file mode 100644 index f35f9cdac2..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/main/kotlin/com/baeldung/lambda/Lambda.kt +++ /dev/null @@ -1,84 +0,0 @@ -package com.baeldung.lambda - -fun inferredType(input: Int): Int { - val square = { number: Int -> number * number } - - return square(input) -} - -fun intToBiggerString(argument: Int): String { - - val magnitude100String = { input: Int -> - val magnitude = input * 100 - magnitude.toString() - } - - return magnitude100String(argument) -} - -fun manyLambda(nums: Array): List { - val newList = nums.map { intToBiggerString(it) } - - return newList -} - -fun empty() { - val noReturn: (Int) -> Unit = { num -> println(num) } - - noReturn(5) -} - -fun invokeLambda(lambda: (Double) -> Boolean): Boolean { - return lambda(4.329) -} - -fun extendString(arg: String, num: Int): String { - val another: String.(Int) -> String = { this + it } - - return arg.another(num) -} - -fun getCalculationLambda(): (Int) -> Any { - val calculateGrade = { grade: Int -> - when (grade) { - in 0..40 -> "Fail" - in 41..70 -> "Pass" - in 71..100 -> "Distinction" - else -> false - } - } - - return calculateGrade -} - -fun getCalculationLambdaWithReturn(): (Int) -> String { - val calculateGrade: Int.() -> String = lambda@{ - if (this < 0 || this > 100) { - return@lambda "Error" - } else if (this < 40) { - return@lambda "Fail" - } else if (this < 70) { - return@lambda "Pass" - } - - "Distinction" - } - - return calculateGrade -} - -fun getCalculationAnonymousFunction(): (Int) -> String { - val calculateGrade = fun(grade: Int): String { - if (grade < 0 || grade > 100) { - return "Error" - } else if (grade < 40) { - return "Fail" - } else if (grade < 70) { - return "Pass" - } - - return "Distinction" - } - - return calculateGrade -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/main/kotlin/com/baeldung/scope/ScopeFunctions.kt b/core-kotlin-modules/core-kotlin-lang-2/src/main/kotlin/com/baeldung/scope/ScopeFunctions.kt deleted file mode 100644 index 37ad8c65e2..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/main/kotlin/com/baeldung/scope/ScopeFunctions.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.baeldung.scope - -data class Student(var studentId: String = "", var name: String = "", var surname: String = "") { -} - -data class Teacher(var teacherId: Int = 0, var name: String = "", var surname: String = "") { - fun setId(anId: Int): Teacher = apply { teacherId = anId } - fun setName(aName: String): Teacher = apply { name = aName } - fun setSurname(aSurname: String): Teacher = apply { surname = aSurname } -} - -data class Headers(val headerInfo: String) - -data class Response(val headers: Headers) - -data class RestClient(val url: String) { - fun getResponse() = Response(Headers("some header info")) -} - -data class BankAccount(val id: Int) { - fun checkAuthorization(username: String) = Unit - fun addPayee(payee: String) = Unit - fun makePayment(paymentDetails: String) = Unit - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/test/java/com/baeldung/lazy/LazyJavaUnitTest.java b/core-kotlin-modules/core-kotlin-lang-2/src/test/java/com/baeldung/lazy/LazyJavaUnitTest.java deleted file mode 100644 index 01c87d9543..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/test/java/com/baeldung/lazy/LazyJavaUnitTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.baeldung.lazy; - -import org.junit.Test; - -import static junit.framework.TestCase.assertTrue; - -public class LazyJavaUnitTest { - - @Test - public void giveHeavyClass_whenInitLazy_thenShouldReturnInstanceOnFirstCall() { - //when - ClassWithHeavyInitialization classWithHeavyInitialization = ClassWithHeavyInitialization.getInstance(); - ClassWithHeavyInitialization classWithHeavyInitialization2 = ClassWithHeavyInitialization.getInstance(); - - //then - assertTrue(classWithHeavyInitialization == classWithHeavyInitialization2); - } -} diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/constant/ConstantUnitTest.kt b/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/constant/ConstantUnitTest.kt deleted file mode 100644 index d9bf433208..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/constant/ConstantUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.constant - -import org.junit.jupiter.api.Test -import kotlin.test.assertEquals - -class ConstantUnitTest { - - @Test - fun givenConstant_whenCompareWithActualValue_thenReturnTrue() { - assertEquals(10, TestKotlinConstantObject.COMPILE_TIME_CONST) - assertEquals(30, TestKotlinConstantObject.RUN_TIME_CONST) - assertEquals(20, TestKotlinConstantObject.JAVA_STATIC_FINAL_FIELD) - - assertEquals(40, TestKotlinConstantClass.COMPANION_OBJECT_NUMBER) - } -} - diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/constant/TestKotlinConstantClass.kt b/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/constant/TestKotlinConstantClass.kt deleted file mode 100644 index 3c4d4db220..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/constant/TestKotlinConstantClass.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.constant - - -class TestKotlinConstantClass { - companion object { - const val COMPANION_OBJECT_NUMBER = 40 - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/constant/TestKotlinConstantObject.kt b/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/constant/TestKotlinConstantObject.kt deleted file mode 100644 index a6951b4481..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/constant/TestKotlinConstantObject.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.constant - - -object TestKotlinConstantObject { - const val COMPILE_TIME_CONST = 10 - - val RUN_TIME_CONST: Int - - @JvmField - val JAVA_STATIC_FINAL_FIELD = 20 - - init { - RUN_TIME_CONST = TestKotlinConstantObject.COMPILE_TIME_CONST + 20; - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/ifelseexpression/IfElseExpressionExampleTest.kt b/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/ifelseexpression/IfElseExpressionExampleTest.kt deleted file mode 100644 index 266e41e07b..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/ifelseexpression/IfElseExpressionExampleTest.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.baeldung.ifelseexpression - -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNotEquals - -class IfElseExpressionExampleTest { - - @Test - fun givenNumber_whenIfStatementCalled_thenReturnsString() { - assertEquals("Positive number", ifStatementUsage()) - } - - @Test - fun givenNumber_whenIfElseStatementCalled_thenReturnsString() { - assertEquals("Negative number", ifElseStatementUsage()) - } - - @Test - fun givenNumber_whenIfElseExpressionCalled_thenReturnsString() { - assertEquals("Negative number", ifElseExpressionUsage()) - } - - @Test - fun givenNumber_whenIfElseExpressionSingleLineCalled_thenReturnsString() { - assertEquals("Negative number", ifElseExpressionSingleLineUsage()) - } - - @Test - fun givenNumber_whenIfElseMultipleExpressionCalled_thenReturnsNumber() { - assertEquals(73, ifElseMultipleExpressionUsage()) - } - - @Test - fun givenNumber_whenIfElseLadderExpressionCalled_thenReturnsString() { - assertEquals("Double digit number", ifElseLadderExpressionUsage()) - } - - @Test - fun givenNumber_whenIfElseNestedExpressionCalled_thenReturnsNumber() { - assertEquals(89, ifElseNestedExpressionUsage()) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/infixfunctions/InfixFunctionsTest.kt b/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/infixfunctions/InfixFunctionsTest.kt deleted file mode 100644 index 0b09d34013..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/infixfunctions/InfixFunctionsTest.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.baeldung.infixfunctions - -import org.junit.Assert -import org.junit.Test - -class InfixFunctionsTest { - @Test - fun testColours() { - val color = 0x123456 - val red = (color and 0xff0000) shr 16 - val green = (color and 0x00ff00) shr 8 - val blue = (color and 0x0000ff) shr 0 - - Assert.assertEquals(0x12, red) - Assert.assertEquals(0x34, green) - Assert.assertEquals(0x56, blue) - } - - @Test - fun testNewAssertions() { - class Assertion(private val target: T) { - infix fun isEqualTo(other: T) { - Assert.assertEquals(other, target) - } - - infix fun isDifferentFrom(other: T) { - Assert.assertNotEquals(other, target) - } - } - - val result = Assertion(5) - - result isEqualTo 5 - - // The following two lines are expected to fail - // result isEqualTo 6 - // result isDifferentFrom 5 - } - - @Test - fun testNewStringMethod() { - infix fun String.substringMatches(r: Regex) : List { - return r.findAll(this) - .map { it.value } - .toList() - } - - val matches = "a bc def" substringMatches ".*? ".toRegex() - Assert.assertEquals(listOf("a ", "bc "), matches) - } -} diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/lambda/LambdaKotlinUnitTest.java b/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/lambda/LambdaKotlinUnitTest.java deleted file mode 100644 index 91c777c036..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/lambda/LambdaKotlinUnitTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.baeldung.lambda; - -import kotlin.jvm.functions.Function1; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -/** - * Created by Paul Jervis on 24/04/2018. - */ -class LambdaKotlinUnitTest { - - @Test - void givenJava6_whenUsingAnonnymousClass_thenReturnLambdaResult() { - assertTrue(LambdaKt.invokeLambda(new Function1() { - @Override - public Boolean invoke(Double c) { - return c >= 0; - } - })); - } - - @Test - void givenJava8_whenUsingLambda_thenReturnLambdaResult() { - assertTrue(LambdaKt.invokeLambda(c -> c >= 0)); - } - - @Test - void givenJava8_whenCallingMethodWithStringExtension_thenImplementExtension() { - String actual = LambdaKt.extendString("Word", 90); - String expected = "Word90"; - - assertEquals(expected, actual); - } -} diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/lambda/LambdaTest.kt b/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/lambda/LambdaTest.kt deleted file mode 100644 index bddabee462..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/lambda/LambdaTest.kt +++ /dev/null @@ -1,96 +0,0 @@ -package com.baeldung.lambda - -import org.junit.jupiter.api.Assertions.assertFalse -import org.junit.jupiter.api.Assertions.assertTrue -import org.junit.jupiter.api.Test -import kotlin.test.assertEquals - -class LambdaTest { - - @Test - fun whenCallingALambda_thenPerformTheAction() { - assertEquals(9, inferredType(3)) - } - - @Test - fun whenCallingAMoreComplicatedLambda_thenPerformTheAction() { - assertEquals("500", intToBiggerString(5)) - } - - @Test - fun whenPassingALambdaObject_thenCallTriggerLambda() { - val lambda = { arg: Double -> - arg == 4.329 - } - - val result = invokeLambda(lambda) - - assertTrue(result) - } - - @Test - fun whenPassingALambdaLiteral_thenCallTriggerLambda() { - val result = invokeLambda({ - true - }) - - assertTrue(result) - } - - @Test - fun whenPassingALambdaLiteralOutsideBrackets_thenCallTriggerLambda() { - val result = invokeLambda { arg -> arg.isNaN() } - - assertFalse(result) - } - - @Test - fun whenPassingAnAnonymousFunction_thenCallTriggerLambda() { - val result = invokeLambda(fun(arg: Double): Boolean { - return arg >= 0 - }) - - assertTrue(result) - } - - @Test - fun whenUsingLambda_thenCalculateGrade() { - val gradeCalculation = getCalculationLambda() - - assertEquals(false, gradeCalculation(-40)) - assertEquals("Pass", gradeCalculation(50)) - } - - @Test - fun whenUsingReturnStatementLambda_thenCalculateGrade() { - val gradeCalculation: Int.() -> String = getCalculationLambdaWithReturn() - - assertEquals("Distinction", 80.gradeCalculation()) - assertEquals("Error", 244_234_324.gradeCalculation()) - } - - @Test - fun whenUsingAnonymousFunction_thenCalculateGrade() { - val gradeCalculation = getCalculationAnonymousFunction() - - assertEquals("Error", gradeCalculation(244_234_324)) - assertEquals("Pass", gradeCalculation(50)) - } - - @Test - fun whenPassingAFunctionReference_thenCallTriggerLambda() { - val reference = Double::isFinite - val result = invokeLambda(reference) - - assertTrue(result) - } - - @Test - fun givenArray_whenMappingArray_thenPerformCalculationOnAllElements() { - val expected = listOf("100", "200", "300", "400", "500") - val actual = manyLambda(arrayOf(1, 2, 3, 4, 5)) - - assertEquals(expected, actual) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/late/LateInitUnitTest.kt b/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/late/LateInitUnitTest.kt deleted file mode 100644 index c99e438742..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/late/LateInitUnitTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.late - -import org.junit.Test -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -class LateInitUnitTest { - - private lateinit var answer: String - - @Test(expected = UninitializedPropertyAccessException::class) - fun givenLateInit_WhenNotInitialized_ShouldThrowAnException() { - answer.length - } - - @Test - fun givenLateInit_TheIsInitialized_ReturnsTheInitializationStatus() { - assertFalse { this::answer.isInitialized } - answer = "42" - assertTrue { this::answer.isInitialized } - } -} diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/lazy/LazyUnitTest.kt b/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/lazy/LazyUnitTest.kt deleted file mode 100644 index b9b21ed4d9..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/lazy/LazyUnitTest.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.baeldung.lazy - -import org.junit.Test -import java.util.concurrent.CountDownLatch -import java.util.concurrent.Executors -import java.util.concurrent.TimeUnit -import java.util.concurrent.atomic.AtomicInteger -import kotlin.test.assertEquals - -class LazyUnitTest { - @Test - fun givenLazyValue_whenGetIt_thenShouldInitializeItOnlyOnce() { - //given - val numberOfInitializations: AtomicInteger = AtomicInteger() - val lazyValue: ClassWithHeavyInitialization by lazy { - numberOfInitializations.incrementAndGet() - ClassWithHeavyInitialization() - } - //when - println(lazyValue) - println(lazyValue) - - //then - assertEquals(numberOfInitializations.get(), 1) - } - - @Test - fun givenLazyValue_whenGetItUsingPublication_thenCouldInitializeItMoreThanOnce() { - //given - val numberOfInitializations: AtomicInteger = AtomicInteger() - val lazyValue: ClassWithHeavyInitialization by lazy(LazyThreadSafetyMode.PUBLICATION) { - numberOfInitializations.incrementAndGet() - ClassWithHeavyInitialization() - } - val executorService = Executors.newFixedThreadPool(2) - val countDownLatch = CountDownLatch(1) - //when - executorService.submit { countDownLatch.await(); println(lazyValue) } - executorService.submit { countDownLatch.await(); println(lazyValue) } - countDownLatch.countDown() - - //then - executorService.shutdown() - executorService.awaitTermination(5, TimeUnit.SECONDS) - //assertEquals(numberOfInitializations.get(), 2) - } - - class ClassWithHeavyInitialization { - - } - - - lateinit var a: String - @Test - fun givenLateInitProperty_whenAccessItAfterInit_thenPass() { - //when - a = "it" - println(a) - - //then not throw - } - - @Test(expected = UninitializedPropertyAccessException::class) - fun givenLateInitProperty_whenAccessItWithoutInit_thenThrow() { - //when - println(a) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/nullsafety/NullSafetyTest.kt b/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/nullsafety/NullSafetyTest.kt deleted file mode 100644 index 66fc043581..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/nullsafety/NullSafetyTest.kt +++ /dev/null @@ -1,161 +0,0 @@ -package com.baeldung.nullsafety - -import org.junit.Test -import kotlin.test.assertEquals -import kotlin.test.assertFailsWith -import kotlin.test.assertNull -import kotlin.test.assertTrue - - -class NullSafetyTest { - - @Test - fun givenNonNullableField_whenAssignValueToIt_thenNotNeedToCheckAgainstNull() { - //given - var a: String = "value" - //a = null compilation error - - //then - assertEquals(a.length, 5) - } - - @Test - fun givenNullableField_whenReadValue_thenNeedToCheckAgainstNull() { - //given - var b: String? = "value" - b = null - - //when - if (b != null) { - - } else { - assertNull(b) - } - } - - @Test - fun givenComplexObject_whenUseSafeCall_thenShouldChainCallsResultingWithValue() { - //given - val p: Person? = Person(Country("ENG")) - - //when - val res = p?.country?.code - - //then - assertEquals(res, "ENG") - } - - @Test - fun givenComplexObject_whenUseSafeCall_thenShouldChainCallsResultingWithNull() { - //given - val p: Person? = Person(Country(null)) - - //when - val res = p?.country?.code - - //then - assertNull(res) - } - - @Test - fun givenCollectionOfObjects_whenUseLetOperator_thenShouldApplyActionOnlyOnNonNullValue() { - //given - val firstName = "Tom" - val secondName = "Michael" - val names: List = listOf(firstName, null, secondName) - - //when - var res = listOf() - for (item in names) { - item?.let { res = res.plus(it); it } - ?.also{it -> println("non nullable value: $it")} - } - - //then - assertEquals(2, res.size) - assertTrue { res.contains(firstName) } - assertTrue { res.contains(secondName) } - } - - @Test - fun fivenCollectionOfObject_whenUseRunOperator_thenExecuteActionOnNonNullValue(){ - //given - val firstName = "Tom" - val secondName = "Michael" - val names: List = listOf(firstName, null, secondName) - - //when - var res = listOf() - for (item in names) { - item?.run{res = res.plus(this)} - } - - //then - assertEquals(2, res.size) - assertTrue { res.contains(firstName) } - assertTrue { res.contains(secondName) } - } - - @Test - fun givenNullableReference_whenUseElvisOperator_thenShouldReturnValueIfReferenceIsNotNull() { - //given - val value: String? = "name" - - //when - val res = value?.length ?: -1 - - //then - assertEquals(res, 4) - } - - @Test - fun givenNullableReference_whenUseElvisOperator_thenShouldReturnDefaultValueIfReferenceIsNull() { - //given - val value: String? = null - - //when - val res = value?.length ?: -1 - - //then - assertEquals(res, -1) - } - - @Test - fun givenNullableField_whenUsingDoubleExclamationMarkOperatorOnNull_thenThrowNPE() { - //given - var b: String? = "value" - b = null - - //when - assertFailsWith { - b!!.length - } - } - - @Test - fun givenNullableField_whenUsingDoubleExclamationMarkOperatorOnNotNull_thenReturnValue() { - //given - val b: String? = "value" - - //then - assertEquals(b!!.length, 5) - } - - @Test - fun givenNullableList_whenUseFilterNotNullMethod_thenRemoveALlNullValues() { - //given - val list: List = listOf("a", null, "b") - - //when - val res = list.filterNotNull() - - //then - assertEquals(res.size, 2) - assertTrue { res.contains("a") } - assertTrue { res.contains("b") } - } -} - -data class Person(val country: Country?) - -data class Country(val code: String?) \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt b/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt deleted file mode 100644 index cb3ed98006..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/scope/ScopeFunctionsUnitTest.kt +++ /dev/null @@ -1,143 +0,0 @@ -package com.baeldung.scope - -import org.junit.Test -import kotlin.test.assertTrue - - -class ScopeFunctionsUnitTest { - - class Logger { - - var called : Boolean = false - - fun info(message: String) { - called = true - } - - fun wasCalled() = called - } - - @Test - fun shouldTransformWhenLetFunctionUsed() { - val stringBuider = StringBuilder() - val numberOfCharacters = stringBuider.let { - it.append("This is a transformation function.") - it.append("It takes a StringBuilder instance and returns the number of characters in the generated String") - it.length - } - - assertTrue { - numberOfCharacters == 128 - } - } - - @Test - fun shouldHandleNullabilityWhenLetFunctionUsed() { - - val message: String? = "hello there!" - val charactersInMessage = message?.let { - "At this point is safe to reference the variable. Let's print the message: $it" - } ?: "default value" - - assertTrue { - charactersInMessage.equals("At this point is safe to reference the variable. Let's print the message: hello there!") - } - - val aNullMessage = null - val thisIsNull = aNullMessage?.let { - "At this point it would be safe to reference the variable. But it will not really happen because it is null. Let's reference: $it" - } ?: "default value" - - assertTrue { - thisIsNull.equals("default value") - } - } - - @Test - fun shouldInitializeObjectWhenUsingApply() { - val aStudent = Student().apply { - studentId = "1234567" - name = "Mary" - surname = "Smith" - } - - assertTrue { - aStudent.name.equals("Mary") - } - } - - @Test - fun shouldAllowBuilderStyleObjectDesignWhenApplyUsedInClassMethods() { - val teacher = Teacher() - .setId(1000) - .setName("Martha") - .setSurname("Spector") - - assertTrue { - teacher.surname.equals("Spector") - } - } - - @Test - fun shouldAllowSideEffectWhenUsingAlso() { - val restClient = RestClient("http://www.someurl.com") - - val logger = Logger() - - val headers = restClient - .getResponse() - .also { logger.info(it.toString()) } - .headers - - assertTrue { - logger.wasCalled() && headers.headerInfo.equals("some header info") - } - - } - - @Test - fun shouldInitializeFieldWhenAlsoUsed() { - val aStudent = Student().also { it.name = "John"} - - assertTrue { - aStudent.name.equals("John") - } - } - - @Test - fun shouldLogicallyGroupObjectCallsWhenUsingWith() { - val bankAccount = BankAccount(1000) - with (bankAccount) { - checkAuthorization("someone") - addPayee("some payee") - makePayment("payment information") - } - } - - @Test - fun shouldConvertObjectWhenRunUsed() { - val stringBuider = StringBuilder() - val numberOfCharacters = stringBuider.run { - append("This is a transformation function.") - append("It takes a StringBuilder instance and returns the number of characters in the generated String") - length - } - - assertTrue { - numberOfCharacters == 128 - } - } - - @Test - fun shouldHandleNullabilityWhenRunIsUsed() { - val message: String? = "hello there!" - val charactersInMessage = message?.run { - "At this point is safe to reference the variable. Let's print the message: $this" - } ?: "default value" - - assertTrue { - charactersInMessage.equals("At this point is safe to reference the variable. Let's print the message: hello there!") - } - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/structuraljump/StructuralJumpUnitTest.kt b/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/structuraljump/StructuralJumpUnitTest.kt deleted file mode 100644 index 88011ab396..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-2/src/test/kotlin/com/baeldung/structuraljump/StructuralJumpUnitTest.kt +++ /dev/null @@ -1,121 +0,0 @@ -package com.baeldung.structuraljump - -import org.junit.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse - -class StructuralJumpUnitTest { - - @Test - fun givenLoop_whenBreak_thenComplete() { - var value = "" - for (i in "hello_world") { - if (i == '_') - break - value += i.toString() - } - assertEquals("hello", value) - } - @Test - fun givenLoop_whenBreakWithLabel_thenComplete() { - var value = "" - outer_loop@ for (i in 'a'..'d') { - for (j in 1..3) { - value += "" + i + j - if (i == 'b' && j == 1) - break@outer_loop - } - } - assertEquals("a1a2a3b1", value) - } - - @Test - fun givenLoop_whenContinue_thenComplete() { - var result = "" - for (i in "hello_world") { - if (i == '_') - continue - result += i - } - assertEquals("helloworld", result) - } - @Test - fun givenLoop_whenContinueWithLabel_thenComplete() { - var result = "" - outer_loop@ for (i in 'a'..'c') { - for (j in 1..3) { - if (i == 'b') - continue@outer_loop - result += "" + i + j - } - } - assertEquals("a1a2a3c1c2c3", result) - } - - @Test - fun givenLambda_whenReturn_thenComplete() { - var result = returnInLambda(); - assertEquals("hello", result) - } - - private fun returnInLambda(): String { - var result = "" - "hello_world".forEach { - // non-local return directly to the caller - if (it == '_') return result - result += it.toString() - } - //this line won't be reached - return result; - } - - @Test - fun givenLambda_whenReturnWithExplicitLabel_thenComplete() { - var result = "" - "hello_world".forEach lit@{ - if (it == '_') { - // local return to the caller of the lambda, i.e. the forEach loop - return@lit - } - result += it.toString() - } - assertEquals("helloworld", result) - } - - @Test - fun givenLambda_whenReturnWithImplicitLabel_thenComplete() { - var result = "" - "hello_world".forEach { - if (it == '_') { - // local return to the caller of the lambda, i.e. the forEach loop - return@forEach - } - result += it.toString() - } - assertEquals("helloworld", result) - } - - @Test - fun givenAnonymousFunction_return_thenComplete() { - var result = "" - "hello_world".forEach(fun(element) { - // local return to the caller of the anonymous fun, i.e. the forEach loop - if (element == '_') return - result += element.toString() - }) - assertEquals("helloworld", result) - } - - @Test - fun givenAnonymousFunction_returnToLabel_thenComplete() { - var result = "" - run loop@{ - "hello_world".forEach { - // non-local return from the lambda passed to run - if (it == '_') return@loop - result += it.toString() - } - } - assertEquals("hello", result) - } -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop-2/README.md b/core-kotlin-modules/core-kotlin-lang-oop-2/README.md deleted file mode 100644 index a62a25c01d..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop-2/README.md +++ /dev/null @@ -1,11 +0,0 @@ -## Core Kotlin Lang OOP - -This module contains articles about Object-Oriented Programming in Kotlin - -### Relevant articles: - -- [Generics in Kotlin](https://www.baeldung.com/kotlin-generics) -- [Delegated Properties in Kotlin](https://www.baeldung.com/kotlin-delegated-properties) -- [Delegation Pattern in Kotlin](https://www.baeldung.com/kotlin-delegation-pattern) -- [Anonymous Inner Classes in Kotlin](https://www.baeldung.com/kotlin/anonymous-inner-classes) -- [[<-- Prev]](/core-kotlin-modules/core-kotlin-lang-oop) diff --git a/core-kotlin-modules/core-kotlin-lang-oop-2/pom.xml b/core-kotlin-modules/core-kotlin-lang-oop-2/pom.xml deleted file mode 100644 index f0adea121e..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop-2/pom.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - 4.0.0 - core-kotlin-lang-oop-2 - core-kotlin-lang-oop-2 - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - - - org.assertj - assertj-core - ${assertj.version} - test - - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/anonymous/Anonymous.kt b/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/anonymous/Anonymous.kt deleted file mode 100644 index ea471f5d00..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/anonymous/Anonymous.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.baeldung.anonymous - -import java.io.Serializable -import java.nio.channels.Channel - -fun main() { - val channel = object : Channel { - override fun isOpen() = false - - override fun close() { - } - } - - val maxEntries = 10 - val lruCache = object : LinkedHashMap(10, 0.75f) { - - override fun removeEldestEntry(eldest: MutableMap.MutableEntry?): Boolean { - return size > maxEntries - } - } - - val map = object : LinkedHashMap() { - // omitted - } - - val serializableChannel = object : Channel, Serializable { - override fun isOpen(): Boolean { - TODO("Not yet implemented") - } - - override fun close() { - TODO("Not yet implemented") - } - } - - val obj = object { - val question = "answer" - val answer = 42 - } - println("The ${obj.question} is ${obj.answer}") -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/generic/Reified.kt b/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/generic/Reified.kt deleted file mode 100644 index 37a632fe41..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/generic/Reified.kt +++ /dev/null @@ -1,6 +0,0 @@ -inline fun Iterable<*>.filterIsInstance() = filter { it is T } - -fun main(args: Array) { - val set = setOf("1984", 2, 3, "Brave new world", 11) - println(set.filterIsInstance()) -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/kotlin/delegates/Database.kt b/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/kotlin/delegates/Database.kt deleted file mode 100644 index 9ea9f027fc..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/kotlin/delegates/Database.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.baeldung.kotlin.delegates - -val data = arrayOf>( - mutableMapOf( - "id" to 1, - "name" to "George", - "age" to 4 - ), - mutableMapOf( - "id" to 2, - "name" to "Charlotte", - "age" to 2 - ) -) - -class NoRecordFoundException(id: Int) : Exception("No record found for id $id") { - init { - println("No record found for ID $id") - } -} - -fun queryForValue(field: String, id: Int): Any { - println("Loading record $id from the fake database") - val value = data.firstOrNull { it["id"] == id } - ?.get(field) ?: throw NoRecordFoundException(id) - println("Loaded value $value for field $field of record $id") - return value -} - -fun update(field: String, id: Int, value: Any?) { - println("Updating field $field of record $id to value $value in the fake database") - data.firstOrNull { it["id"] == id } - ?.put(field, value) - ?: throw NoRecordFoundException(id) -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/kotlin/delegates/DatabaseDelegate.kt b/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/kotlin/delegates/DatabaseDelegate.kt deleted file mode 100644 index c1c0f8823c..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/kotlin/delegates/DatabaseDelegate.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.kotlin.delegates - -import kotlin.properties.ReadWriteProperty -import kotlin.reflect.KProperty - -class DatabaseDelegate(private val field: String, private val id: Int) : ReadWriteProperty { - override fun getValue(thisRef: R, property: KProperty<*>): T = - queryForValue(field, id) as T - - override fun setValue(thisRef: R, property: KProperty<*>, value: T) { - update(field, id, value) - } -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegation.kt b/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegation.kt deleted file mode 100644 index 8e261aacf2..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegation.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.baeldung.kotlin.delegates - -import java.util.concurrent.locks.ReentrantLock -import kotlin.concurrent.withLock - -interface Producer { - - fun produce(): String -} - -class ProducerImpl : Producer { - - override fun produce() = "ProducerImpl" -} - -class EnhancedProducer(private val delegate: Producer) : Producer by delegate { - - override fun produce() = "${delegate.produce()} and EnhancedProducer" -} - -interface MessageService { - - fun processMessage(message: String): String -} - -class MessageServiceImpl : MessageService { - override fun processMessage(message: String): String { - return "MessageServiceImpl: $message" - } -} - -interface UserService { - - fun processUser(userId: String): String -} - -class UserServiceImpl : UserService { - - override fun processUser(userId: String): String { - return "UserServiceImpl: $userId" - } -} - -class CompositeService : UserService by UserServiceImpl(), MessageService by MessageServiceImpl() - -interface Service { - - val seed: Int - - fun serve(action: (Int) -> Unit) -} - -class ServiceImpl : Service { - - override val seed = 1 - - override fun serve(action: (Int) -> Unit) { - action(seed) - } -} - -class ServiceDecorator : Service by ServiceImpl() { - override val seed = 2 -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/kotlin/delegates/User.kt b/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/kotlin/delegates/User.kt deleted file mode 100644 index 7788305ea1..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop-2/src/main/kotlin/com/baeldung/kotlin/delegates/User.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.baeldung.kotlin.delegates - -class User(val id: Int) { - var name: String by DatabaseDelegate("name", id) - var age: Int by DatabaseDelegate("age", id) -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop-2/src/test/kotlin/com/baeldung/GenericsTest.kt b/core-kotlin-modules/core-kotlin-lang-oop-2/src/test/kotlin/com/baeldung/GenericsTest.kt deleted file mode 100644 index b189d0f483..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop-2/src/test/kotlin/com/baeldung/GenericsTest.kt +++ /dev/null @@ -1,143 +0,0 @@ -package com.baeldung.kotlin - -import org.junit.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class GenericsTest { - - @Test - fun givenParametrizeClass_whenInitializeItWithSpecificType_thenShouldBeParameterized() { - //given - val parameterizedClass = ParameterizedClass("string-value") - - //when - val res = parameterizedClass.getValue() - - //then - assertTrue(res is String) - } - - @Test - fun givenParametrizeClass_whenInitializeIt_thenShouldBeParameterizedByInferredType() { - //given - val parameterizedClass = ParameterizedClass("string-value") - - //when - val res = parameterizedClass.getValue() - - //then - assertTrue(res is String) - } - - @Test - fun givenParameterizedProducerByOutKeyword_whenGetValue_thenCanAssignItToSuperType() { - //given - val parameterizedProducer = ParameterizedProducer("string") - - //when - val ref: ParameterizedProducer = parameterizedProducer - - //then - assertTrue(ref is ParameterizedProducer) - } - - @Test - fun givenParameterizedConsumerByInKeyword_whenGetValue_thenCanAssignItToSubType() { - //given - val parameterizedConsumer = ParameterizedConsumer() - - //when - val ref: ParameterizedConsumer = parameterizedConsumer - - //then - assertTrue(ref is ParameterizedConsumer) - } - - @Test - fun givenTypeProjections_whenOperateOnTwoList_thenCanAcceptListOfSubtypes() { - //given - val ints: Array = arrayOf(1, 2, 3) - val any: Array = arrayOfNulls(3) - - //when - copy(ints, any) - - //then - assertEquals(any[0], 1) - assertEquals(any[1], 2) - assertEquals(any[2], 3) - - } - - fun copy(from: Array, to: Array) { - assert(from.size == to.size) - for (i in from.indices) - to[i] = from[i] - } - - @Test - fun givenTypeProjection_whenHaveArrayOfIn_thenShouldAddElementsOfSubtypesToIt() { - //given - val objects: Array = arrayOfNulls(1) - - //when - fill(objects, 1) - - //then - assertEquals(objects[0], 1) - } - - fun fill(dest: Array, value: Int) { - dest[0] = value - } - - @Test - fun givenStartProjection_whenPassAnyType_thenCompile() { - //given - val array = arrayOf(1,2,3) - - //then - printArray(array) - - } - - fun printArray(array: Array<*>) { - array.forEach { println(it) } - } - - @Test - fun givenFunctionWithDefinedGenericConstraints_whenCallWithProperType_thenCompile(){ - //given - val listOfInts = listOf(5,2,3,4,1) - - //when - val sorted = sort(listOfInts) - - //then - assertEquals(sorted, listOf(1,2,3,4,5)) - } - - fun > sort(list: List): List{ - return list.sorted() - } - - class ParameterizedClass(private val value: A) { - - fun getValue(): A { - return value - } - } - - class ParameterizedProducer(private val value: T) { - fun get(): T { - return value - } - } - - class ParameterizedConsumer { - fun toString(value: T): String { - return value.toString() - } - } -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop-2/src/test/kotlin/com/baeldung/kotlin/delegates/DatabaseDelegatesTest.kt b/core-kotlin-modules/core-kotlin-lang-oop-2/src/test/kotlin/com/baeldung/kotlin/delegates/DatabaseDelegatesTest.kt deleted file mode 100644 index fc50730dfa..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop-2/src/test/kotlin/com/baeldung/kotlin/delegates/DatabaseDelegatesTest.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.baeldung.kotlin.delegates - -import org.junit.Test -import kotlin.test.assertEquals - -class DatabaseDelegatesTest { - @Test - fun testGetKnownFields() { - val user = User(1) - assertEquals("George", user.name) - assertEquals(4, user.age) - } - - @Test - fun testSetKnownFields() { - val user = User(2) - user.age = 3 - assertEquals(3, user.age) - } - - @Test(expected = NoRecordFoundException::class) - fun testGetKnownField() { - val user = User(3) - user.name - } -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop-2/src/test/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegationTest.kt b/core-kotlin-modules/core-kotlin-lang-oop-2/src/test/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegationTest.kt deleted file mode 100644 index e65032acd4..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop-2/src/test/kotlin/com/baeldung/kotlin/delegates/InterfaceDelegationTest.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.kotlin.delegates - -import org.assertj.core.api.Assertions.assertThat -import org.junit.Test - -class InterfaceDelegationTest { - - @Test - fun `when delegated implementation is used then it works as expected`() { - val producer = EnhancedProducer(ProducerImpl()) - assertThat(producer.produce()).isEqualTo("ProducerImpl and EnhancedProducer") - } - - @Test - fun `when composite delegation is used then it works as expected`() { - val service = CompositeService() - assertThat(service.processMessage("message")).isEqualTo("MessageServiceImpl: message") - assertThat(service.processUser("user")).isEqualTo("UserServiceImpl: user") - } - - @Test - fun `when decoration is used then delegate knows nothing about it`() { - val service = ServiceDecorator() - service.serve { - assertThat(it).isEqualTo(1) - } - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/README.md b/core-kotlin-modules/core-kotlin-lang-oop/README.md deleted file mode 100644 index 0c1aeb7850..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/README.md +++ /dev/null @@ -1,17 +0,0 @@ -## Core Kotlin Lang OOP - -This module contains articles about Object-Oriented Programming in Kotlin - -### Relevant articles: - -- [Data Classes in Kotlin](https://www.baeldung.com/kotlin-data-classes) -- [Sealed Classes in Kotlin](https://www.baeldung.com/kotlin-sealed-classes) -- [Extension Methods in Kotlin](https://www.baeldung.com/kotlin-extension-methods) -- [Objects in Kotlin](https://www.baeldung.com/kotlin-objects) -- [Working with Enums in Kotlin](https://www.baeldung.com/kotlin-enum) -- [Kotlin Constructors](https://www.baeldung.com/kotlin-constructors) -- [Kotlin Nested and Inner Classes](https://www.baeldung.com/kotlin-inner-classes) -- [Guide to Kotlin Interfaces](https://www.baeldung.com/kotlin-interfaces) -- [Inline Classes in Kotlin](https://www.baeldung.com/kotlin-inline-classes) -- [Static Methods Behavior in Kotlin](https://www.baeldung.com/kotlin-static-methods) -- More articles: [[next -->]](/core-kotlin-modules/core-kotlin-lang-oop-2) diff --git a/core-kotlin-modules/core-kotlin-lang-oop/pom.xml b/core-kotlin-modules/core-kotlin-lang-oop/pom.xml deleted file mode 100644 index 03fc80f07d..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/pom.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - 4.0.0 - core-kotlin-lang-oop - core-kotlin-lang-oop - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - - - org.assertj - assertj-core - ${assertj.version} - test - - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/java/com/baeldung/constructor/Car.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/java/com/baeldung/constructor/Car.kt deleted file mode 100644 index 72b8d330e8..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/java/com/baeldung/constructor/Car.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.constructor - -class Car { - val id: String - val type: String - - constructor(id: String, type: String) { - this.id = id - this.type = type - } - -} - -fun main(args: Array) { - val car = Car("1", "sport") - val s= Car("2", "suv") -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/java/com/baeldung/constructor/Employee.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/java/com/baeldung/constructor/Employee.kt deleted file mode 100644 index 4483bfcf08..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/java/com/baeldung/constructor/Employee.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.constructor - -class Employee(name: String, val salary: Int): Person(name) \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/java/com/baeldung/constructor/Person.java b/core-kotlin-modules/core-kotlin-lang-oop/src/main/java/com/baeldung/constructor/Person.java deleted file mode 100644 index 57911b24ee..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/java/com/baeldung/constructor/Person.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.constructor; - -class PersonJava { - final String name; - final String surname; - final Integer age; - - public PersonJava(String name, String surname) { - this.name = name; - this.surname = surname; - this.age = null; - } - - public PersonJava(String name, String surname, Integer age) { - this.name = name; - this.surname = surname; - this.age = age; - } -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/java/com/baeldung/dataclass/Movie.java b/core-kotlin-modules/core-kotlin-lang-oop/src/main/java/com/baeldung/dataclass/Movie.java deleted file mode 100644 index 7eac98fe2a..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/java/com/baeldung/dataclass/Movie.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.baeldung.dataclass; - -public class Movie { - - private String name; - private String studio; - private float rating; - - public Movie(String name, String studio, float rating) { - this.name = name; - this.studio = studio; - this.rating = rating; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getStudio() { - return studio; - } - - public void setStudio(String studio) { - this.studio = studio; - } - - public float getRating() { - return rating; - } - - public void setRating(float rating) { - this.rating = rating; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + Float.floatToIntBits(rating); - result = prime * result + ((studio == null) ? 0 : studio.hashCode()); - - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - - if (obj == null) - return false; - - if (getClass() != obj.getClass()) - return false; - - Movie other = (Movie) obj; - - if (name == null) { - if (other.name != null) - return false; - - } else if (!name.equals(other.name)) - return false; - - if (Float.floatToIntBits(rating) != Float.floatToIntBits(other.rating)) - return false; - - if (studio == null) { - if (other.studio != null) - return false; - - } else if (!studio.equals(other.studio)) - return false; - - return true; - } - - @Override - public String toString() { - return "Movie [name=" + name + ", studio=" + studio + ", rating=" + rating + "]"; - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/constructor/Person.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/constructor/Person.kt deleted file mode 100644 index 3779d74541..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/constructor/Person.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.baeldung.constructor - -open class Person( - val name: String, - val age: Int? = null -) { - val upperCaseName: String = name.toUpperCase() - - init { - println("Hello, I'm $name") - - if (age != null && age < 0) { - throw IllegalArgumentException("Age cannot be less than zero!") - } - } - - init { - println("upperCaseName is $upperCaseName") - } - -} - -fun main(args: Array) { - val person = Person("John") - val personWithAge = Person("John", 22) -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/dataclass/Movie.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/dataclass/Movie.kt deleted file mode 100644 index c0c15b2516..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/dataclass/Movie.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.dataclass - -data class Movie(val name: String, val studio: String, var rating: Float) \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/dataclass/Sandbox.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/dataclass/Sandbox.kt deleted file mode 100644 index d47909bf29..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/dataclass/Sandbox.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.baeldung.dataclass - -fun main(args: Array) { - - val movie = Movie("Whiplash", "Sony Pictures", 8.5F) - - println(movie.name) //Whiplash - println(movie.studio) //Sony Pictures - println(movie.rating) //8.5 - - movie.rating = 9F - - println(movie.toString()) //Movie(name=Whiplash, studio=Sony Pictures, rating=9.0) - - val betterRating = movie.copy(rating = 9.5F) - println(betterRating.toString()) //Movie(name=Whiplash, studio=Sony Pictures, rating=9.5) - - movie.component1() //name - movie.component2() //studio - movie.component3() //rating - - val(name, studio, rating) = movie - - fun getMovieInfo() = movie - val(namef, studiof, ratingf) = getMovieInfo() -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/enums/CardType.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/enums/CardType.kt deleted file mode 100644 index 69cfce5601..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/enums/CardType.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.baeldung.enums - -enum class CardType(val color: String) : ICardLimit { - SILVER("gray") { - override fun getCreditLimit() = 100000 - override fun calculateCashbackPercent() = 0.25f - }, - GOLD("yellow") { - override fun getCreditLimit() = 200000 - override fun calculateCashbackPercent(): Float = 0.5f - }, - PLATINUM("black") { - override fun getCreditLimit() = 300000 - override fun calculateCashbackPercent() = 0.75f - }; - - companion object { - fun getCardTypeByColor(color: String) = values().firstOrNull { it.color == color } - fun getCardTypeByName(name: String) = valueOf(name.toUpperCase()) - } - - abstract fun calculateCashbackPercent(): Float -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/enums/ICardLimit.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/enums/ICardLimit.kt deleted file mode 100644 index 7994822a52..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/enums/ICardLimit.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.baeldung.enums - -interface ICardLimit { - fun getCreditLimit(): Int -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/inline/classes/CircleRadius.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/inline/classes/CircleRadius.kt deleted file mode 100644 index 5b46b9570f..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/inline/classes/CircleRadius.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.inline.classes - -interface Drawable { - fun draw() -} - -inline class CircleRadius(private val circleRadius : Double) : Drawable { - val diameterOfCircle get() = 2 * circleRadius - fun areaOfCircle() = 3.14 * circleRadius * circleRadius - - override fun draw() { - println("Draw my circle") - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/inline/classes/InlineDoubleWrapper.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/inline/classes/InlineDoubleWrapper.kt deleted file mode 100644 index 430fa509da..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/inline/classes/InlineDoubleWrapper.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.inline.classes - -inline class InlineDoubleWrapper(val doubleValue : Double) \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/interfaces/ConflictingInterfaces.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/interfaces/ConflictingInterfaces.kt deleted file mode 100644 index 630afbdae7..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/interfaces/ConflictingInterfaces.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.baeldung.interfaces - -interface BaseInterface { - fun someMethod(): String -} - -interface FirstChildInterface : BaseInterface { - override fun someMethod(): String { - return("Hello, from someMethod in FirstChildInterface") - } -} - -interface SecondChildInterface : BaseInterface { - override fun someMethod(): String { - return("Hello, from someMethod in SecondChildInterface") - } -} - -class ChildClass : FirstChildInterface, SecondChildInterface { - override fun someMethod(): String { - return super.someMethod() - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/interfaces/InterfaceDelegation.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/interfaces/InterfaceDelegation.kt deleted file mode 100644 index 591fde0689..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/interfaces/InterfaceDelegation.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.interfaces - -interface MyInterface { - fun someMethod(): String -} - -class MyClass() : MyInterface { - override fun someMethod(): String { - return("Hello, World!") - } -} - -class MyDerivedClass(myInterface: MyInterface) : MyInterface by myInterface \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/interfaces/MultipleInterfaces.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/interfaces/MultipleInterfaces.kt deleted file mode 100644 index 105a85cbb3..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/interfaces/MultipleInterfaces.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.baeldung.interfaces - -interface FirstInterface { - fun someMethod(): String - - fun anotherMethod(): String { - return("Hello, from anotherMethod in FirstInterface") - } -} - -interface SecondInterface { - fun someMethod(): String { - return("Hello, from someMethod in SecondInterface") - } - - fun anotherMethod(): String { - return("Hello, from anotherMethod in SecondInterface") - } -} - -class SomeClass: FirstInterface, SecondInterface { - override fun someMethod(): String { - return("Hello, from someMethod in SomeClass") - } - - override fun anotherMethod(): String { - return("Hello, from anotherMethod in SomeClass") - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/interfaces/SimpleInterface.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/interfaces/SimpleInterface.kt deleted file mode 100644 index 0758549dde..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/interfaces/SimpleInterface.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.interfaces - -interface SimpleInterface { - val firstProp: String - val secondProp: String - get() = "Second Property" - fun firstMethod(): String - fun secondMethod(): String { - println("Hello, from: " + secondProp) - return "" - } -} - -class SimpleClass: SimpleInterface { - override val firstProp: String = "First Property" - override val secondProp: String - get() = "Second Property, Overridden!" - override fun firstMethod(): String { - return("Hello, from: " + firstProp) - } - override fun secondMethod(): String { - return("Hello, from: " + secondProp + firstProp) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/kotlin/Sealed.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/kotlin/Sealed.kt deleted file mode 100644 index 96e54716b3..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/kotlin/Sealed.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.kotlin - -sealed class Result { - abstract fun map(func: (S) -> R) : Result - abstract fun mapFailure(func: (F) -> R) : Result - abstract fun get() : S? -} - -data class Success(val success: S) : Result() { - override fun map(func: (S) -> R) : Result = Success(func(success)) - override fun mapFailure(func: (F) -> R): Result = Success(success) - override fun get(): S? = success -} - -data class Failure(val failure: F) : Result() { - override fun map(func: (S) -> R) : Result = Failure(failure) - override fun mapFailure(func: (F) -> R): Result = Failure(func(failure)) - override fun get(): S? = null -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/kotlin/StringUtil.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/kotlin/StringUtil.kt deleted file mode 100644 index ca57b2965e..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/kotlin/StringUtil.kt +++ /dev/null @@ -1,9 +0,0 @@ -@file:JvmName("Strings") -package com.baeldung.kotlin - -fun String.escapeForXml() : String { - return this - .replace("&", "&") - .replace("<", "<") - .replace(">", ">") -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/nested/Computer.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/nested/Computer.kt deleted file mode 100644 index ee01c06646..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/nested/Computer.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.baeldung.nested - -import org.slf4j.Logger -import org.slf4j.LoggerFactory - -class Computer(val model: String) { - - companion object { - const val originCountry = "China" - fun getBuiltDate(): String { - return "2018-05-23" - } - - val log: Logger = LoggerFactory.getLogger(Computer::class.java) - } - - //Nested class - class MotherBoard(val manufacturer: String) { - fun getInfo() = "Made by $manufacturer installed in $originCountry - ${getBuiltDate()}" - } - - //Inner class - inner class HardDisk(val sizeInGb: Int) { - fun getInfo() = "Installed on ${this@Computer} with $sizeInGb GB" - } - - interface Switcher { - fun on(): String - } - - interface Protector { - fun smart() - } - - fun powerOn(): String { - //Local class - var defaultColor = "Blue" - - class Led(val color: String) { - fun blink(): String { - return "blinking $color" - } - - fun changeDefaultPowerOnColor() { - defaultColor = "Violet" - } - } - - val powerLed = Led("Green") - log.debug("defaultColor is $defaultColor") - powerLed.changeDefaultPowerOnColor() - log.debug("defaultColor changed inside Led class to $defaultColor") - //Anonymous object - val powerSwitch = object : Switcher, Protector { - override fun on(): String { - return powerLed.blink() - } - - override fun smart() { - log.debug("Smart protection is implemented") - } - - fun changeDefaultPowerOnColor() { - defaultColor = "Yellow" - } - } - powerSwitch.changeDefaultPowerOnColor() - log.debug("defaultColor changed inside powerSwitch anonymous object to $defaultColor") - return powerSwitch.on() - } - - override fun toString(): String { - return "Computer(model=$model)" - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/static/ConsoleUtils.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/static/ConsoleUtils.kt deleted file mode 100644 index 23c7cfb11a..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/static/ConsoleUtils.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.baeldung.static - -class ConsoleUtils { - companion object { - @JvmStatic - fun debug(debugMessage : String) { - println("[DEBUG] $debugMessage") - } - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/static/LoggingUtils.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/static/LoggingUtils.kt deleted file mode 100644 index e67addc9ea..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/main/kotlin/com/baeldung/static/LoggingUtils.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.baeldung.static - -fun debug(debugMessage : String) { - println("[DEBUG] $debugMessage") -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/java/com/baeldung/kotlin/StringUtilUnitTest.java b/core-kotlin-modules/core-kotlin-lang-oop/src/test/java/com/baeldung/kotlin/StringUtilUnitTest.java deleted file mode 100644 index c7ef18b879..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/java/com/baeldung/kotlin/StringUtilUnitTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.kotlin; - -import kotlin.text.StringsKt; -import org.junit.Assert; -import org.junit.Test; - -import static com.baeldung.kotlin.Strings.*; - - -public class StringUtilUnitTest { - - @Test - public void shouldEscapeXmlTagsInString() { - String xml = "hi"; - - String escapedXml = escapeForXml(xml); - - Assert.assertEquals("<a>hi</a>", escapedXml); - } - - @Test - public void callingBuiltInKotlinExtensionMethod() { - String name = "john"; - - String capitalizedName = StringsKt.capitalize(name); - - Assert.assertEquals("John", capitalizedName); - } - -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/enums/CardTypeUnitTest.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/enums/CardTypeUnitTest.kt deleted file mode 100644 index 525faebd55..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/enums/CardTypeUnitTest.kt +++ /dev/null @@ -1,84 +0,0 @@ -package com.baeldung.enums - -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test - -internal class CardTypeUnitTest { - - @Test - fun givenSilverCardType_whenCalculateCashbackPercent_thenReturnCashbackValue() { - assertEquals(0.25f, CardType.SILVER.calculateCashbackPercent()) - } - - @Test - fun givenGoldCardType_whenCalculateCashbackPercent_thenReturnCashbackValue() { - assertEquals(0.5f, CardType.GOLD.calculateCashbackPercent()) - } - - @Test - fun givenPlatinumCardType_whenCalculateCashbackPercent_thenReturnCashbackValue() { - assertEquals(0.75f, CardType.PLATINUM.calculateCashbackPercent()) - } - - @Test - fun givenSilverCardType_whenGetCreditLimit_thenReturnCreditLimit() { - assertEquals(100000, CardType.SILVER.getCreditLimit()) - } - - @Test - fun givenGoldCardType_whenGetCreditLimit_thenReturnCreditLimit() { - assertEquals(200000, CardType.GOLD.getCreditLimit()) - } - - @Test - fun givenPlatinumCardType_whenGetCreditLimit_thenReturnCreditLimit() { - assertEquals(300000, CardType.PLATINUM.getCreditLimit()) - } - - @Test - fun givenSilverCardType_whenCheckColor_thenReturnColor() { - assertEquals("gray", CardType.SILVER.color) - } - - @Test - fun givenGoldCardType_whenCheckColor_thenReturnColor() { - assertEquals("yellow", CardType.GOLD.color) - } - - @Test - fun givenPlatinumCardType_whenCheckColor_thenReturnColor() { - assertEquals("black", CardType.PLATINUM.color) - } - - @Test - fun whenGetCardTypeByColor_thenSilverCardType() { - Assertions.assertEquals(CardType.SILVER, CardType.getCardTypeByColor("gray")) - } - - @Test - fun whenGetCardTypeByColor_thenGoldCardType() { - Assertions.assertEquals(CardType.GOLD, CardType.getCardTypeByColor("yellow")) - } - - @Test - fun whenGetCardTypeByColor_thenPlatinumCardType() { - Assertions.assertEquals(CardType.PLATINUM, CardType.getCardTypeByColor("black")) - } - - @Test - fun whenGetCardTypeByName_thenSilverCardType() { - Assertions.assertEquals(CardType.SILVER, CardType.getCardTypeByName("silver")) - } - - @Test - fun whenGetCardTypeByName_thenGoldCardType() { - Assertions.assertEquals(CardType.GOLD, CardType.getCardTypeByName("gold")) - } - - @Test - fun whenGetCardTypeByName_thenPlatinumCardType() { - Assertions.assertEquals(CardType.PLATINUM, CardType.getCardTypeByName("platinum")) - } - -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/inline/classes/CircleRadiusTest.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/inline/classes/CircleRadiusTest.kt deleted file mode 100644 index 8de378b6dd..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/inline/classes/CircleRadiusTest.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.inline.classes - -import org.junit.Test -import kotlin.test.assertEquals - -class CircleRadiusTest { - - @Test - fun givenRadius_ThenDiameterIsCorrectlyCalculated() { - val radius = CircleRadius(5.0) - assertEquals(10.0, radius.diameterOfCircle) - } - - @Test - fun givenRadius_ThenAreaIsCorrectlyCalculated() { - val radius = CircleRadius(5.0) - assertEquals(78.5, radius.areaOfCircle()) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/inline/classes/InlineDoubleWrapperTest.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/inline/classes/InlineDoubleWrapperTest.kt deleted file mode 100644 index 349c90d6f4..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/inline/classes/InlineDoubleWrapperTest.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.inline.classes - -import org.junit.Test -import kotlin.test.assertEquals - -class InlineDoubleWrapperTest { - - @Test - fun whenInclineClassIsUsed_ThenPropertyIsReadCorrectly() { - val piDoubleValue = InlineDoubleWrapper(3.14) - assertEquals(3.14, piDoubleValue.doubleValue) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/interfaces/InterfaceExamplesUnitTest.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/interfaces/InterfaceExamplesUnitTest.kt deleted file mode 100644 index 96b99948b7..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/interfaces/InterfaceExamplesUnitTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.interfaces - -import org.junit.Test -import kotlin.test.assertEquals - -class InterfaceExamplesUnitTest { - @Test - fun givenAnInterface_whenImplemented_thenBehavesAsOverridden() { - val simpleClass = SimpleClass() - assertEquals("Hello, from: First Property", simpleClass.firstMethod()) - assertEquals("Hello, from: Second Property, Overridden!First Property", simpleClass.secondMethod()) - } - - @Test - fun givenMultipleInterfaces_whenImplemented_thenBehavesAsOverridden() { - val someClass = SomeClass() - assertEquals("Hello, from someMethod in SomeClass", someClass.someMethod()) - assertEquals("Hello, from anotherMethod in SomeClass", someClass.anotherMethod()) - } - - @Test - fun givenConflictingInterfaces_whenImplemented_thenBehavesAsOverridden() { - val childClass = ChildClass() - assertEquals("Hello, from someMethod in SecondChildInterface", childClass.someMethod()) - } - - @Test - fun givenAnInterface_whenImplemented_thenBehavesAsDelegated() { - val myClass = MyClass() - assertEquals("Hello, World!", MyDerivedClass(myClass).someMethod()) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/ExtensionMethods.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/ExtensionMethods.kt deleted file mode 100644 index 44c5cd0ece..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/ExtensionMethods.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.baeldung.kotlin - -import org.junit.Assert -import org.junit.Test - -class ExtensionMethods { - @Test - fun simpleExtensionMethod() { - Assert.assertEquals("Nothing", "Nothing".escapeForXml()) - Assert.assertEquals("<Tag>", "".escapeForXml()) - Assert.assertEquals("a&b", "a&b".escapeForXml()) - } - - @Test - fun genericExtensionMethod() { - fun T.concatAsString(b: T) : String { - return this.toString() + b.toString() - } - - Assert.assertEquals("12", "1".concatAsString("2")) - Assert.assertEquals("12", 1.concatAsString(2)) - // This doesn't compile - // Assert.assertEquals("12", 1.concatAsString(2.0)) - } - - @Test - fun infixExtensionMethod() { - infix fun Number.toPowerOf(exponent: Number): Double { - return Math.pow(this.toDouble(), exponent.toDouble()) - } - - Assert.assertEquals(9.0, 3 toPowerOf 2, 0.1) - Assert.assertEquals(3.0, 9 toPowerOf 0.5, 0.1) - } - - @Test - fun operatorExtensionMethod() { - operator fun List.times(by: Int): List { - return this.map { it * by } - } - - Assert.assertEquals(listOf(2, 4, 6), listOf(1, 2, 3) * 2) - } -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/SealedTest.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/SealedTest.kt deleted file mode 100644 index 8c7509f653..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/SealedTest.kt +++ /dev/null @@ -1,84 +0,0 @@ -package com.baeldung.kotlin - -import org.junit.Assert -import org.junit.Test - -class SealedTest { - fun divide(a: Int, b: Int) : Result = when (b) { - 0 -> Failure("Division by zero") - else -> Success(a.toFloat() / b) - } - - @Test - fun testSuccess() { - val result = divide(10, 5) - Assert.assertEquals(Success(2.0f), result) - } - - @Test - fun testError() { - val result = divide(10, 0) - Assert.assertEquals(Failure("Division by zero"), result) - } - - @Test - fun testMatchOnSuccess() { - val result = divide(10, 5) - when (result) { - is Success -> { - // Expected - } - is Failure -> Assert.fail("Expected Success") - } - } - - @Test - fun testMatchOnError() { - val result = divide(10, 0) - when (result) { - is Failure -> { - // Expected - } - } - } - - @Test - fun testGetSuccess() { - val result = divide(10, 5) - Assert.assertEquals(2.0f, result.get()) - } - - @Test - fun testGetError() { - val result = divide(10, 0) - Assert.assertNull(result.get()) - } - - @Test - fun testMapOnSuccess() { - val result = divide(10, 5) - .map { "Result: $it" } - Assert.assertEquals(Success("Result: 2.0"), result) - } - - @Test - fun testMapOnError() { - val result = divide(10, 0) - .map { "Result: $it" } - Assert.assertEquals(Failure("Division by zero"), result) - } - - @Test - fun testMapFailureOnSuccess() { - val result = divide(10, 5) - .mapFailure { "Failure: $it" } - Assert.assertEquals(Success(2.0f), result) - } - - @Test - fun testMapFailureOnError() { - val result = divide(10, 0) - .mapFailure { "Failure: $it" } - Assert.assertEquals(Failure("Failure: Division by zero"), result) - } -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/Counter.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/Counter.kt deleted file mode 100644 index 46ba42e1e5..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/Counter.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.kotlin.objects - -object Counter { - private var count: Int = 0 - - fun currentCount() = count - - fun increment() { - ++count - } - - fun decrement() { - --count - } -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/ObjectsTest.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/ObjectsTest.kt deleted file mode 100644 index 0bbb1c741d..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/ObjectsTest.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.baeldung.kotlin.objects - -import org.junit.Assert -import org.junit.Test - -class ObjectsTest { - @Test - fun singleton() { - - Assert.assertEquals(42, SimpleSingleton.answer) - Assert.assertEquals("Hello, world!", SimpleSingleton.greet("world")) - } - - @Test - fun counter() { - Assert.assertEquals(0, Counter.currentCount()) - Counter.increment() - Assert.assertEquals(1, Counter.currentCount()) - Counter.decrement() - Assert.assertEquals(0, Counter.currentCount()) - } - - @Test - fun comparator() { - val strings = listOf("Hello", "World") - val sortedStrings = strings.sortedWith(ReverseStringComparator) - - Assert.assertEquals(listOf("World", "Hello"), sortedStrings) - } - - @Test - fun companion() { - Assert.assertEquals("You can see me", OuterClass.public) - // Assert.assertEquals("You can't see me", OuterClass.secret) // Cannot access 'secret' - } -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/OuterClass.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/OuterClass.kt deleted file mode 100644 index 4abb7a668d..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/OuterClass.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.baeldung.kotlin.objects - -class OuterClass { - companion object { - private val secret = "You can't see me" - val public = "You can see me" - } - - fun getSecretValue() = secret -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/ReverseStringComparator.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/ReverseStringComparator.kt deleted file mode 100644 index 20dc2d8c5b..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/ReverseStringComparator.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.baeldung.kotlin.objects - -object ReverseStringComparator : Comparator { - override fun compare(o1: String, o2: String) = o1.reversed().compareTo(o2.reversed()) -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/SimpleSingleton.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/SimpleSingleton.kt deleted file mode 100644 index bfafd8183f..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/SimpleSingleton.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.baeldung.kotlin.objects - -object SimpleSingleton { - val answer = 42; - - fun greet(name: String) = "Hello, $name!" -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/StaticClass.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/StaticClass.kt deleted file mode 100644 index 36cd476110..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/kotlin/objects/StaticClass.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.kotlin.objects - -class StaticClass { - companion object { - @JvmStatic - val staticField = 42 - } -} diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/nested/ComputerUnitTest.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/nested/ComputerUnitTest.kt deleted file mode 100644 index 7882d85b3c..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/nested/ComputerUnitTest.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.nested - -import org.assertj.core.api.Assertions.assertThat -import org.junit.jupiter.api.Test - -class ComputerUnitTest { - - @Test - fun givenComputer_whenPowerOn_thenBlink() { - val computer = Computer("Desktop") - - assertThat(computer.powerOn()).isEqualTo("blinking Green") - } - - @Test - fun givenMotherboard_whenGetInfo_thenGetInstalledAndBuiltDetails() { - val motherBoard = Computer.MotherBoard("MotherBoard Inc.") - - assertThat(motherBoard.getInfo()).isEqualTo("Made by MotherBoard Inc. installed in China - 2018-05-23") - } - - @Test - fun givenHardDisk_whenGetInfo_thenGetComputerModelAndDiskSizeInGb() { - val hardDisk = Computer("Desktop").HardDisk(1000) - - assertThat(hardDisk.getInfo()).isEqualTo("Installed on Computer(model=Desktop) with 1000 GB") - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/static/ConsoleUtilsUnitTest.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/static/ConsoleUtilsUnitTest.kt deleted file mode 100644 index 8abed144eb..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/static/ConsoleUtilsUnitTest.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.baeldung.static - -import org.junit.Test - -class ConsoleUtilsUnitTest { - @Test - fun givenAStaticMethod_whenCalled_thenNoErrorIsThrown() { - ConsoleUtils.debug("test message") - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/static/LoggingUtilsUnitTest.kt b/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/static/LoggingUtilsUnitTest.kt deleted file mode 100644 index 59587ff009..0000000000 --- a/core-kotlin-modules/core-kotlin-lang-oop/src/test/kotlin/com/baeldung/static/LoggingUtilsUnitTest.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.baeldung.static - -import org.junit.Test - -class LoggingUtilsUnitTest { - @Test - fun givenAPackageMethod_whenCalled_thenNoErrorIsThrown() { - debug("test message") - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/README.md b/core-kotlin-modules/core-kotlin-lang/README.md deleted file mode 100644 index eaeae76854..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/README.md +++ /dev/null @@ -1,16 +0,0 @@ -## Core Kotlin Lang - -This module contains articles about core features in the Kotlin language. - -### Relevant articles: -- [Guide to the “when{}” Block in Kotlin](https://www.baeldung.com/kotlin-when) -- [Difference Between “==” and “===” Operators in Kotlin](https://www.baeldung.com/kotlin-equality-operators) -- [Nested forEach in Kotlin](https://www.baeldung.com/kotlin-nested-foreach) -- [Destructuring Declarations in Kotlin](https://www.baeldung.com/kotlin-destructuring-declarations) -- [Try-with-resources in Kotlin](https://www.baeldung.com/kotlin-try-with-resources) -- [Operator Overloading in Kotlin](https://www.baeldung.com/kotlin-operator-overloading) -- [Inline Functions in Kotlin](https://www.baeldung.com/kotlin-inline-functions) -- [Void Type in Kotlin](https://www.baeldung.com/kotlin-void-type) -- [How to use Kotlin Range Expressions](https://www.baeldung.com/kotlin-ranges) -- [Creating a Kotlin Range Iterator on a Custom Object](https://www.baeldung.com/kotlin-custom-range-iterator) -- [[More --> ]](/core-kotlin-modules/core-kotlin-lang-2) diff --git a/core-kotlin-modules/core-kotlin-lang/pom.xml b/core-kotlin-modules/core-kotlin-lang/pom.xml deleted file mode 100644 index d3ac7f690c..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/pom.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - 4.0.0 - core-kotlin-lang - core-kotlin-lang - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/destructuringdeclarations/Person.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/destructuringdeclarations/Person.kt deleted file mode 100644 index d3167ce033..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/destructuringdeclarations/Person.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.destructuringdeclarations - -data class Person(var id: Int, var name: String, var age: Int) \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/destructuringdeclarations/Result.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/destructuringdeclarations/Result.kt deleted file mode 100644 index e3da9b46a4..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/destructuringdeclarations/Result.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.destructuringdeclarations - -data class Result(val result: Int, val status: String) \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/destructuringdeclarations/Sandbox.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/destructuringdeclarations/Sandbox.kt deleted file mode 100644 index f845d01539..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/destructuringdeclarations/Sandbox.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.destructuringdeclarations - -fun main(args: Array) { - - //2.1. Objects - val person = Person(1, "Jon Snow", 20) - val(id, name, age) = person - - println(id) //1 - println(name) //Jon Snow - println(age) //20 - - //2.2. Functions - fun getPersonInfo() = Person(2, "Ned Stark", 45) - val(idf, namef, agef) = getPersonInfo() - - fun twoValuesReturn(): Pair { - - // needed code - - return Pair(1, "success") - } - - // Now, to use this function: - val (result, status) = twoValuesReturn() - - //2.3. Collections and For-loops - var map: HashMap = HashMap() - map.put(1, person) - - for((key, value) in map){ - println("Key: $key, Value: $value") - } - - //2.4. Underscore and Destructuring in Lambdas - val (_, name2, age2) = person - val (id3, name3) = person - - map.mapValues { entry -> "${entry.value}!" } - map.mapValues { (key, value) -> "$value!" } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/equalityoperators/User.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/equalityoperators/User.kt deleted file mode 100644 index 030169bb8a..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/equalityoperators/User.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.equalityoperators - -data class User(val name: String, val age: Int, val hobbies: List) diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/forEach/forEach.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/forEach/forEach.kt deleted file mode 100644 index 20eda4e64f..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/forEach/forEach.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.baeldung.forEach - - -class Country(val name : String, val cities : List) - -class City(val name : String, val streets : List) - -fun City.getStreetsWithCityName() : List { - return streets.map { "$name, $it" }.toList() -} - -fun Country.getCitiesWithCountryName() : List { - return cities.flatMap { it.getStreetsWithCityName() } - .map { "$name, $it" } -} - -class World { - - private val streetsOfAmsterdam = listOf("Herengracht", "Prinsengracht") - private val streetsOfBerlin = listOf("Unter den Linden","Tiergarten") - private val streetsOfMaastricht = listOf("Grote Gracht", "Vrijthof") - private val countries = listOf( - Country("Netherlands", listOf(City("Maastricht", streetsOfMaastricht), - City("Amsterdam", streetsOfAmsterdam))), - Country("Germany", listOf(City("Berlin", streetsOfBerlin)))) - - fun allCountriesIt() { - countries.forEach { println(it.name) } - } - - fun allCountriesItExplicit() { - countries.forEach { it -> println(it.name) } - } - - //here we cannot refer to 'it' anymore inside the forEach - fun allCountriesExplicit() { - countries.forEach { c -> println(c.name) } - } - - fun allNested() { - countries.forEach { - println(it.name) - it.cities.forEach { - println(" ${it.name}") - it.streets.forEach { println(" $it") } - } - } - } - - fun allTable() { - countries.forEach { c -> - c.cities.forEach { p -> - p.streets.forEach { println("${c.name} ${p.name} $it") } - } - } - } - - fun allStreetsFlatMap() { - - countries.flatMap { it.cities} - .flatMap { it.streets} - .forEach { println(it) } - } - - fun allFlatMapTable() { - - countries.flatMap { it.getCitiesWithCountryName() } - .forEach { println(it) } - } -} - -fun main(args : Array) { - - val world = World() - - world.allCountriesExplicit() - - world.allNested() - - world.allTable() - - world.allStreetsFlatMap() - - world.allFlatMapTable() -} - - diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/inline/Inline.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/inline/Inline.kt deleted file mode 100644 index aaa6616ed1..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/inline/Inline.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.baeldung.inline - -import kotlin.random.Random - -/** - * An extension function on all collections to apply a function to all collection - * elements. - */ -fun Collection.each(block: (T) -> Unit) { - for (e in this) block(e) -} - -/** - * In order to see the the JVM bytecode: - * 1. Compile the Kotlin file using `kotlinc Inline.kt` - * 2. Take a peek at the bytecode using the `javap -c InlineKt` - */ -fun main() { - val numbers = listOf(1, 2, 3, 4, 5) - val random = random() - - numbers.each { println(random * it) } // capturing the random variable -} - -fun namedFunction(): Int { - return 42 -} - -fun anonymous(): () -> Int { - return fun(): Int { - return 42 - } -} - -inline fun List.eachIndexed(f: (Int, T) -> Unit) { - for (i in indices) { - f(i, this[i]) - } -} - -fun List.indexOf(x: T): Int { - eachIndexed { index, value -> - if (value == x) return index - } - - return -1 -} - -/** - * Generates a random number. - */ -private fun random(): Int = Random.nextInt() \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/operators/Money.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/operators/Money.kt deleted file mode 100644 index 93eb78c5b6..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/operators/Money.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.baeldung.operators - -import java.math.BigDecimal - -enum class Currency { - DOLLARS, EURO -} - -class Money(val amount: BigDecimal, val currency: Currency) : Comparable { - - override fun compareTo(other: Money): Int = - convert(Currency.DOLLARS).compareTo(other.convert(Currency.DOLLARS)) - - fun convert(currency: Currency): BigDecimal = TODO() - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is Money) return false - - if (amount != other.amount) return false - if (currency != other.currency) return false - - return true - } - - override fun hashCode(): Int { - var result = amount.hashCode() - result = 31 * result + currency.hashCode() - return result - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/operators/Page.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/operators/Page.kt deleted file mode 100644 index 8a0ee48a36..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/operators/Page.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.operators - -interface Page { - fun pageNumber(): Int - fun pageSize(): Int - fun elements(): MutableList -} - -operator fun Page.invoke(index: Int): T = elements()[index] -operator fun Page.get(index: Int): T = elements()[index] -operator fun Page.get(start: Int, endExclusive: Int): List = elements().subList(start, endExclusive) -operator fun Page.set(index: Int, value: T) { - elements()[index] = value -} - -operator fun Page.contains(element: T): Boolean = element in elements() -operator fun Page.iterator() = elements().iterator() \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/operators/Point.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/operators/Point.kt deleted file mode 100644 index e3282e64cc..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/operators/Point.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.baeldung.operators - -data class Point(val x: Int, val y: Int) - -operator fun Point.unaryMinus() = Point(-x, -y) -operator fun Point.not() = Point(y, x) -operator fun Point.inc() = Point(x + 1, y + 1) -operator fun Point.dec() = Point(x - 1, y - 1) - -operator fun Point.plus(other: Point): Point = Point(x + other.x, y + other.y) -operator fun Point.minus(other: Point): Point = Point(x - other.x, y - other.y) -operator fun Point.times(other: Point): Point = Point(x * other.x, y * other.y) -operator fun Point.div(other: Point): Point = Point(x / other.x, y / other.y) -operator fun Point.rem(other: Point): Point = Point(x % other.x, y % other.y) -operator fun Point.times(factor: Int): Point = Point(x * factor, y * factor) -operator fun Int.times(point: Point): Point = Point(point.x * this, point.y * this) - -class Shape { - val points = mutableListOf() - - operator fun Point.unaryPlus() { - points.add(this) - } -} - -fun shape(init: Shape.() -> Unit): Shape { - val shape = Shape() - shape.init() - - return shape -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/operators/Utils.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/operators/Utils.kt deleted file mode 100644 index 0f16544f38..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/operators/Utils.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.operators - -import java.math.BigInteger - -operator fun MutableCollection.plusAssign(element: T) { - add(element) -} -operator fun BigInteger.plus(other: Int): BigInteger = add(BigInteger("$other")) \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/CharRange.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/CharRange.kt deleted file mode 100644 index 3151674d61..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/CharRange.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.range - -fun main(args: Array) { - - for (ch in 'a'..'f') { - print(ch) - } - println() - - for (ch in 'f' downTo 'a') { - print(ch) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/Color.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/Color.kt deleted file mode 100644 index ef7adf06b5..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/Color.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.range - -enum class Color(val rgb: Int) { - BLUE(0x0000FF), - GREEN(0x008000), - RED(0xFF0000), - MAGENTA(0xFF00FF), - YELLOW(0xFFFF00); -} - -fun main(args: Array) { - - println(Color.values().toList()); - val red = Color.RED - val yellow = Color.YELLOW - val range = red..yellow - - println(range.contains(Color.MAGENTA)) - println(range.contains(Color.BLUE)) - println(range.contains(Color.GREEN)) -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/Filter.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/Filter.kt deleted file mode 100644 index 0e611b14cf..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/Filter.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.baeldung.range - -fun main(args: Array) { - val r = 1..10 - - //Apply filter - val f = r.filter { it -> it % 2 == 0 } - println(f) - - //Map - val m = r.map { it -> it * it } - println(m) - - //Reduce - val rdc = r.reduce { a, b -> a + b } - println(rdc) - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/FirstLast.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/FirstLast.kt deleted file mode 100644 index b82f5a8b9b..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/FirstLast.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.range - -fun main(args: Array) { - - println((1..9).first) - println((1..9 step 2).step) - println((3..9).reversed().last) -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/OtherRangeFunctions.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/OtherRangeFunctions.kt deleted file mode 100644 index 19dcab89b2..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/OtherRangeFunctions.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.range - -fun main(args: Array) { - - val r = 1..20 - println(r.min()) - println(r.max()) - println(r.sum()) - println(r.average()) - println(r.count()) - - val repeated = listOf(1, 1, 2, 4, 4, 6, 10) - println(repeated.distinct()) -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/Range.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/Range.kt deleted file mode 100644 index c313181599..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/Range.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.range - -fun main(args: Array) { - - for (i in 1..9) { - print(i) - } - println() - - for (i in 9 downTo 1) { - print(i) - } - println() - - for (i in 1.rangeTo(9)) { - print(i) - } - println() - - for (i in 9.downTo(1)) { - print(i) - } - println() - - for (i in 1 until 9) { - print(i) - } -} diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/ReverseRange.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/ReverseRange.kt deleted file mode 100644 index 875cf62200..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/ReverseRange.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.range - -fun main(args: Array) { - - (1..9).reversed().forEach { - print(it) - } - - println() - - (1..9).reversed().step(3).forEach { - print(it) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/Step.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/Step.kt deleted file mode 100644 index b9c5d48588..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/Step.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.range - -fun main(args: Array) { - - for(i in 1..9 step 2){ - print(i) - } - - println() - - for (i in 9 downTo 1 step 2){ - print(i) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/UntilRange.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/UntilRange.kt deleted file mode 100644 index 2c116a286f..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/range/UntilRange.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.range - -fun main(args: Array) { - - for (i in 1 until 9) { - print(i) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/rangeiterator/CustomColor.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/rangeiterator/CustomColor.kt deleted file mode 100644 index c1ab8e1610..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/rangeiterator/CustomColor.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.baeldung.rangeiterator - -import java.lang.IllegalStateException - -class CustomColor(val rgb: Int): Comparable { - - override fun compareTo(other: CustomColor): Int { - return this.rgb.compareTo(other.rgb) - } - - operator fun rangeTo(that: CustomColor) = ColorRange(this, that) - - operator fun inc(): CustomColor { - return CustomColor(rgb + 1) - } - - init { - if(rgb < 0x000000 || rgb > 0xFFFFFF){ - throw IllegalStateException("RGB must be between 0 and 16777215") - } - } - - override fun toString(): String { - return "CustomColor(rgb=$rgb)" - } -} -class ColorRange(override val start: CustomColor, - override val endInclusive: CustomColor) : ClosedRange, Iterable{ - - override fun iterator(): Iterator { - return ColorIterator(start, endInclusive) - } -} - -class ColorIterator(val start: CustomColor, val endInclusive: CustomColor) : Iterator { - - var initValue = start - - override fun hasNext(): Boolean { - return initValue <= endInclusive - } - - override fun next(): CustomColor { - return initValue++ - } -} - -fun main(args: Array) { - val a = CustomColor(0xABCDEF) - val b = CustomColor(-1) - val c = CustomColor(0xABCDFF) - - for(color in a..c){ - println(color) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/whenblock/WhenBlockTypes.kt b/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/whenblock/WhenBlockTypes.kt deleted file mode 100644 index a4cd7b98f0..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/main/kotlin/com/baeldung/whenblock/WhenBlockTypes.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.whenblock - -enum class UnixFileType { - D, HYPHEN_MINUS, L -} - -sealed class UnixFile { - - abstract fun getFileType(): UnixFileType - - class RegularFile(val content: String) : UnixFile() { - override fun getFileType(): UnixFileType { - return UnixFileType.HYPHEN_MINUS - } - } - - class Directory(val children: List) : UnixFile() { - override fun getFileType(): UnixFileType { - return UnixFileType.D - } - } - - class SymbolicLink(val originalFile: UnixFile) : UnixFile() { - override fun getFileType(): UnixFileType { - return UnixFileType.L - } - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/equalityoperators/EqualityTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/equalityoperators/EqualityTest.kt deleted file mode 100644 index 0728d55b73..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/equalityoperators/EqualityTest.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.baeldung.equalityoperators - -import org.junit.Test -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -class EqualityTest { - - // Checks referential equality - @Test - fun givenTwoIntegers_whenCheckReference_thenEqualReference() { - val a = Integer(10) - val b = Integer(10) - - assertFalse(a === b) - } - - // Checks structural equality - @Test - fun givenTwoIntegers_whenCheckValue_thenStructurallyEqual() { - val a = Integer(10) - val b = Integer(10) - - assertTrue(a == b) - } - - @Test - fun givenUser_whenCheckReference_thenEqualReference() { - val user = User("John", 30, listOf("Hiking, Chess")) - val user2 = User("Sarah", 28, listOf("Shopping, Gymnastics")) - - assertFalse(user === user2) - } - - @Test - fun givenUser_whenCheckValue_thenStructurallyEqual() { - val user = User("John", 30, listOf("Hiking, Chess")) - val user2 = User("John", 30, listOf("Hiking, Chess")) - - assertTrue(user == user2) - } - - @Test - fun givenArray_whenCheckReference_thenEqualReference() { - val hobbies = arrayOf("Riding motorcycle, Video games") - val hobbies2 = arrayOf("Riding motorcycle, Video games") - - assertFalse(hobbies === hobbies2) - } - - @Test - fun givenArray_whenCheckContent_thenStructurallyEqual() { - val hobbies = arrayOf("Hiking, Chess") - val hobbies2 = arrayOf("Hiking, Chess") - - assertTrue(hobbies contentEquals hobbies2) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/operators/PageTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/operators/PageTest.kt deleted file mode 100644 index fa6e1773bd..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/operators/PageTest.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.baeldung.operators - -import org.junit.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class PageTest { - - private val page = PageImpl(1, 10, "Java", "Kotlin", "Scala") - - @Test - fun `Get convention should work as expected`() { - assertEquals(page[1], "Kotlin") - assertEquals(page[1, 3], listOf("Kotlin", "Scala")) - } - - @Test - fun `Invoke convention should work as expected`() { - assertEquals(page(1), "Kotlin") - } - - @Test - fun `In convention should work on a page as expected`() { - assertTrue("Kotlin" in page) - } - -} - -private class PageImpl(val page: Int, val size: Int, vararg val elements: T) : Page { - override fun pageNumber(): Int = page - override fun pageSize(): Int = size - override fun elements(): MutableList = mutableListOf(*elements) -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/operators/PointTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/operators/PointTest.kt deleted file mode 100644 index 168ab6431d..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/operators/PointTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.baeldung.operators - -import org.junit.Test -import kotlin.test.assertEquals -import kotlin.test.assertTrue - -class PointTest { - - private val p1 = Point(1, 2) - private val p2 = Point(2, 3) - - @Test - fun `We should be able to add two points together using +`() { - assertEquals(p1 + p2, Point(3, 5)) - } - - @Test - fun `We shoud be able to subtract one point from another using -`() { - assertEquals(p1 - p2, Point(-1, -1)) - } - - @Test - fun `We should be able to multiply two points together with *`() { - assertEquals(p1 * p2, Point(2, 6)) - } - - @Test - fun `We should be able to divide one point by another`() { - assertEquals(p1 / p2, Point(0, 0)) - } - - @Test - fun `We should be able to scale a point by an integral factor`() { - assertEquals(p1 * 2, Point(2, 4)) - assertEquals(2 * p1, Point(2, 4)) - } - - @Test - fun `We should be able to add points to an empty shape`() { - val line = shape { - +Point(0, 0) - +Point(1, 3) - } - - assertTrue(Point(0, 0) in line.points) - assertTrue(Point(1, 3) in line.points) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/operators/UtilsTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/operators/UtilsTest.kt deleted file mode 100644 index 4abe962cb5..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/operators/UtilsTest.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.operators - -import java.math.BigInteger -import org.junit.Test -import kotlin.test.assertEquals - -class UtilsTest { - - @Test - fun `We should be able to add an int value to an existing BigInteger using +`() { - assertEquals(BigInteger.ZERO + 1, BigInteger.ONE) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/CharRangeTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/CharRangeTest.kt deleted file mode 100644 index 0e23f508b6..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/CharRangeTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.range - -import org.junit.Test -import kotlin.test.assertEquals - -class CharRangeTest { - - @Test - fun testCharRange() { - assertEquals(listOf('a', 'b', 'c'), ('a'..'c').toList()) - } - - @Test - fun testCharDownRange() { - assertEquals(listOf('c', 'b', 'a'), ('c'.downTo('a')).toList()) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/ColorTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/ColorTest.kt deleted file mode 100644 index 4ac3270fcc..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/ColorTest.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.baeldung.range - -import org.junit.Test -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -class ColorTest { - - @Test - fun testEnumRange() { - - println(Color.values().toList()); - val red = Color.RED - val yellow = Color.YELLOW - val range = red..yellow - - assertTrue { range.contains(Color.MAGENTA) } - assertFalse { range.contains(Color.BLUE) } - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/FilterTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/FilterTest.kt deleted file mode 100644 index d0e2df8860..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/FilterTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.range - -import org.junit.Test -import kotlin.test.assertEquals - -class FilterTest { - - val r = 1..10 - - @Test - fun filterTest() { - assertEquals(listOf(2, 4, 6, 8, 10), r.filter { it -> it % 2 == 0 }.toList()) - } - - @Test - fun mapTest() { - assertEquals(listOf(1, 4, 9, 16, 25, 36, 49, 64, 81, 100), r.map { it -> it * it }.toList()) - } - - @Test - fun reduceTest() { - assertEquals(55, r.reduce { a, b -> a + b }) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/FirstLastTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/FirstLastTest.kt deleted file mode 100644 index ca797e9c9b..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/FirstLastTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.range - -import org.junit.Test -import kotlin.test.assertEquals - -class FirstLastTest { - - @Test - fun testFirst() { - assertEquals(1, (1..9).first) - } - - @Test - fun testLast() { - assertEquals(9, (1..9).last) - } - - @Test - fun testStep() { - assertEquals(2, (1..9 step 2).step) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/OtherRangeFunctionsTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/OtherRangeFunctionsTest.kt deleted file mode 100644 index d2d36bbfae..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/OtherRangeFunctionsTest.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.baeldung.range - -import org.junit.Test -import kotlin.test.assertEquals - -class OtherRangeFunctionsTest { - - val r = 1..20 - val repeated = listOf(1, 1, 2, 4, 4, 6, 10) - - @Test - fun testMin() { - assertEquals(1, r.min()) - } - - @Test - fun testMax() { - assertEquals(20, r.max()) - } - - @Test - fun testSum() { - assertEquals(210, r.sum()) - } - - @Test - fun testAverage() { - assertEquals(10.5, r.average()) - } - - @Test - fun testCount() { - assertEquals(20, r.count()) - } - - @Test - fun testDistinct() { - assertEquals(listOf(1, 2, 4, 6, 10), repeated.distinct()) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/RangeTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/RangeTest.kt deleted file mode 100644 index 48fa483924..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/RangeTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.range - -import org.junit.Test -import kotlin.test.assertEquals - -class RangeTest { - - @Test - fun testRange() { - assertEquals(listOf(1,2,3), (1.rangeTo(3).toList())) - } - - @Test - fun testDownTo(){ - assertEquals(listOf(3,2,1), (3.downTo(1).toList())) - } - - @Test - fun testUntil(){ - assertEquals(listOf(1,2), (1.until(3).toList())) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/ReverseRangeTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/ReverseRangeTest.kt deleted file mode 100644 index 7e1c7badb7..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/ReverseRangeTest.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.range - -import org.junit.Test -import kotlin.test.assertEquals - -class ReverseRangeTest { - - @Test - fun reversedTest() { - assertEquals(listOf(9, 6, 3), (1..9).reversed().step(3).toList()) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/StepTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/StepTest.kt deleted file mode 100644 index 4570ceeb0a..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/StepTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.range - -import org.junit.Test -import kotlin.test.assertEquals - -class StepTest { - - @Test - fun testStep() { - assertEquals(listOf(1, 3, 5, 7, 9), (1..9 step 2).toList()) - } - - @Test - fun testStepDown() { - assertEquals(listOf(9, 7, 5, 3, 1), (9 downTo 1 step 2).toList()) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/UntilRangeTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/UntilRangeTest.kt deleted file mode 100644 index f941c7f1e6..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/range/UntilRangeTest.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.range - -import org.junit.Test -import kotlin.test.assertEquals - -class UntilRangeTest { - - @Test - fun testUntil() { - assertEquals(listOf(1, 2, 3, 4), (1 until 5).toList()) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/rangeiterator/CustomColorTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/rangeiterator/CustomColorTest.kt deleted file mode 100644 index 676b47ae7a..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/rangeiterator/CustomColorTest.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.baeldung.rangeiterator - -import org.junit.Test -import java.lang.IllegalStateException -import kotlin.test.assertFailsWith -import kotlin.test.assertTrue - -class CustomColorTest { - - @Test - fun testInvalidConstructor(){ - assertFailsWith(IllegalStateException::class){ - CustomColor(-1) - } - } - - @Test - fun assertHas10Colors(){ - assertTrue { - val a = CustomColor(1) - val b = CustomColor(10) - val range = a..b - for(cc in range){ - println(cc) - } - range.toList().size == 10 - } - } - - @Test - fun assertContains0xCCCCCC(){ - assertTrue { - val a = CustomColor(0xBBBBBB) - val b = CustomColor(0xDDDDDD) - val range = a..b - range.contains(CustomColor(0xCCCCCC)) - } - } - -} - diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/trywithresource/UseTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/trywithresource/UseTest.kt deleted file mode 100644 index d17832b380..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/trywithresource/UseTest.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.baeldung.trywithresource - -import org.junit.Test -import java.beans.ExceptionListener -import java.beans.XMLEncoder -import java.io.* -import java.lang.Exception -import kotlin.test.assertEquals -import kotlin.test.assertTrue -import kotlin.test.fail - -class UseTest { - - @Test - fun givenCloseable_whenUseIsCalled_thenItIsClosed() { - val stringWriter = StringWriter() - val writer = BufferedWriter(stringWriter) //Using a BufferedWriter because after close() it throws. - writer.use { - assertEquals(writer, it) - - it.write("something") - } - try { - writer.write("something else") - - fail("write() should have thrown an exception because the writer is closed.") - } catch (e: IOException) { - //Ok - } - - assertEquals("something", stringWriter.toString()) - } - - @Test - fun givenAutoCloseable_whenUseIsCalled_thenItIsClosed() { - val baos = ByteArrayOutputStream() - val encoder = XMLEncoder(PrintStream(baos)) //XMLEncoder is AutoCloseable but not Closeable. - //Here, we use a PrintStream because after close() it throws. - encoder.exceptionListener = ThrowingExceptionListener() - encoder.use { - assertEquals(encoder, it) - - it.writeObject("something") - } - try { - encoder.writeObject("something else") - encoder.flush() - - fail("write() should have thrown an exception because the encoder is closed.") - } catch (e: IOException) { - //Ok - } - } - - @Test - fun whenSimpleFormIsUsed_thenItWorks() { - StringWriter().use { it.write("something") } - } -} - -class ThrowingExceptionListener : ExceptionListener { - override fun exceptionThrown(e: Exception?) { - if(e != null) { - throw e - } - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt deleted file mode 100644 index 468352dbed..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/voidtypes/VoidTypesUnitTest.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.baeldung.voidtypes - -import org.junit.jupiter.api.Test -import kotlin.test.assertNull -import kotlin.test.assertTrue - -class VoidTypesUnitTest { - - // Un-commenting below methods will result into compilation error - // as the syntax used is incorrect and is used for explanation in tutorial. - - // fun returnTypeAsVoidAttempt1(): Void { - // println("Trying with Void as return type") - // } - - // fun returnTypeAsVoidAttempt2(): Void { - // println("Trying with Void as return type") - // return null - // } - - fun returnTypeAsVoidSuccess(): Void? { - println("Function can have Void as return type") - return null - } - - fun unitReturnTypeForNonMeaningfulReturns(): Unit { - println("No meaningful return") - } - - fun unitReturnTypeIsImplicit() { - println("Unit Return type is implicit") - } - - fun alwaysThrowException(): Nothing { - throw IllegalArgumentException() - } - - fun invokeANothingOnlyFunction() { - alwaysThrowException() - - var name = "Tom" - } - - @Test - fun givenJavaVoidFunction_thenMappedToKotlinUnit() { - assertTrue(System.out.println() is Unit) - } - - @Test - fun givenVoidReturnType_thenReturnsNullOnly() { - assertNull(returnTypeAsVoidSuccess()) - } - - @Test - fun givenUnitReturnTypeDeclared_thenReturnsOfTypeUnit() { - assertTrue(unitReturnTypeForNonMeaningfulReturns() is Unit) - } - - @Test - fun givenUnitReturnTypeNotDeclared_thenReturnsOfTypeUnit() { - assertTrue(unitReturnTypeIsImplicit() is Unit) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/whenblock/WhenBlockUnitTest.kt b/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/whenblock/WhenBlockUnitTest.kt deleted file mode 100644 index 31b6ad69f5..0000000000 --- a/core-kotlin-modules/core-kotlin-lang/src/test/kotlin/com/baeldung/whenblock/WhenBlockUnitTest.kt +++ /dev/null @@ -1,136 +0,0 @@ -package com.baeldung.whenblock - -import org.junit.Assert.assertEquals -import org.junit.Assert.assertTrue -import org.junit.Test - -class WhenBlockUnitTest { - - @Test - fun testWhenExpression() { - val directoryType = UnixFileType.D - - val objectType = when (directoryType) { - UnixFileType.D -> "d" - UnixFileType.HYPHEN_MINUS -> "-" - UnixFileType.L -> "l" - } - - assertEquals("d", objectType) - } - - @Test - fun testWhenExpressionWithDefaultCase() { - val fileType = UnixFileType.L - - val result = when (fileType) { - UnixFileType.L -> "linking to another file" - else -> "not a link" - } - - assertEquals("linking to another file", result) - } - - @Test(expected = IllegalArgumentException::class) - fun testWhenExpressionWithThrowException() { - val fileType = UnixFileType.L - - val result: Boolean = when (fileType) { - UnixFileType.HYPHEN_MINUS -> true - else -> throw IllegalArgumentException("Wrong type of file") - } - } - - @Test - fun testWhenStatement() { - val fileType = UnixFileType.HYPHEN_MINUS - - when (fileType) { - UnixFileType.HYPHEN_MINUS -> println("Regular file type") - UnixFileType.D -> println("Directory file type") - } - } - - @Test - fun testCaseCombination() { - val fileType = UnixFileType.D - - val frequentFileType: Boolean = when (fileType) { - UnixFileType.HYPHEN_MINUS, UnixFileType.D -> true - else -> false - } - - assertTrue(frequentFileType) - } - - @Test - fun testWhenWithoutArgument() { - val fileType = UnixFileType.L - - val objectType = when { - fileType === UnixFileType.L -> "l" - fileType === UnixFileType.HYPHEN_MINUS -> "-" - fileType === UnixFileType.D -> "d" - else -> "unknown file type" - } - - assertEquals("l", objectType) - } - - @Test - fun testDynamicCaseExpression() { - val unixFile = UnixFile.SymbolicLink(UnixFile.RegularFile("Content")) - - when { - unixFile.getFileType() == UnixFileType.D -> println("It's a directory!") - unixFile.getFileType() == UnixFileType.HYPHEN_MINUS -> println("It's a regular file!") - unixFile.getFileType() == UnixFileType.L -> println("It's a soft link!") - } - } - - @Test - fun testCollectionCaseExpressions() { - val regularFile = UnixFile.RegularFile("Test Content") - val symbolicLink = UnixFile.SymbolicLink(regularFile) - val directory = UnixFile.Directory(listOf(regularFile, symbolicLink)) - - val isRegularFileInDirectory = when (regularFile) { - in directory.children -> true - else -> false - } - - val isSymbolicLinkInDirectory = when { - symbolicLink in directory.children -> true - else -> false - } - - assertTrue(isRegularFileInDirectory) - assertTrue(isSymbolicLinkInDirectory) - } - - @Test - fun testRangeCaseExpressions() { - val fileType = UnixFileType.HYPHEN_MINUS - - val isCorrectType = when (fileType) { - in UnixFileType.D..UnixFileType.L -> true - else -> false - } - - assertTrue(isCorrectType) - } - - @Test - fun testWhenWithIsOperatorWithSmartCase() { - val unixFile: UnixFile = UnixFile.RegularFile("Test Content") - - val result = when (unixFile) { - is UnixFile.RegularFile -> unixFile.content - is UnixFile.Directory -> unixFile.children.map { it.getFileType() }.joinToString(", ") - is UnixFile.SymbolicLink -> unixFile.originalFile.getFileType() - } - - assertEquals("Test Content", result) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-strings/README.md b/core-kotlin-modules/core-kotlin-strings/README.md deleted file mode 100644 index 0e3d8ea57f..0000000000 --- a/core-kotlin-modules/core-kotlin-strings/README.md +++ /dev/null @@ -1,9 +0,0 @@ -## Core Kotlin Strings - -This module contains articles about core Kotlin strings. - -### Relevant articles: -- [Generate a Random Alphanumeric String in Kotlin](https://www.baeldung.com/kotlin-random-alphanumeric-string) -- [String Comparison in Kotlin](https://www.baeldung.com/kotlin-string-comparison) -- [Concatenate Strings in Kotlin](https://www.baeldung.com/kotlin-concatenate-strings) -- [Kotlin String Templates](https://www.baeldung.com/kotlin-string-template) diff --git a/core-kotlin-modules/core-kotlin-strings/pom.xml b/core-kotlin-modules/core-kotlin-strings/pom.xml deleted file mode 100644 index fb2998e9e1..0000000000 --- a/core-kotlin-modules/core-kotlin-strings/pom.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - 4.0.0 - core-kotlin-strings - core-kotlin-strings - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-strings/src/main/kotlin/com/baeldung/stringtemplates/Templates.kt b/core-kotlin-modules/core-kotlin-strings/src/main/kotlin/com/baeldung/stringtemplates/Templates.kt deleted file mode 100644 index 4b2d863618..0000000000 --- a/core-kotlin-modules/core-kotlin-strings/src/main/kotlin/com/baeldung/stringtemplates/Templates.kt +++ /dev/null @@ -1,115 +0,0 @@ -package com.baeldung.stringtemplates - -/** - * Example of a useful function defined in Kotlin String class - */ -fun padExample(): String { - return "Hello".padEnd(10, '!') -} - -/** - * Example of a simple string template usage - */ -fun simpleTemplate(n: Int): String { - val message = "n = $n" - return message -} - -/** - * Example of a string template with a simple expression - */ -fun templateWithExpression(n: Int): String { - val message = "n + 1 = ${n + 1}" - return message -} - -/** - * Example of a string template with expression containing some logic - */ -fun templateWithLogic(n: Int): String { - val message = "$n is ${if (n > 0) "positive" else "not positive"}" - return message -} - -/** - * Example of nested string templates - */ -fun nestedTemplates(n: Int): String { - val message = "$n is ${if (n > 0) "positive" else if (n < 0) "negative and ${if (n % 2 == 0) "even" else "odd"}" else "zero"}" - return message -} - -/** - * Example of joining array's element into a string with a default separator - */ -fun templateJoinArray(): String { - val numbers = listOf(1, 1, 2, 3, 5, 8) - val message = "first Fibonacci numbers: ${numbers.joinToString()}" - return message -} - -/** - * Example of escaping the dollar sign - */ -fun notAStringTemplate(): String { - val message = "n = \$n" - return message -} - -/** - * Example of a simple triple quoted string - */ -fun showFilePath(): String { - val path = """C:\Repository\read.me""" - return path -} - -/** - * Example of a multiline string - */ -fun showMultiline(): String { - val receipt = """Item 1: $1.00 -Item 2: $0.50""" - return receipt -} - -/** - * Example of a multiline string with indentation - */ -fun showMultilineIndent(): String { - val receipt = """Item 1: $1.00 - >Item 2: $0.50""".trimMargin(">") - return receipt -} - -/** - * Example of a triple quoted string with a not-working escape sequence - */ -fun showTripleQuotedWrongEscape(): String { - val receipt = """Item 1: $1.00\nItem 2: $0.50""" - return receipt -} - -/** - * Example of a triple quoted string with a correctly working escape sequence - */ - -fun showTripleQuotedCorrectEscape(): String { - val receipt = """Item 1: $1.00${"\n"}Item 2: $0.50""" - return receipt -} - -fun main(args: Array) { - println(padExample()) - println(simpleTemplate(10)) - println(templateWithExpression(5)) - println(templateWithLogic(7)) - println(nestedTemplates(-5)) - println(templateJoinArray()) - println(notAStringTemplate()) - println(showFilePath()) - println(showMultiline()) - println(showMultilineIndent()) - println(showTripleQuotedWrongEscape()) - println(showTripleQuotedCorrectEscape()) -} diff --git a/core-kotlin-modules/core-kotlin-strings/src/test/kotlin/com/baeldung/randomstring/RandomStringUnitTest.kt b/core-kotlin-modules/core-kotlin-strings/src/test/kotlin/com/baeldung/randomstring/RandomStringUnitTest.kt deleted file mode 100644 index 5b84d1f67d..0000000000 --- a/core-kotlin-modules/core-kotlin-strings/src/test/kotlin/com/baeldung/randomstring/RandomStringUnitTest.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.baeldung.randomstring - -import org.apache.commons.lang3.RandomStringUtils -import org.junit.Before -import org.junit.jupiter.api.BeforeAll -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import java.security.SecureRandom -import java.util.concurrent.ThreadLocalRandom -import kotlin.experimental.and -import kotlin.streams.asSequence -import kotlin.test.assertEquals - -const val STRING_LENGTH = 10 -const val ALPHANUMERIC_REGEX = "[a-zA-Z0-9]+" - -class RandomStringUnitTest { - private val charPool : List = ('a'..'z') + ('A'..'Z') + ('0'..'9') - - @Test - fun givenAStringLength_whenUsingJava_thenReturnAlphanumericString() { - var randomString = ThreadLocalRandom.current() - .ints(STRING_LENGTH.toLong(), 0, charPool.size) - .asSequence() - .map(charPool::get) - .joinToString("") - - assert(randomString.matches(Regex(ALPHANUMERIC_REGEX))) - assertEquals(STRING_LENGTH, randomString.length) - } - - @Test - fun givenAStringLength_whenUsingKotlin_thenReturnAlphanumericString() { - var randomString = (1..STRING_LENGTH).map { i -> kotlin.random.Random.nextInt(0, charPool.size) } - .map(charPool::get) - .joinToString("") - - assert(randomString.matches(Regex(ALPHANUMERIC_REGEX))) - assertEquals(STRING_LENGTH, randomString.length) - } - - @Test - fun givenAStringLength_whenUsingApacheCommon_thenReturnAlphanumericString() { - var randomString = RandomStringUtils.randomAlphanumeric(STRING_LENGTH) - - assert(randomString.matches(Regex(ALPHANUMERIC_REGEX))) - assertEquals(STRING_LENGTH, randomString.length) - } - - @Test - fun givenAStringLength_whenUsingRandomForBytes_thenReturnAlphanumericString() { - val random = SecureRandom() - val bytes = ByteArray(STRING_LENGTH) - random.nextBytes(bytes) - - var randomString = (0..bytes.size - 1).map { i -> - charPool.get((bytes[i] and 0xFF.toByte() and (charPool.size-1).toByte()).toInt()) - }.joinToString("") - - assert(randomString.matches(Regex(ALPHANUMERIC_REGEX))) - assertEquals(STRING_LENGTH, randomString.length) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-strings/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt b/core-kotlin-modules/core-kotlin-strings/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt deleted file mode 100644 index 49ff798faa..0000000000 --- a/core-kotlin-modules/core-kotlin-strings/src/test/kotlin/com/baeldung/stringcomparison/StringComparisonTest.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.baeldung.stringcomparison - -import org.junit.Test -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -class StringComparisonUnitTest { - - @Test - fun `compare using equals operator`() { - val first = "kotlin" - val second = "kotlin" - val firstCapitalized = "KOTLIN" - assertTrue { first == second } - assertFalse { first == firstCapitalized } - } - - @Test - fun `compare using referential equals operator`() { - val first = "kotlin" - val second = "kotlin" - val third = String("kotlin".toCharArray()) - assertTrue { first === second } - assertFalse { first === third } - } - - @Test - fun `compare using equals method`() { - val first = "kotlin" - val second = "kotlin" - val firstCapitalized = "KOTLIN" - assertTrue { first.equals(second) } - assertFalse { first.equals(firstCapitalized) } - assertTrue { first.equals(firstCapitalized, true) } - } - - @Test - fun `compare using compare method`() { - val first = "kotlin" - val second = "kotlin" - val firstCapitalized = "KOTLIN" - assertTrue { first.compareTo(second) == 0 } - assertTrue { first.compareTo(firstCapitalized) == 32 } - assertTrue { firstCapitalized.compareTo(first) == -32 } - assertTrue { first.compareTo(firstCapitalized, true) == 0 } - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-strings/src/test/kotlin/com/baeldung/stringconcatenation/StringConcatenationTest.kt b/core-kotlin-modules/core-kotlin-strings/src/test/kotlin/com/baeldung/stringconcatenation/StringConcatenationTest.kt deleted file mode 100644 index 9ac011f7d2..0000000000 --- a/core-kotlin-modules/core-kotlin-strings/src/test/kotlin/com/baeldung/stringconcatenation/StringConcatenationTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.baeldung.stringconcatenation - -import org.junit.Test -import kotlin.test.assertEquals - -class StringConcatenationTest { - - @Test - fun givenTwoStrings_concatenateWithTemplates_thenEquals() { - val a = "Hello" - val b = "Baeldung" - val c = "$a $b" - - assertEquals("Hello Baeldung", c) - } - - @Test - fun givenTwoStrings_concatenateWithPlusOperator_thenEquals() { - val a = "Hello" - val b = "Baeldung" - val c = a + " " + b - - assertEquals("Hello Baeldung", c) - } - - @Test - fun givenTwoStrings_concatenateWithStringBuilder_thenEquals() { - val a = "Hello" - val b = "Baeldung" - - val builder = StringBuilder() - builder.append(a).append(" ").append(b) - - val c = builder.toString() - - assertEquals("Hello Baeldung", c) - } - - @Test - fun givenTwoStrings_concatenateWithPlusMethod_thenEquals() { - val a = "Hello" - val b = "Baeldung" - val c = a.plus(" ").plus(b) - - assertEquals("Hello Baeldung", c) - } - -} diff --git a/core-kotlin-modules/core-kotlin-testing/README.md b/core-kotlin-modules/core-kotlin-testing/README.md deleted file mode 100644 index f4d89593a7..0000000000 --- a/core-kotlin-modules/core-kotlin-testing/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## Core Kotlin Testing - -This module contains articles about testing in Kotlin - -### Relevant articles: -- [JUnit 5 for Kotlin Developers](https://www.baeldung.com/junit-5-kotlin) \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-testing/pom.xml b/core-kotlin-modules/core-kotlin-testing/pom.xml deleted file mode 100644 index d38bc62409..0000000000 --- a/core-kotlin-modules/core-kotlin-testing/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - 4.0.0 - core-kotlin-testing - core-kotlin-testing - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - - - org.junit.platform - junit-platform-runner - ${junit.platform.version} - test - - - - - 1.1.1 - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/Calculator.kt b/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/Calculator.kt deleted file mode 100644 index 9f6e3ab2b9..0000000000 --- a/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/Calculator.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.junit5 - -class Calculator { - fun add(a: Int, b: Int) = a + b - - fun divide(a: Int, b: Int) = if (b == 0) { - throw DivideByZeroException(a) - } else { - a / b - } - - fun square(a: Int) = a * a - - fun squareRoot(a: Int) = Math.sqrt(a.toDouble()) - - fun log(base: Int, value: Int) = Math.log(value.toDouble()) / Math.log(base.toDouble()) -} diff --git a/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/CalculatorUnitTest.kt b/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/CalculatorUnitTest.kt deleted file mode 100644 index 07cab3b76e..0000000000 --- a/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/CalculatorUnitTest.kt +++ /dev/null @@ -1,82 +0,0 @@ -package com.baeldung.junit5 - -import org.junit.jupiter.api.* -import org.junit.jupiter.api.function.Executable - -class CalculatorUnitTest { - private val calculator = Calculator() - - @Test - fun `Adding 1 and 3 should be equal to 4`() { - Assertions.assertEquals(4, calculator.add(1, 3)) - } - - @Test - fun `Dividing by zero should throw the DivideByZeroException`() { - val exception = Assertions.assertThrows(DivideByZeroException::class.java) { - calculator.divide(5, 0) - } - - Assertions.assertEquals(5, exception.numerator) - } - - @Test - fun `The square of a number should be equal to that number multiplied in itself`() { - Assertions.assertAll( - Executable { Assertions.assertEquals(1, calculator.square(1)) }, - Executable { Assertions.assertEquals(4, calculator.square(2)) }, - Executable { Assertions.assertEquals(9, calculator.square(3)) } - ) - } - - @TestFactory - fun testSquaresFactory() = listOf( - DynamicTest.dynamicTest("when I calculate 1^2 then I get 1") { Assertions.assertEquals(1,calculator.square(1))}, - DynamicTest.dynamicTest("when I calculate 2^2 then I get 4") { Assertions.assertEquals(4,calculator.square(2))}, - DynamicTest.dynamicTest("when I calculate 3^2 then I get 9") { Assertions.assertEquals(9,calculator.square(3))} - ) - - @TestFactory - fun testSquaresFactory2() = listOf( - 1 to 1, - 2 to 4, - 3 to 9, - 4 to 16, - 5 to 25) - .map { (input, expected) -> - DynamicTest.dynamicTest("when I calculate $input^2 then I get $expected") { - Assertions.assertEquals(expected, calculator.square(input)) - } - } - - private val squaresTestData = listOf( - 1 to 1, - 2 to 4, - 3 to 9, - 4 to 16, - 5 to 25) - - @TestFactory - fun testSquaresFactory3() = squaresTestData - .map { (input, expected) -> - DynamicTest.dynamicTest("when I calculate $input^2 then I get $expected") { - Assertions.assertEquals(expected, calculator.square(input)) - } - } - @TestFactory - fun testSquareRootsFactory3() = squaresTestData - .map { (expected, input) -> - DynamicTest.dynamicTest("I calculate the square root of $input then I get $expected") { - Assertions.assertEquals(expected.toDouble(), calculator.squareRoot(input)) - } - } - - @Tags( - Tag("slow"), - Tag("logarithms") - ) - @Test - fun `Log to base 2 of 8 should be equal to 3`() { - Assertions.assertEquals(3.0, calculator.log(2, 8)) - } -} diff --git a/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/DivideByZeroException.kt b/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/DivideByZeroException.kt deleted file mode 100644 index 5675367fd5..0000000000 --- a/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/DivideByZeroException.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.junit5 - -class DivideByZeroException(val numerator: Int) : Exception() diff --git a/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/SimpleUnitTest.kt b/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/SimpleUnitTest.kt deleted file mode 100644 index e3fe998efd..0000000000 --- a/core-kotlin-modules/core-kotlin-testing/src/test/kotlin/com/baeldung/junit5/SimpleUnitTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.junit5 - -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test - -class SimpleUnitTest { - - @Test - fun `isEmpty should return true for empty lists`() { - val list = listOf() - Assertions.assertTrue(list::isEmpty) - } - - @Test - @Disabled - fun `3 is equal to 4`() { - Assertions.assertEquals(3, 4) { - "Three does not equal four" - } - } -} diff --git a/core-kotlin-modules/core-kotlin/README.md b/core-kotlin-modules/core-kotlin/README.md deleted file mode 100644 index 33f8745937..0000000000 --- a/core-kotlin-modules/core-kotlin/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## Core Kotlin - -This module contains articles about Kotlin core features. - -### Relevant articles: - -- [Introduction to the Kotlin Language](https://www.baeldung.com/kotlin-intro) -- [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) -- [Kotlin Ternary Conditional Operator](https://www.baeldung.com/kotlin-ternary-operator) -- [Sequences in Kotlin](https://www.baeldung.com/kotlin/sequences) -- [Converting Kotlin Data Class from JSON using GSON](https://www.baeldung.com/kotlin-json-convert-data-class) -- [Exception Handling in Kotlin](https://www.baeldung.com/kotlin/exception-handling) diff --git a/core-kotlin-modules/core-kotlin/pom.xml b/core-kotlin-modules/core-kotlin/pom.xml deleted file mode 100644 index 6e36b7c8ef..0000000000 --- a/core-kotlin-modules/core-kotlin/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - 4.0.0 - core-kotlin - core-kotlin - jar - - - com.baeldung.core-kotlin-modules - core-kotlin-modules - 1.0.0-SNAPSHOT - - - - - org.junit.platform - junit-platform-runner - ${junit.platform.version} - test - - - - - 1.1.1 - - - \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/interoperability/ArrayExample.java b/core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/interoperability/ArrayExample.java deleted file mode 100644 index 93b9a3984a..0000000000 --- a/core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/interoperability/ArrayExample.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.interoperability; - -import java.io.File; -import java.io.FileReader; -import java.io.IOException; - -public class ArrayExample { - - public int sumValues(int[] nums) { - int res = 0; - - for (int x:nums) { - res += x; - } - - return res; - } - - public void writeList() throws IOException { - File file = new File("E://file.txt"); - FileReader fr = new FileReader(file); - fr.close(); - } -} diff --git a/core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/introduction/StringUtils.java b/core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/introduction/StringUtils.java deleted file mode 100644 index 1c477ce039..0000000000 --- a/core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/introduction/StringUtils.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.baeldung.introduction; - -public class StringUtils { - public static String toUpperCase(String name) { - return name.toUpperCase(); - } -} diff --git a/core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/mavenjavakotlin/Application.java b/core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/mavenjavakotlin/Application.java deleted file mode 100644 index ac933d6228..0000000000 --- a/core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/mavenjavakotlin/Application.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.baeldung.mavenjavakotlin; - -import com.baeldung.mavenjavakotlin.services.JavaService; - -public class Application { - - private static final String JAVA = "java"; - private static final String KOTLIN = "kotlin"; - - public static void main(String[] args) { - String language = args[0]; - switch (language) { - case JAVA: - new JavaService().sayHello(); - break; - case KOTLIN: - new KotlinService().sayHello(); - break; - default: - // Do nothing - break; - } - } - -} diff --git a/core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/mavenjavakotlin/services/JavaService.java b/core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/mavenjavakotlin/services/JavaService.java deleted file mode 100644 index b767e761af..0000000000 --- a/core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/mavenjavakotlin/services/JavaService.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.baeldung.mavenjavakotlin.services; - -public class JavaService { - - public void sayHello() { - System.out.println("Java says 'Hello World!'"); - } - -} diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/exceptionhandling/ExceptionHandling.kt b/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/exceptionhandling/ExceptionHandling.kt deleted file mode 100644 index 6689ab43e4..0000000000 --- a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/exceptionhandling/ExceptionHandling.kt +++ /dev/null @@ -1,88 +0,0 @@ -package com.baeldung.exceptionhandling - -import java.io.IOException - -class ExceptionHandling { - - fun tryCatchBlock(): Int? { - try { - val message = "Welcome to Kotlin Tutorials" - return message.toInt() - } catch (exception: NumberFormatException) { - println("NumberFormatException in the code") - return null - } - } - - fun tryCatchExpression(): Int? { - val number = try { - val message = "Welcome to Kotlin Tutorials" - message.toInt() - } catch (exception: NumberFormatException) { - println("NumberFormatException in the code") - null - } - return number - } - - fun multipleCatchBlock(): Int? { - return try { - val result = 25 / 0 - result - } catch (exception: NumberFormatException) { - println("NumberFormatException in the code") - null - } catch (exception: ArithmeticException) { - println("ArithmeticException in the code") - null - } catch (exception: Exception) { - println("Exception in the code") - null - } - } - - fun nestedTryCatchBlock(): Int? { - return try { - val firstNumber = 50 / 2 * 0 - try { - val secondNumber = 100 / firstNumber - secondNumber - } catch (exception: ArithmeticException) { - println("ArithmeticException in the code") - null - } - } catch (exception: NumberFormatException) { - println("NumberFormatException in the code") - null - } - } - - fun finallyBlock(): Int? { - return try { - val message = "Welcome to Kotlin Tutorials" - message.toInt() - } catch (exception: NumberFormatException) { - println("NumberFormatException in the code") - null - } finally { - println("In the Finally block") - } - } - - fun throwKeyword(): Int { - val message = "Welcome to Kotlin Tutorials" - if (message.length > 10) throw IllegalArgumentException("String is invalid") - else return message.length - } - - fun throwExpression(): Int? { - val message: String? = null - return message?.length ?: throw IllegalArgumentException("String is null") - } - - @Throws(IOException::class) - fun throwsAnnotation(): String?{ - val filePath = null - return filePath ?: throw IOException("File path is invalid") - } -} diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/Example1.kt b/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/Example1.kt deleted file mode 100644 index aacd8f7915..0000000000 --- a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/Example1.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.baeldung.introduction - -fun main(args: Array){ - println("hello word") -} diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/Item.kt b/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/Item.kt deleted file mode 100644 index bb91dd1eae..0000000000 --- a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/Item.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.introduction - -open class Item(val id: String, val name: String = "unknown_name") { - open fun getIdOfItem(): String { - return id - } -} - -class ItemWithCategory(id: String, name: String, val categoryId: String) : Item(id, name) { - override fun getIdOfItem(): String { - return id + name - } -} - diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/ItemService.kt b/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/ItemService.kt deleted file mode 100644 index dfcf17df7c..0000000000 --- a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/ItemService.kt +++ /dev/null @@ -1,83 +0,0 @@ -package com.baeldung.introduction - -import java.util.* - -class ItemService { - fun findItemNameForId(id: String): Item? { - val itemId = UUID.randomUUID().toString() - return Item(itemId, "name-$itemId") - } -} - -class ItemManager(val categoryId: String, val dbConnection: String) { - var email = "" - - constructor(categoryId: String, dbConnection: String, email: String) - : this(categoryId, dbConnection) { - this.email = email - } - - fun isFromSpecificCategory(catId: String): Boolean { - return categoryId == catId - } - - fun makeAnalyisOfCategory(catId: String): Unit { - val result = if (catId == "100") "Yes" else "No" - println(result) - `object`() - } - - fun sum(a: Int, b: Int): Int { - return a + b - } - - fun `object`(): String { - return "this is object" - } - -} - -fun main(args: Array) { - val numbers = arrayOf("first", "second", "third", "fourth") - - for (n in numbers) { - println(n) - } - - for (i in 2..9 step 2) { - println(i) - } - - val res = 1.rangeTo(10).map { it * 2 } - println(res) - - val firstName = "Tom" - val secondName = "Mary" - val concatOfNames = "$firstName + $secondName" - println("Names: $concatOfNames") - val sum = "four: ${2 + 2}" - - val itemManager = ItemManager("cat_id", "db://connection") - ItemManager(categoryId = "catId", dbConnection = "db://Connection") - val result = "function result: ${itemManager.isFromSpecificCategory("1")}" - println(result) - - val number = 2 - if (number < 10) { - println("number less that 10") - } else if (number > 10) { - println("number is greater that 10") - } - - val name = "John" - when (name) { - "John" -> println("Hi man") - "Alice" -> println("Hi lady") - } - - val items = listOf(1, 2, 3, 4) - - - val rwList = mutableListOf(1, 2, 3) - rwList.add(5) -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/ListExtension.kt b/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/ListExtension.kt deleted file mode 100644 index e71292c60a..0000000000 --- a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/ListExtension.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.introduction - -import java.util.concurrent.ThreadLocalRandom - -class ListExtension { - fun List.random(): T? { - if (this.isEmpty()) return null - return get(ThreadLocalRandom.current().nextInt(count())) - } - - fun getRandomElementOfList(list: List): T? { - return list.random() - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/MathematicsOperations.kt b/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/MathematicsOperations.kt deleted file mode 100644 index 0ed30ed5b4..0000000000 --- a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/introduction/MathematicsOperations.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.baeldung.introduction - -class MathematicsOperations { - fun addTwoNumbers(a: Int, b: Int): Int { - return a + b - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/mavenjavakotlin/KotlinService.kt b/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/mavenjavakotlin/KotlinService.kt deleted file mode 100644 index 10d6a792d8..0000000000 --- a/core-kotlin-modules/core-kotlin/src/main/kotlin/com/baeldung/mavenjavakotlin/KotlinService.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.baeldung.mavenjavakotlin - -class KotlinService { - - fun sayHello() { - System.out.println("Kotlin says 'Hello World!'") - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin/src/test/java/com/baeldung/introduction/JavaCallToKotlinUnitTest.java b/core-kotlin-modules/core-kotlin/src/test/java/com/baeldung/introduction/JavaCallToKotlinUnitTest.java deleted file mode 100644 index 2c386eaad3..0000000000 --- a/core-kotlin-modules/core-kotlin/src/test/java/com/baeldung/introduction/JavaCallToKotlinUnitTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.introduction; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class JavaCallToKotlinUnitTest { - @Test - public void givenKotlinClass_whenCallFromJava_shouldProduceResults() { - //when - int res = new MathematicsOperations().addTwoNumbers(2, 4); - - //then - assertEquals(6, res); - - } -} diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/exceptionhandling/ExceptionHandlingUnitTest.kt b/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/exceptionhandling/ExceptionHandlingUnitTest.kt deleted file mode 100644 index af7aa4406f..0000000000 --- a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/exceptionhandling/ExceptionHandlingUnitTest.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.baeldung.exceptionhandling - -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows -import java.io.IOException -import kotlin.test.assertNull - -class ExceptionHandlingUnitTest { - - private val classUnderTest: ExceptionHandling = ExceptionHandling() - - @Test - fun givenInvalidConversion_whenTryCatchUsed_thenReturnsCatchBlockValue(){ - assertNull(classUnderTest.tryCatchBlock()) - } - - @Test - fun givenInvalidConversion_whenTryCatchExpressionUsed_thenReturnsCatchBlockValue(){ - assertNull(classUnderTest.tryCatchExpression()) - } - - @Test - fun givenDivisionByZero_whenMultipleCatchUsed_thenReturnsCatchBlockValue(){ - assertNull(classUnderTest.multipleCatchBlock()) - } - - @Test - fun givenDivisionByZero_whenNestedTryCatchUsed_thenReturnsNestedCatchBlockValue(){ - assertNull(classUnderTest.nestedTryCatchBlock()) - } - - @Test - fun givenInvalidConversion_whenTryCatchFinallyUsed_thenReturnsCatchAndFinallyBlock(){ - assertNull(classUnderTest.finallyBlock()) - } - - @Test - fun givenIllegalArgument_whenThrowKeywordUsed_thenThrowsException(){ - assertThrows { classUnderTest.throwKeyword() } - } - - @Test - fun givenIllegalArgument_whenElvisExpressionUsed_thenThrowsException(){ - assertThrows { classUnderTest.throwExpression() } - } - - @Test - fun whenAnnotationUsed_thenThrowsException(){ - assertThrows { classUnderTest.throwsAnnotation() } - } -} diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/interoperability/ArrayTest.kt b/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/interoperability/ArrayTest.kt deleted file mode 100644 index 8e9467f92a..0000000000 --- a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/interoperability/ArrayTest.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.baeldung.interoperability - -import org.junit.Test -import kotlin.test.assertEquals - -class ArrayTest { - - @Test - fun givenArray_whenValidateArrayType_thenComplete () { - val ex = ArrayExample() - val numArray = intArrayOf(1, 2, 3) - - assertEquals(ex.sumValues(numArray), 6) - } - - @Test - fun givenCustomer_whenGetSuperType_thenComplete() { - val instance = Customer::class - val supertypes = instance.supertypes - - assertEquals(supertypes[0].toString(), "kotlin.Any") - } - - @Test - fun givenCustomer_whenGetConstructor_thenComplete() { - val instance = Customer::class.java - val constructors = instance.constructors - - assertEquals(constructors.size, 1) - assertEquals(constructors[0].name, "com.baeldung.interoperability.Customer") - } - - fun makeReadFile() { - val ax = ArrayExample() - ax.writeList() - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/interoperability/CustomerTest.kt b/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/interoperability/CustomerTest.kt deleted file mode 100644 index c1b09cd0c1..0000000000 --- a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/interoperability/CustomerTest.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.interoperability - -import org.junit.Test -import kotlin.test.assertEquals - -class CustomerTest { - - @Test - fun givenCustomer_whenNameAndLastNameAreAssigned_thenComplete() { - val customer = Customer() - - // Setter method is being called - customer.firstName = "Frodo" - customer.lastName = "Baggins" - - // Getter method is being called - assertEquals(customer.firstName, "Frodo") - assertEquals(customer.lastName, "Baggins") - } - -} - diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/introduction/ItemServiceTest.kt b/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/introduction/ItemServiceTest.kt deleted file mode 100644 index 2ba14a7462..0000000000 --- a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/introduction/ItemServiceTest.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.introduction - -import org.junit.Test -import kotlin.test.assertNotNull - -class ItemServiceTest { - - @Test - fun givenItemId_whenGetForOptionalItem_shouldMakeActionOnNonNullValue() { - //given - val id = "item_id" - val itemService = ItemService() - - //when - val result = itemService.findItemNameForId(id) - - //then - assertNotNull(result?.let { it -> it.id }) - assertNotNull(result!!.id) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/introduction/KotlinJavaInteroperabilityTest.kt b/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/introduction/KotlinJavaInteroperabilityTest.kt deleted file mode 100644 index 5dddf9bfc9..0000000000 --- a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/introduction/KotlinJavaInteroperabilityTest.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.baeldung.introduction - -import org.junit.Test -import kotlin.test.assertEquals - - -class KotlinJavaInteroperabilityTest { - - @Test - fun givenLowercaseString_whenExecuteMethodFromJavaStringUtils_shouldReturnStringUppercase() { - //given - val name = "tom" - - //whene - val res = StringUtils.toUpperCase(name) - - //then - assertEquals(res, "TOM") - } -} diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/introduction/LambdaTest.kt b/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/introduction/LambdaTest.kt deleted file mode 100644 index 5e5166074e..0000000000 --- a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/introduction/LambdaTest.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.baeldung.introduction - -import org.junit.Test -import kotlin.test.assertEquals - - -class LambdaTest { - - @Test - fun givenListOfNumber_whenDoingOperationsUsingLambda_shouldReturnProperResult() { - //given - val listOfNumbers = listOf(1, 2, 3) - - //when - val sum = listOfNumbers.reduce { a, b -> a + b } - - //then - assertEquals(6, sum) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/introduction/ListExtensionTest.kt b/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/introduction/ListExtensionTest.kt deleted file mode 100644 index 38f244297b..0000000000 --- a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/introduction/ListExtensionTest.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.introduction - -import org.junit.Test -import kotlin.test.assertTrue - -class ListExtensionTest { - - @Test - fun givenList_whenExecuteExtensionFunctionOnList_shouldReturnRandomElementOfList() { - //given - val elements = listOf("a", "b", "c") - - //when - val result = ListExtension().getRandomElementOfList(elements) - - //then - assertTrue(elements.contains(result)) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/nullassertion/NotNullAssertionUnitTest.kt b/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/nullassertion/NotNullAssertionUnitTest.kt deleted file mode 100644 index 434f177927..0000000000 --- a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/nullassertion/NotNullAssertionUnitTest.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.baeldung.nullassertion - -import org.junit.Test -import kotlin.test.assertEquals - -class NotNullAssertionUnitTest { - - @Test - fun givenNullableValue_WhenNotNull_ShouldExtractTheValue() { - val answer: String? = "42" - - assertEquals(42, answer!!.toInt()) - } - - @Test(expected = KotlinNullPointerException::class) - fun givenNullableValue_WhenIsNull_ThenShouldThrow() { - val noAnswer: String? = null - noAnswer!! - } -} diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/random/RandomNumberTest.kt b/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/random/RandomNumberTest.kt deleted file mode 100644 index 2956a35f8a..0000000000 --- a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/random/RandomNumberTest.kt +++ /dev/null @@ -1,55 +0,0 @@ - -import org.junit.jupiter.api.Test -import java.util.concurrent.ThreadLocalRandom -import kotlin.test.assertTrue - -class RandomNumberTest { - - @Test - fun whenRandomNumberWithJavaUtilMath_thenResultIsBetween0And1() { - val randomNumber = Math.random() - assertTrue { randomNumber >=0 } - assertTrue { randomNumber <= 1 } - } - - @Test - fun whenRandomNumberWithJavaThreadLocalRandom_thenResultsInDefaultRanges() { - val randomDouble = ThreadLocalRandom.current().nextDouble() - val randomInteger = ThreadLocalRandom.current().nextInt() - val randomLong = ThreadLocalRandom.current().nextLong() - assertTrue { randomDouble >= 0 } - assertTrue { randomDouble <= 1 } - assertTrue { randomInteger >= Integer.MIN_VALUE } - assertTrue { randomInteger <= Integer.MAX_VALUE } - assertTrue { randomLong >= Long.MIN_VALUE } - assertTrue { randomLong <= Long.MAX_VALUE } - } - - @Test - fun whenRandomNumberWithKotlinJSMath_thenResultIsBetween0And1() { - val randomDouble = Math.random() - assertTrue { randomDouble >=0 } - assertTrue { randomDouble <= 1 } - } - - @Test - fun whenRandomNumberWithKotlinNumberRange_thenResultInGivenRange() { - val randomInteger = (1..12).shuffled().first() - assertTrue { randomInteger >= 1 } - assertTrue { randomInteger <= 12 } - } - - @Test - fun whenRandomNumberWithJavaThreadLocalRandom_thenResultsInGivenRanges() { - val randomDouble = ThreadLocalRandom.current().nextDouble(1.0, 10.0) - val randomInteger = ThreadLocalRandom.current().nextInt(1, 10) - val randomLong = ThreadLocalRandom.current().nextLong(1, 10) - assertTrue { randomDouble >= 1 } - assertTrue { randomDouble <= 10 } - assertTrue { randomInteger >= 1 } - assertTrue { randomInteger <= 10 } - assertTrue { randomLong >= 1 } - assertTrue { randomLong <= 10 } - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/sequences/SequencesTest.kt b/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/sequences/SequencesTest.kt deleted file mode 100644 index a41e213c44..0000000000 --- a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/sequences/SequencesTest.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.baeldung.sequeces - -import org.junit.Test -import kotlin.test.assertEquals -import java.time.Instant - -class SequencesTest { - - @Test - fun shouldBuildSequenceWhenUsingFromElements() { - val seqOfElements = sequenceOf("first" ,"second", "third") - .toList() - assertEquals(3, seqOfElements.count()) - } - - @Test - fun shouldBuildSequenceWhenUsingFromFunction() { - val seqFromFunction = generateSequence(Instant.now()) {it.plusSeconds(1)} - .take(3) - .toList() - assertEquals(3, seqFromFunction.count()) - } - - @Test - fun shouldBuildSequenceWhenUsingFromChunks() { - val seqFromChunks = sequence { - yield(1) - yieldAll((2..5).toList()) - }.toList() - assertEquals(5, seqFromChunks.count()) - } - - @Test - fun shouldBuildSequenceWhenUsingFromCollection() { - val seqFromIterable = (1..10) - .asSequence() - .toList() - assertEquals(10, seqFromIterable.count()) - } - - @Test - fun shouldShowNoCountDiffWhenUsingWithAndWithoutSequence() { - val withSequence = (1..10).asSequence() - .filter{it % 2 == 1} - .map { it * 2 } - .toList() - val withoutSequence = (1..10) - .filter{it % 2 == 1} - .map { it * 2 } - .toList() - assertEquals(withSequence.count(), withoutSequence.count()) - } - -} \ No newline at end of file diff --git a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/ternary/TernaryOperatorTest.kt b/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/ternary/TernaryOperatorTest.kt deleted file mode 100644 index 347290de72..0000000000 --- a/core-kotlin-modules/core-kotlin/src/test/kotlin/com/baeldung/ternary/TernaryOperatorTest.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.ternary - -import org.junit.Test -import kotlin.test.assertEquals - -class TernaryOperatorTest { - - @Test - fun `using If`() { - val a = true - val result = if (a) "yes" else "no" - assertEquals("yes", result) - } - - @Test - fun `using When`() { - val a = true - val result = when(a) { - true -> "yes" - false -> "no" - } - assertEquals("yes", result) - } - - @Test - fun `using elvis`() { - val a: String? = null - val result = a ?: "Default" - - assertEquals("Default", result) - } -} \ No newline at end of file diff --git a/core-kotlin-modules/pom.xml b/core-kotlin-modules/pom.xml deleted file mode 100644 index 67520a7dee..0000000000 --- a/core-kotlin-modules/pom.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - 4.0.0 - com.baeldung.core-kotlin-modules - core-kotlin-modules - core-kotlin-modules - pom - - - com.baeldung - parent-kotlin - 1.0.0-SNAPSHOT - ../parent-kotlin - - - - core-kotlin - core-kotlin-advanced - core-kotlin-annotations - core-kotlin-collections - core-kotlin-collections-2 - core-kotlin-concurrency - core-kotlin-date-time - core-kotlin-design-patterns - core-kotlin-io - core-kotlin-lang - core-kotlin-lang-2 - core-kotlin-lang-oop - core-kotlin-lang-oop-2 - core-kotlin-strings - core-kotlin-testing - - - - - - org.jetbrains.kotlin - kotlin-maven-plugin - ${kotlin.version} - - - compile - compile - - compile - - - - test-compile - test-compile - - test-compile - - - - - 1.8 - - - - - - - 1.3.30 - - - diff --git a/core-scala/README.md b/core-scala/README.md deleted file mode 100644 index 72b583c22b..0000000000 --- a/core-scala/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles: - -- [Pattern Matching in Scala](https://www.baeldung.com/scala/pattern-matching) diff --git a/core-scala/pom.xml b/core-scala/pom.xml deleted file mode 100644 index 8277b0f856..0000000000 --- a/core-scala/pom.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - 4.0.0 - core-scala - 1.0-SNAPSHOT - core-scala - jar - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - - - org.scala-lang - scala-library - ${scala.version} - - - - - src/main/scala - src/test/scala - - - net.alchim31.maven - scala-maven-plugin - ${scala.plugin.version} - - - - compile - testCompile - - - - -dependencyfile - ${project.build.directory}/.scala_dependencies - - - - - - - - - - 2.12.7 - 3.3.2 - - - diff --git a/ddd/pom.xml b/ddd/pom.xml index a67719f8a6..7d03208802 100644 --- a/ddd/pom.xml +++ b/ddd/pom.xml @@ -104,16 +104,12 @@ org.apache.maven.plugins maven-surefire-plugin - ${maven-surefire-plugin.version} - 2.22.2 - 1.0.1 - 5.6.2 diff --git a/discord4j/.gitignore b/discord4j/.gitignore new file mode 100644 index 0000000000..7ed0d6b679 --- /dev/null +++ b/discord4j/.gitignore @@ -0,0 +1,32 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ diff --git a/discord4j/README.md b/discord4j/README.md new file mode 100644 index 0000000000..58a9924666 --- /dev/null +++ b/discord4j/README.md @@ -0,0 +1,7 @@ +## DISCORD4J + +This module contains articles about Discord4J + +### Relevant Articles: + +- [Creating a Discord Bot with Discord4J + Spring Boot](https://www.baeldung.com/spring-discord4j-bot) \ No newline at end of file diff --git a/discord4j/pom.xml b/discord4j/pom.xml new file mode 100644 index 0000000000..664692f60a --- /dev/null +++ b/discord4j/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.3.5.RELEASE + + + com.baeldung + discord4j-bot + 0.0.1-SNAPSHOT + discord4j-bot + Demo Discord bot using Discord4J + Spring Boot + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-webflux + + + org.springframework.boot + spring-boot-starter-actuator + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + com.discord4j + discord4j-core + 3.1.1 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + diff --git a/discord4j/src/main/java/com/baeldung/discordbot/BotConfiguration.java b/discord4j/src/main/java/com/baeldung/discordbot/BotConfiguration.java new file mode 100644 index 0000000000..901308605b --- /dev/null +++ b/discord4j/src/main/java/com/baeldung/discordbot/BotConfiguration.java @@ -0,0 +1,46 @@ +package com.baeldung.discordbot; + +import com.baeldung.discordbot.events.EventListener; +import discord4j.core.DiscordClientBuilder; +import discord4j.core.GatewayDiscordClient; +import discord4j.core.event.domain.Event; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.List; + +@Configuration +public class BotConfiguration { + + private static final Logger log = LoggerFactory.getLogger( BotConfiguration.class ); + + @Value("${token}") + private String token; + + @Bean + public GatewayDiscordClient gatewayDiscordClient(List> eventListeners) { + GatewayDiscordClient client = null; + + try { + client = DiscordClientBuilder.create(token) + .build() + .login() + .block(); + + for(EventListener listener : eventListeners) { + client.on(listener.getEventType()) + .flatMap(listener::execute) + .onErrorResume(listener::handleError) + .subscribe(); + } + } + catch ( Exception exception ) { + log.error( "Be sure to use a valid bot token!", exception ); + } + + return client; + } +} diff --git a/discord4j/src/main/java/com/baeldung/discordbot/DiscordBotApplication.java b/discord4j/src/main/java/com/baeldung/discordbot/DiscordBotApplication.java new file mode 100644 index 0000000000..069a36635c --- /dev/null +++ b/discord4j/src/main/java/com/baeldung/discordbot/DiscordBotApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.discordbot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DiscordBotApplication { + + public static void main(String[] args) { + SpringApplication.run(DiscordBotApplication.class, args); + } +} diff --git a/discord4j/src/main/java/com/baeldung/discordbot/events/EventListener.java b/discord4j/src/main/java/com/baeldung/discordbot/events/EventListener.java new file mode 100644 index 0000000000..ca4c79de0d --- /dev/null +++ b/discord4j/src/main/java/com/baeldung/discordbot/events/EventListener.java @@ -0,0 +1,19 @@ +package com.baeldung.discordbot.events; + +import discord4j.core.event.domain.Event; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Mono; + +public interface EventListener { + + Logger LOG = LoggerFactory.getLogger(EventListener.class); + + Class getEventType(); + Mono execute(T event); + + default Mono handleError(Throwable error) { + LOG.error("Unable to process " + getEventType().getSimpleName(), error); + return Mono.empty(); + } +} diff --git a/discord4j/src/main/java/com/baeldung/discordbot/events/MessageCreateListener.java b/discord4j/src/main/java/com/baeldung/discordbot/events/MessageCreateListener.java new file mode 100644 index 0000000000..f545489804 --- /dev/null +++ b/discord4j/src/main/java/com/baeldung/discordbot/events/MessageCreateListener.java @@ -0,0 +1,19 @@ +package com.baeldung.discordbot.events; + +import discord4j.core.event.domain.message.MessageCreateEvent; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; + +@Service +public class MessageCreateListener extends MessageListener implements EventListener { + + @Override + public Class getEventType() { + return MessageCreateEvent.class; + } + + @Override + public Mono execute(MessageCreateEvent event) { + return processCommand(event.getMessage()); + } +} diff --git a/discord4j/src/main/java/com/baeldung/discordbot/events/MessageListener.java b/discord4j/src/main/java/com/baeldung/discordbot/events/MessageListener.java new file mode 100644 index 0000000000..e1f48468be --- /dev/null +++ b/discord4j/src/main/java/com/baeldung/discordbot/events/MessageListener.java @@ -0,0 +1,19 @@ +package com.baeldung.discordbot.events; + +import discord4j.core.object.entity.Message; +import reactor.core.publisher.Mono; + +public abstract class MessageListener { + + public Mono processCommand(Message eventMessage) { + return Mono.just(eventMessage) + .filter(message -> message.getAuthor().map(user -> !user.isBot()).orElse(false)) + .filter(message -> message.getContent().equalsIgnoreCase("!todo")) + .flatMap(Message::getChannel) + .flatMap(channel -> channel.createMessage("Things to do today:\n" + + " - write a bot\n" + + " - eat lunch\n" + + " - play a game")) + .then(); + } +} diff --git a/discord4j/src/main/java/com/baeldung/discordbot/events/MessageUpdateListener.java b/discord4j/src/main/java/com/baeldung/discordbot/events/MessageUpdateListener.java new file mode 100644 index 0000000000..62802d4903 --- /dev/null +++ b/discord4j/src/main/java/com/baeldung/discordbot/events/MessageUpdateListener.java @@ -0,0 +1,22 @@ +package com.baeldung.discordbot.events; + +import discord4j.core.event.domain.message.MessageUpdateEvent; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Mono; + +@Service +public class MessageUpdateListener extends MessageListener implements EventListener { + + @Override + public Class getEventType() { + return MessageUpdateEvent.class; + } + + @Override + public Mono execute(MessageUpdateEvent event) { + return Mono.just(event) + .filter(MessageUpdateEvent::isContentChanged) + .flatMap(MessageUpdateEvent::getMessage) + .flatMap(super::processCommand); + } +} diff --git a/discord4j/src/main/resources/application.yml b/discord4j/src/main/resources/application.yml new file mode 100644 index 0000000000..e2079e33b4 --- /dev/null +++ b/discord4j/src/main/resources/application.yml @@ -0,0 +1 @@ +token: 'our-token-here' diff --git a/discord4j/src/test/java/com/baeldung/discordbot/DiscordBotLiveTest.java b/discord4j/src/test/java/com/baeldung/discordbot/DiscordBotLiveTest.java new file mode 100644 index 0000000000..8d9a285748 --- /dev/null +++ b/discord4j/src/test/java/com/baeldung/discordbot/DiscordBotLiveTest.java @@ -0,0 +1,12 @@ +package com.baeldung.discordbot; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class DiscordBotLiveTest { + + @Test + public void contextTest() { + } +} diff --git a/docker/README.md b/docker/README.md index 8e5cc2b621..ce7fe261c2 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,4 +1,5 @@ ## Relevant Articles: - [Introduction to Docker Compose](https://www.baeldung.com/docker-compose) -- [Creating Docker Images with Spring Boot](https://www.baeldung.com/spring-boot-docker-images) +- [Reusing Docker Layers with Spring Boot](https://www.baeldung.com/docker-layers-spring-boot) +- [Running Spring Boot with PostgreSQL in Docker Compose](https://www.baeldung.com/spring-boot-postgresql-docker) diff --git a/docker/docker-internal-dto/pom.xml b/docker/docker-internal-dto/pom.xml new file mode 100644 index 0000000000..55cef257fe --- /dev/null +++ b/docker/docker-internal-dto/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + + com.baeldung.docker + docker + 0.0.1 + + + docker-internal-dto + docker-internal-dto + + diff --git a/docker/docker-internal-dto/src/main/java/com/baeldung/docker/dto/VariableDto.java b/docker/docker-internal-dto/src/main/java/com/baeldung/docker/dto/VariableDto.java new file mode 100644 index 0000000000..2de3b734ea --- /dev/null +++ b/docker/docker-internal-dto/src/main/java/com/baeldung/docker/dto/VariableDto.java @@ -0,0 +1,14 @@ +package com.baeldung.docker.dto; + +public class VariableDto { + + private final String value; + + public VariableDto(String value) { + this.value = value; + } + + public String getValue() { + return value; + } +} diff --git a/docker/docker-spring-boot-postgres/.gitignore b/docker/docker-spring-boot-postgres/.gitignore new file mode 100644 index 0000000000..802324853e --- /dev/null +++ b/docker/docker-spring-boot-postgres/.gitignore @@ -0,0 +1,38 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + + +### Custom exclusions ### + +*.jar diff --git a/docker/docker-spring-boot-postgres/.mvn/wrapper/MavenWrapperDownloader.java b/docker/docker-spring-boot-postgres/.mvn/wrapper/MavenWrapperDownloader.java new file mode 100644 index 0000000000..e76d1f3241 --- /dev/null +++ b/docker/docker-spring-boot-postgres/.mvn/wrapper/MavenWrapperDownloader.java @@ -0,0 +1,117 @@ +/* + * Copyright 2007-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.util.Properties; + +public class MavenWrapperDownloader { + + private static final String WRAPPER_VERSION = "0.5.6"; + /** + * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. + */ + private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" + + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; + + /** + * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to + * use instead of the default one. + */ + private static final String MAVEN_WRAPPER_PROPERTIES_PATH = + ".mvn/wrapper/maven-wrapper.properties"; + + /** + * Path where the maven-wrapper.jar will be saved to. + */ + private static final String MAVEN_WRAPPER_JAR_PATH = + ".mvn/wrapper/maven-wrapper.jar"; + + /** + * Name of the property which should be used to override the default download url for the wrapper. + */ + private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; + + public static void main(String args[]) { + System.out.println("- Downloader started"); + File baseDirectory = new File(args[0]); + System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); + + // If the maven-wrapper.properties exists, read it and check if it contains a custom + // wrapperUrl parameter. + File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); + String url = DEFAULT_DOWNLOAD_URL; + if(mavenWrapperPropertyFile.exists()) { + FileInputStream mavenWrapperPropertyFileInputStream = null; + try { + mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); + Properties mavenWrapperProperties = new Properties(); + mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); + url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); + } catch (IOException e) { + System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); + } finally { + try { + if(mavenWrapperPropertyFileInputStream != null) { + mavenWrapperPropertyFileInputStream.close(); + } + } catch (IOException e) { + // Ignore ... + } + } + } + System.out.println("- Downloading from: " + url); + + File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); + if(!outputFile.getParentFile().exists()) { + if(!outputFile.getParentFile().mkdirs()) { + System.out.println( + "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); + } + } + System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); + try { + downloadFileFromURL(url, outputFile); + System.out.println("Done"); + System.exit(0); + } catch (Throwable e) { + System.out.println("- Error downloading"); + e.printStackTrace(); + System.exit(1); + } + } + + private static void downloadFileFromURL(String urlString, File destination) throws Exception { + if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { + String username = System.getenv("MVNW_USERNAME"); + char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); + Authenticator.setDefault(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication(username, password); + } + }); + } + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } + +} diff --git a/docker/docker-spring-boot-postgres/.mvn/wrapper/maven-wrapper.jar b/docker/docker-spring-boot-postgres/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000000..2cc7d4a55c Binary files /dev/null and b/docker/docker-spring-boot-postgres/.mvn/wrapper/maven-wrapper.jar differ diff --git a/docker/docker-spring-boot-postgres/.mvn/wrapper/maven-wrapper.properties b/docker/docker-spring-boot-postgres/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..642d572ce9 --- /dev/null +++ b/docker/docker-spring-boot-postgres/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,2 @@ +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/docker/docker-spring-boot-postgres/mvnw b/docker/docker-spring-boot-postgres/mvnw new file mode 100755 index 0000000000..a16b5431b4 --- /dev/null +++ b/docker/docker-spring-boot-postgres/mvnw @@ -0,0 +1,310 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found .mvn/wrapper/maven-wrapper.jar" + fi +else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." + fi + if [ -n "$MVNW_REPOURL" ]; then + jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + else + jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + fi + while IFS="=" read key value; do + case "$key" in (wrapperUrl) jarUrl="$value"; break ;; + esac + done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" + if [ "$MVNW_VERBOSE" = true ]; then + echo "Downloading from: $jarUrl" + fi + wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" + if $cygwin; then + wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` + fi + + if command -v wget > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found wget ... using wget" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget "$jarUrl" -O "$wrapperJarPath" + else + wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + if [ "$MVNW_VERBOSE" = true ]; then + echo "Found curl ... using curl" + fi + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl -o "$wrapperJarPath" "$jarUrl" -f + else + curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f + fi + + else + if [ "$MVNW_VERBOSE" = true ]; then + echo "Falling back to using Java to download" + fi + javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaClass=`cygpath --path --windows "$javaClass"` + fi + if [ -e "$javaClass" ]; then + if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Compiling MavenWrapperDownloader.java ..." + fi + # Compiling the Java class + ("$JAVA_HOME/bin/javac" "$javaClass") + fi + if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then + # Running the downloader + if [ "$MVNW_VERBOSE" = true ]; then + echo " - Running MavenWrapperDownloader.java ..." + fi + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +if [ "$MVNW_VERBOSE" = true ]; then + echo $MAVEN_PROJECTBASEDIR +fi +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/docker/docker-spring-boot-postgres/mvnw.cmd b/docker/docker-spring-boot-postgres/mvnw.cmd new file mode 100644 index 0000000000..c8d43372c9 --- /dev/null +++ b/docker/docker-spring-boot-postgres/mvnw.cmd @@ -0,0 +1,182 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + +FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %DOWNLOAD_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/docker/docker-spring-boot-postgres/pom.xml b/docker/docker-spring-boot-postgres/pom.xml new file mode 100644 index 0000000000..0b359138f6 --- /dev/null +++ b/docker/docker-spring-boot-postgres/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.4.0 + + + com.baeldung.docker + docker-spring-boot-postgres + 0.0.1-SNAPSHOT + docker-spring-boot-postgres + Demo project showing Spring Boot, PostgreSQL, and Docker + + + 11 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + org.postgresql + postgresql + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/docker/docker-spring-boot-postgres/src/main/docker/Dockerfile b/docker/docker-spring-boot-postgres/src/main/docker/Dockerfile new file mode 100644 index 0000000000..a642876cbe --- /dev/null +++ b/docker/docker-spring-boot-postgres/src/main/docker/Dockerfile @@ -0,0 +1,7 @@ +FROM adoptopenjdk:11-jre-hotspot +MAINTAINER baeldung.com + +ARG JAR_FILE=*.jar +COPY ${JAR_FILE} application.jar + +ENTRYPOINT ["java", "-jar", "application.jar"] \ No newline at end of file diff --git a/docker/docker-spring-boot-postgres/src/main/docker/docker-compose.yml b/docker/docker-spring-boot-postgres/src/main/docker/docker-compose.yml new file mode 100644 index 0000000000..93aa634205 --- /dev/null +++ b/docker/docker-spring-boot-postgres/src/main/docker/docker-compose.yml @@ -0,0 +1,22 @@ +version: '2' + +services: + app: + image: 'docker-spring-boot-postgres:latest' + build: + context: . + container_name: app + depends_on: + - db + environment: + - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/compose-postgres + - SPRING_DATASOURCE_USERNAME=compose-postgres + - SPRING_DATASOURCE_PASSWORD=compose-postgres + - SPRING_JPA_HIBERNATE_DDL_AUTO=update + + db: + image: 'postgres:13.1-alpine' + container_name: db + environment: + - POSTGRES_USER=compose-postgres + - POSTGRES_PASSWORD=compose-postgres \ No newline at end of file diff --git a/docker/docker-spring-boot-postgres/src/main/java/com/baeldung/docker/Customer.java b/docker/docker-spring-boot-postgres/src/main/java/com/baeldung/docker/Customer.java new file mode 100644 index 0000000000..9369a84287 --- /dev/null +++ b/docker/docker-spring-boot-postgres/src/main/java/com/baeldung/docker/Customer.java @@ -0,0 +1,57 @@ +package com.baeldung.docker; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "customer") +public class Customer { + + @Id + @GeneratedValue + private long id; + + + @Column(name = "first_name", nullable = false) + private String firstName; + + @Column(name = "last_name", nullable = false) + private String lastName; + + public Customer() { + super(); + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Override + public String toString() { + return "Customer [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + "]"; + } + +} diff --git a/docker/docker-spring-boot-postgres/src/main/java/com/baeldung/docker/CustomerRepository.java b/docker/docker-spring-boot-postgres/src/main/java/com/baeldung/docker/CustomerRepository.java new file mode 100644 index 0000000000..c959e00c89 --- /dev/null +++ b/docker/docker-spring-boot-postgres/src/main/java/com/baeldung/docker/CustomerRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.docker; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CustomerRepository extends JpaRepository { + +} diff --git a/docker/docker-spring-boot-postgres/src/main/java/com/baeldung/docker/DemoApplication.java b/docker/docker-spring-boot-postgres/src/main/java/com/baeldung/docker/DemoApplication.java new file mode 100644 index 0000000000..05377c6893 --- /dev/null +++ b/docker/docker-spring-boot-postgres/src/main/java/com/baeldung/docker/DemoApplication.java @@ -0,0 +1,43 @@ +package com.baeldung.docker; + +import java.util.List; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; + +@SpringBootApplication +public class DemoApplication { + private final Logger logger = LoggerFactory.getLogger(DemoApplication.class); + + @Autowired private CustomerRepository repository; + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } + + @EventListener(ApplicationReadyEvent.class) + public void runAfterStartup() { + queryAllCustomers(); + createCustomer(); + queryAllCustomers(); + } + + private void createCustomer() { + Customer newCustomer = new Customer(); + newCustomer.setFirstName("John"); + newCustomer.setLastName("Doe"); + logger.info("Saving new customer..."); + this.repository.save(newCustomer); + } + + private void queryAllCustomers() { + List allCustomers = this.repository.findAll(); + logger.info("Number of customers: " + allCustomers.size()); + } + +} diff --git a/spring-security-modules/spring-security-kotlin-dsl/src/main/resources/application.properties b/docker/docker-spring-boot-postgres/src/main/resources/application.properties similarity index 100% rename from spring-security-modules/spring-security-kotlin-dsl/src/main/resources/application.properties rename to docker/docker-spring-boot-postgres/src/main/resources/application.properties diff --git a/docker/docker-spring-boot-postgres/src/test/java/com/baeldung/docker/DemoApplicationTests.java b/docker/docker-spring-boot-postgres/src/test/java/com/baeldung/docker/DemoApplicationTests.java new file mode 100644 index 0000000000..87bd1dd6ba --- /dev/null +++ b/docker/docker-spring-boot-postgres/src/test/java/com/baeldung/docker/DemoApplicationTests.java @@ -0,0 +1,13 @@ +package com.baeldung.docker; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class DemoApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/docker/docker-spring-boot/README.md b/docker/docker-spring-boot/README.md new file mode 100644 index 0000000000..4af9378290 --- /dev/null +++ b/docker/docker-spring-boot/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Creating Docker Images with Spring Boot](https://www.baeldung.com/spring-boot-docker-images) diff --git a/docker/docker-spring-boot/pom.xml b/docker/docker-spring-boot/pom.xml index b9c80bc43a..74bd1561cf 100644 --- a/docker/docker-spring-boot/pom.xml +++ b/docker/docker-spring-boot/pom.xml @@ -1,21 +1,21 @@ - + 4.0.0 - org.springframework.boot - spring-boot-starter-parent - 2.3.1.RELEASE - + com.baeldung.docker + docker + 0.0.1 - com.baeldung.docker - spring-boot-docker - 0.0.1-SNAPSHOT - spring-boot-docker + + docker-spring-boot + + docker-spring-boot Demo project showing Spring Boot and Docker - 8 + 11 @@ -24,6 +24,12 @@ spring-boot-starter-web + + com.baeldung.docker + docker-internal-dto + 0.0.1 + + org.springframework.boot spring-boot-starter-test @@ -45,6 +51,7 @@ true + ${project.basedir}/src/layers.xml diff --git a/docker/docker-spring-boot/src/layers.xml b/docker/docker-spring-boot/src/layers.xml new file mode 100644 index 0000000000..61c9bd9c39 --- /dev/null +++ b/docker/docker-spring-boot/src/layers.xml @@ -0,0 +1,27 @@ + + + + org/springframework/boot/loader/** + + + + + + *:*:*SNAPSHOT + + + com.baeldung.docker:*:* + + + + + dependencies + spring-boot-loader + internal-dependencies + snapshot-dependencies + application + + \ No newline at end of file diff --git a/docker/docker-spring-boot/src/main/docker/Dockerfile b/docker/docker-spring-boot/src/main/docker/Dockerfile index fa147dd69b..c0fd9c9cdb 100644 --- a/docker/docker-spring-boot/src/main/docker/Dockerfile +++ b/docker/docker-spring-boot/src/main/docker/Dockerfile @@ -9,7 +9,8 @@ RUN java -Djarmode=layertools -jar application.jar extract FROM adoptopenjdk:11-jre-hotspot COPY --from=builder dependencies/ ./ -COPY --from=builder snapshot-dependencies/ ./ COPY --from=builder spring-boot-loader/ ./ +COPY --from=builder internal-dependencies/ ./ +COPY --from=builder snapshot-dependencies/ ./ COPY --from=builder application/ ./ ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"] \ No newline at end of file diff --git a/docker/docker-spring-boot/src/main/java/com/baeldung/docker/spring/DemoApplication.java b/docker/docker-spring-boot/src/main/java/com/baeldung/docker/spring/DemoApplication.java new file mode 100644 index 0000000000..9210cabbb3 --- /dev/null +++ b/docker/docker-spring-boot/src/main/java/com/baeldung/docker/spring/DemoApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.docker.spring; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DemoApplication { + + public static void main(String[] args) { + SpringApplication.run(DemoApplication.class, args); + } + +} diff --git a/docker/docker-spring-boot/src/main/java/com/baeldung/docker/HelloController.java b/docker/docker-spring-boot/src/main/java/com/baeldung/docker/spring/HelloController.java similarity index 90% rename from docker/docker-spring-boot/src/main/java/com/baeldung/docker/HelloController.java rename to docker/docker-spring-boot/src/main/java/com/baeldung/docker/spring/HelloController.java index b463bb557f..430a158011 100644 --- a/docker/docker-spring-boot/src/main/java/com/baeldung/docker/HelloController.java +++ b/docker/docker-spring-boot/src/main/java/com/baeldung/docker/spring/HelloController.java @@ -1,4 +1,4 @@ -package com.baeldung.docker; +package com.baeldung.docker.spring; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; diff --git a/docker/pom.xml b/docker/pom.xml new file mode 100644 index 0000000000..f05c303938 --- /dev/null +++ b/docker/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 2.3.1.RELEASE + + + + com.baeldung.docker + docker + 0.0.1 + docker + Demo project showing Spring Boot and Docker + pom + + + 11 + + + + docker-internal-dto + docker-spring-boot + + + diff --git a/feign/pom.xml b/feign/pom.xml index 4b994be1f2..da3cbcb0fd 100644 --- a/feign/pom.xml +++ b/feign/pom.xml @@ -16,11 +16,6 @@ - - io.github.openfeign - feign-core - ${feign.version} - io.github.openfeign feign-okhttp @@ -44,21 +39,8 @@ - - - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot-maven-plugin.version} - - - - - - 9.4.0 - 1.4.2.RELEASE + 10.11 diff --git a/feign/src/test/java/com/baeldung/feign/clients/BookClientLiveTest.java b/feign/src/test/java/com/baeldung/feign/clients/BookClientLiveTest.java index bee440bd9e..6f6666de32 100644 --- a/feign/src/test/java/com/baeldung/feign/clients/BookClientLiveTest.java +++ b/feign/src/test/java/com/baeldung/feign/clients/BookClientLiveTest.java @@ -6,8 +6,6 @@ import com.baeldung.feign.models.BookResource; import lombok.extern.slf4j.Slf4j; import org.junit.Before; import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; import java.util.List; import java.util.UUID; @@ -22,7 +20,6 @@ import static org.junit.Assert.assertTrue; * Consumes https://github.com/Baeldung/spring-hypermedia-api */ @Slf4j -@RunWith(JUnit4.class) public class BookClientLiveTest { private BookClient bookClient; diff --git a/gradle/README.md b/gradle/README.md index 84a8508e2c..cf002a7114 100644 --- a/gradle/README.md +++ b/gradle/README.md @@ -8,3 +8,4 @@ This module contains articles about Gradle - [Creating a Fat Jar in Gradle](https://www.baeldung.com/gradle-fat-jar) - [A Custom Task in Gradle](https://www.baeldung.com/gradle-custom-task) - [Using JUnit 5 with Gradle](https://www.baeldung.com/junit-5-gradle) +- [Dependency Management in Gradle](https://www.baeldung.com/gradle-dependency-management) diff --git a/gradle/gradle-dependency-management/build.gradle b/gradle/gradle-dependency-management/build.gradle new file mode 100644 index 0000000000..88ed84f4b1 --- /dev/null +++ b/gradle/gradle-dependency-management/build.gradle @@ -0,0 +1,32 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '2.3.4.RELEASE' +} + +group = 'com.gradle' +version = '1.0.0' +sourceCompatibility = '14' + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter:2.3.4.RELEASE' + + testImplementation 'org.springframework.boot:spring-boot-starter-test:2.3.4.RELEASE' + + compileOnly 'org.projectlombok:lombok:1.18.14' + + testCompileOnly 'org.projectlombok:lombok:1.18.14' + + runtimeOnly files('libs/sampleOne.jar', 'libs/sampleTwo.jar') + + runtimeOnly fileTree('libs') { include '*.jar' } + +// implementation gradleApi() +} + +test { + useJUnitPlatform() +} diff --git a/kotlin-js/gradle/wrapper/gradle-wrapper.properties b/gradle/gradle-dependency-management/gradle/wrapper/gradle-wrapper.properties similarity index 92% rename from kotlin-js/gradle/wrapper/gradle-wrapper.properties rename to gradle/gradle-dependency-management/gradle/wrapper/gradle-wrapper.properties index 933b6473ce..12d38de6a4 100644 --- a/kotlin-js/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/gradle-dependency-management/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip diff --git a/gradle/gradle-dependency-management/settings.gradle b/gradle/gradle-dependency-management/settings.gradle new file mode 100644 index 0000000000..09bfe08af7 --- /dev/null +++ b/gradle/gradle-dependency-management/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'dependencymanagement' diff --git a/gradle/gradle-dependency-management/src/main/java/com/gradle/dependencymanagement/DependencyManagementApplication.java b/gradle/gradle-dependency-management/src/main/java/com/gradle/dependencymanagement/DependencyManagementApplication.java new file mode 100644 index 0000000000..7e589c0477 --- /dev/null +++ b/gradle/gradle-dependency-management/src/main/java/com/gradle/dependencymanagement/DependencyManagementApplication.java @@ -0,0 +1,13 @@ +package com.gradle.dependencymanagement; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DependencyManagementApplication { + + public static void main(String[] args) { + SpringApplication.run(DependencyManagementApplication.class, args); + } + +} diff --git a/spring-rest-testing/src/testFile b/gradle/gradle-dependency-management/src/main/resources/application.properties similarity index 100% rename from spring-rest-testing/src/testFile rename to gradle/gradle-dependency-management/src/main/resources/application.properties diff --git a/gradle/gradle-dependency-management/src/test/java/com/gradle/dependencymanagement/DependencyManagementApplicationUnitTests.java b/gradle/gradle-dependency-management/src/test/java/com/gradle/dependencymanagement/DependencyManagementApplicationUnitTests.java new file mode 100644 index 0000000000..85634a052e --- /dev/null +++ b/gradle/gradle-dependency-management/src/test/java/com/gradle/dependencymanagement/DependencyManagementApplicationUnitTests.java @@ -0,0 +1,13 @@ +package com.gradle.dependencymanagement; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class DependencyManagementApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/gradle/gradle-wrapper/README.md b/gradle/gradle-wrapper/README.md new file mode 100644 index 0000000000..972ced46c8 --- /dev/null +++ b/gradle/gradle-wrapper/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Guide to the Gradle Wrapper](https://www.baeldung.com/gradle-wrapper) diff --git a/guest/core-kotlin/README.md b/guest/core-kotlin/README.md new file mode 100644 index 0000000000..fad62ebea6 --- /dev/null +++ b/guest/core-kotlin/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Kotlin vs Java](https://www.baeldung.com/kotlin/vs-java) diff --git a/httpclient-2/README.md b/httpclient-2/README.md index 52d8b8fcff..9d7a9683cd 100644 --- a/httpclient-2/README.md +++ b/httpclient-2/README.md @@ -8,5 +8,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles: -- [How to Set TLS Version in Apache HttpClient](https://www.baeldung.com/TODO) +- [How to Set TLS Version in Apache HttpClient](https://www.baeldung.com/apache-httpclient-tls) +- [Reading an HTTP Response Body as a String in Java](https://www.baeldung.com/java-http-response-body-as-string) +- [How To Get Cookies From the Apache HttpClient Response](https://www.baeldung.com/java-apache-httpclient-cookies) - More articles: [[<-- prev]](../httpclient) diff --git a/httpclient-2/pom.xml b/httpclient-2/pom.xml index 1a27d9b5fe..7638c692dc 100644 --- a/httpclient-2/pom.xml +++ b/httpclient-2/pom.xml @@ -4,6 +4,7 @@ 4.0.0 httpclient-2 0.1-SNAPSHOT + httpclient-2 com.baeldung @@ -13,6 +14,7 @@ + org.apache.httpcomponents httpclient @@ -24,6 +26,19 @@ + + + + org.springframework.boot + spring-boot-starter-web + ${spring-boot.version} + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot.version} + test + @@ -34,10 +49,24 @@ true + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source.version} + ${maven.compiler.target.version} + + + 4.5.8 + 11 + 11 + 2.1.7.RELEASE \ No newline at end of file diff --git a/httpclient-2/src/test/java/com/baeldung/httpclient/cookies/HttpClientGettingCookieValueUnitTest.java b/httpclient-2/src/test/java/com/baeldung/httpclient/cookies/HttpClientGettingCookieValueUnitTest.java new file mode 100644 index 0000000000..404acb3098 --- /dev/null +++ b/httpclient-2/src/test/java/com/baeldung/httpclient/cookies/HttpClientGettingCookieValueUnitTest.java @@ -0,0 +1,56 @@ +package com.baeldung.httpclient.cookies; + +import org.apache.http.client.CookieStore; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.cookie.ClientCookie; +import org.apache.http.cookie.Cookie; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.cookie.BasicClientCookie; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +import static org.junit.Assert.assertEquals; + + +public class HttpClientGettingCookieValueUnitTest { + private static Logger log = LoggerFactory.getLogger(HttpClientGettingCookieValueUnitTest.class); + + private static final String SAMPLE_URL = "http://www.baeldung.com/"; + + @Test + public final void whenSettingCustomCookieOnTheRequest_thenGettingTheSameCookieFromTheResponse() throws IOException { + HttpClientContext context = HttpClientContext.create(); + context.setAttribute(HttpClientContext.COOKIE_STORE, createCustomCookieStore()); + + try (CloseableHttpClient httpClient = HttpClients.createDefault()) { + try (CloseableHttpResponse response = httpClient.execute(new HttpGet(SAMPLE_URL), context)) { + CookieStore cookieStore = context.getCookieStore(); + Cookie customCookie = cookieStore.getCookies() + .stream() + .peek(cookie -> log.info("cookie name:{}", cookie.getName())) + .filter(cookie -> "custom_cookie".equals(cookie.getName())) + .findFirst() + .orElseThrow(IllegalStateException::new); + + assertEquals("test_value", customCookie.getValue()); + } + } + } + + private BasicCookieStore createCustomCookieStore() { + BasicCookieStore cookieStore = new BasicCookieStore(); + BasicClientCookie cookie = new BasicClientCookie("custom_cookie", "test_value"); + cookie.setDomain("baeldung.com"); + cookie.setAttribute(ClientCookie.DOMAIN_ATTR, "true"); + cookie.setPath("/"); + cookieStore.addCookie(cookie); + return cookieStore; + } +} diff --git a/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClientUnitTest.java b/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClientUnitTest.java new file mode 100644 index 0000000000..5a638b2bd5 --- /dev/null +++ b/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/ApacheHttpClientUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.httpclient.readresponsebodystring; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.util.EntityUtils; +import org.junit.Test; + +import java.io.IOException; + +public class ApacheHttpClientUnitTest { + public static final String DUMMY_URL = "https://postman-echo.com/get"; + + @Test + public void whenUseApacheHttpClient_thenCorrect() throws IOException { + HttpGet request = new HttpGet(DUMMY_URL); + + try (CloseableHttpClient client = HttpClients.createDefault(); CloseableHttpResponse response = client.execute(request)) { + HttpEntity entity = response.getEntity(); + String result = EntityUtils.toString(entity); + System.out.println("Response -> " + result); + } + } +} diff --git a/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/HttpClientUnitTest.java b/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/HttpClientUnitTest.java new file mode 100644 index 0000000000..1dca1bf7c6 --- /dev/null +++ b/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/HttpClientUnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.httpclient.readresponsebodystring; + +import org.junit.Test; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; + +public class HttpClientUnitTest { + public static final String DUMMY_URL = "https://postman-echo.com/get"; + + @Test + public void whenUseHttpClient_thenCorrect() throws IOException, InterruptedException { + HttpClient client = HttpClient.newHttpClient(); + HttpRequest request = HttpRequest.newBuilder().uri(URI.create(DUMMY_URL)).build(); + + // synchronous response + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + System.out.println(response.body()); + + // asynchronous response + client.sendAsync(request, HttpResponse.BodyHandlers.ofString()) + .thenApply(HttpResponse::body) + .thenAccept(System.out::println) + .join(); + } +} diff --git a/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/HttpUrlConnectionUnitTest.java b/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/HttpUrlConnectionUnitTest.java new file mode 100644 index 0000000000..54ae887eb4 --- /dev/null +++ b/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/HttpUrlConnectionUnitTest.java @@ -0,0 +1,34 @@ +package com.baeldung.httpclient.readresponsebodystring; + +import org.junit.Assert; +import org.junit.Test; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +public class HttpUrlConnectionUnitTest { + + public static final String DUMMY_URL = "https://postman-echo.com/get"; + + @Test + public void whenUseHttpUrlConnection_thenCorrect() throws IOException { + HttpURLConnection connection = (HttpURLConnection) new URL(DUMMY_URL).openConnection(); + + InputStream inputStream = connection.getInputStream(); + + BufferedReader in = new BufferedReader(new InputStreamReader(inputStream)); + StringBuilder response = new StringBuilder(); + String currentLine; + + while ((currentLine = in.readLine()) != null) + response.append(currentLine); + + in.close(); + Assert.assertNotNull(response.toString()); + System.out.println("Response -> " + response.toString()); + } +} diff --git a/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/SpringRestTemplateUnitTest.java b/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/SpringRestTemplateUnitTest.java new file mode 100644 index 0000000000..c59d7662f1 --- /dev/null +++ b/httpclient-2/src/test/java/com/baeldung/httpclient/readresponsebodystring/SpringRestTemplateUnitTest.java @@ -0,0 +1,17 @@ +package com.baeldung.httpclient.readresponsebodystring; + +import org.junit.Test; +import org.springframework.web.client.RestTemplate; + +public class SpringRestTemplateUnitTest { + + public static final String DUMMY_URL = "https://postman-echo.com/get"; + + @Test + public void whenUseRestTemplate_thenCorrect() { + RestTemplate restTemplate = new RestTemplate(); + String response = restTemplate.getForObject(DUMMY_URL, String.class); + System.out.println(response); + } + +} diff --git a/httpclient-simple/README.md b/httpclient-simple/README.md index 098d5f278e..93fb22ac1e 100644 --- a/httpclient-simple/README.md +++ b/httpclient-simple/README.md @@ -11,6 +11,7 @@ This module contains articles about HTTPClient that are part of the HTTPClient E - [Custom HTTP Header with the HttpClient](https://www.baeldung.com/httpclient-custom-http-header) - [HttpClient Basic Authentication](https://www.baeldung.com/httpclient-4-basic-authentication) - [Posting with HttpClient](https://www.baeldung.com/httpclient-post-http-request) +- [Adding Parameters to HttpClient Requests](https://www.baeldung.com/java-httpclient-parameters) ### Running the Tests diff --git a/httpclient-simple/pom.xml b/httpclient-simple/pom.xml index 4b97070307..019f1af856 100644 --- a/httpclient-simple/pom.xml +++ b/httpclient-simple/pom.xml @@ -302,7 +302,7 @@ 2.5.1 4.4.11 - 4.5.8 + 4.5.8 1.6.1 diff --git a/httpclient-simple/src/test/java/com/baeldung/httpclient/HttpClientParamsLiveTest.java b/httpclient-simple/src/test/java/com/baeldung/httpclient/HttpClientParamsLiveTest.java new file mode 100644 index 0000000000..f3ea9be089 --- /dev/null +++ b/httpclient-simple/src/test/java/com/baeldung/httpclient/HttpClientParamsLiveTest.java @@ -0,0 +1,111 @@ +package com.baeldung.httpclient; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +import org.apache.http.NameValuePair; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.apache.http.message.BasicNameValuePair; +import org.junit.Before; +import org.junit.Test; + +public class HttpClientParamsLiveTest { + + private CloseableHttpClient client; + + private CloseableHttpResponse response; + + private List nameValuePairs; + + @Before + public void setUp() { + client = HttpClientBuilder.create() + .build(); + nameValuePairs = new ArrayList(); + NameValuePair param1NameValuePair = new BasicNameValuePair("param1", "value1"); + NameValuePair param2NameValuePair = new BasicNameValuePair("param2", "value2"); + nameValuePairs.add(param1NameValuePair); + nameValuePairs.add(param2NameValuePair); + } + + @Test + public void givenStringNameValuePairParams_whenGetRequest_thenResponseOk() throws URISyntaxException, ClientProtocolException, IOException { + HttpGet httpGet = new HttpGet("https://postman-echo.com/get"); + URI uri = new URIBuilder(httpGet.getURI()).addParameter("param1", "value1") + .addParameter("param2", "value2") + .build(); + ((HttpRequestBase) httpGet).setURI(uri); + response = client.execute(httpGet); + + assertThat(response.getStatusLine() + .getStatusCode(), equalTo(200)); + client.close(); + } + + @Test + public void givenStringNameValuePairParams_whenPostRequest_thenResponseOk() throws URISyntaxException, ClientProtocolException, IOException { + HttpPost httpPost = new HttpPost("https://postman-echo.com/post"); + URI uri = new URIBuilder(httpPost.getURI()).addParameter("param1", "value1") + .addParameter("param2", "value2") + .build(); + ((HttpRequestBase) httpPost).setURI(uri); + response = client.execute(httpPost); + + assertThat(response.getStatusLine() + .getStatusCode(), equalTo(200)); + client.close(); + } + + @Test + public void givenNameValuePairParams_whenGetRequest_thenResponseOk() throws URISyntaxException, ClientProtocolException, IOException { + HttpGet httpGet = new HttpGet("https://postman-echo.com/get"); + URI uri = new URIBuilder(httpGet.getURI()).addParameters(nameValuePairs) + .build(); + ((HttpRequestBase) httpGet).setURI(uri); + response = client.execute(httpGet); + + assertThat(response.getStatusLine() + .getStatusCode(), equalTo(200)); + client.close(); + } + + @Test + public void givenNameValuePairsParams_whenPostRequest_thenResponseOk() throws URISyntaxException, ClientProtocolException, IOException { + HttpPost httpPost = new HttpPost("https://postman-echo.com/post"); + URI uri = new URIBuilder(httpPost.getURI()).addParameters(nameValuePairs) + .build(); + ((HttpRequestBase) httpPost).setURI(uri); + response = client.execute(httpPost); + + assertThat(response.getStatusLine() + .getStatusCode(), equalTo(200)); + client.close(); + } + + @Test + public void givenUrlEncodedEntityParams_whenPostRequest_thenResponseOk() throws URISyntaxException, ClientProtocolException, IOException { + HttpPost httpPost = new HttpPost("https://postman-echo.com/post"); + httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, StandardCharsets.UTF_8)); + response = client.execute(httpPost); + + assertThat(response.getStatusLine() + .getStatusCode(), equalTo(200)); + client.close(); + } + +} diff --git a/httpclient-simple/src/test/java/com/baeldung/httpclient/sec/HttpClientCookieLiveTest.java b/httpclient-simple/src/test/java/com/baeldung/httpclient/sec/HttpClientCookieLiveTest.java index 287b6e996c..75286e5b2e 100644 --- a/httpclient-simple/src/test/java/com/baeldung/httpclient/sec/HttpClientCookieLiveTest.java +++ b/httpclient-simple/src/test/java/com/baeldung/httpclient/sec/HttpClientCookieLiveTest.java @@ -1,19 +1,23 @@ package com.baeldung.httpclient.sec; -import org.apache.http.client.HttpClient; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.cookie.ClientCookie; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.cookie.BasicClientCookie; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.HttpContext; import com.baeldung.httpclient.ResponseUtil; + import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; @@ -25,6 +29,8 @@ public class HttpClientCookieLiveTest { private CloseableHttpClient instance; private CloseableHttpResponse response; + + private static Logger log = LoggerFactory.getLogger(HttpClientCookieLiveTest.class); @Before public final void before() { @@ -54,11 +60,15 @@ public class HttpClientCookieLiveTest { final BasicCookieStore cookieStore = new BasicCookieStore(); final BasicClientCookie cookie = new BasicClientCookie("JSESSIONID", "1234"); cookie.setDomain(".github.com"); + cookie.setAttribute(ClientCookie.DOMAIN_ATTR, "true"); + cookie.setPath("/"); cookieStore.addCookie(cookie); - final HttpClient client = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build(); - - final HttpGet request = new HttpGet("http://www.github.com"); + + DefaultHttpClient client = new DefaultHttpClient(); + client.setCookieStore(cookieStore); + + final HttpGet request = new HttpGet("https://www.github.com"); response = (CloseableHttpResponse) client.execute(request); @@ -70,6 +80,7 @@ public class HttpClientCookieLiveTest { final BasicCookieStore cookieStore = new BasicCookieStore(); final BasicClientCookie cookie = new BasicClientCookie("JSESSIONID", "1234"); cookie.setDomain(".github.com"); + cookie.setAttribute(ClientCookie.DOMAIN_ATTR, "true"); cookie.setPath("/"); cookieStore.addCookie(cookie); instance = HttpClientBuilder.create().setDefaultCookieStore(cookieStore).build(); diff --git a/jackson-modules/jackson-conversions-2/README.md b/jackson-modules/jackson-conversions-2/README.md index 71c5578525..9986fe75b5 100644 --- a/jackson-modules/jackson-conversions-2/README.md +++ b/jackson-modules/jackson-conversions-2/README.md @@ -9,4 +9,5 @@ This module contains articles about Jackson conversions. - [Converting JSON to CSV in Java](https://www.baeldung.com/java-converting-json-to-csv) - [How to Process YAML with Jackson](https://www.baeldung.com/jackson-yaml) - [Jackson Streaming API](https://www.baeldung.com/jackson-streaming-api) +- [Jackson: java.util.LinkedHashMap cannot be cast to X](https://www.baeldung.com/jackson-linkedhashmap-cannot-be-cast) - More articles: [[<-- prev]](../jackson-conversions) diff --git a/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/tocollection/Book.java b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/tocollection/Book.java new file mode 100644 index 0000000000..e9cb1343e9 --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/tocollection/Book.java @@ -0,0 +1,70 @@ +package com.baeldung.jackson.tocollection; + + +import java.util.Objects; + +public class Book { + private Integer bookId; + private String title; + private String author; + + public Book() {} + + public Book(Integer bookId, String title, String author) { + this.bookId = bookId; + this.title = title; + this.author = author; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof Book)) { + return false; + } + + Book book = (Book) o; + + if (!Objects.equals(bookId, book.bookId)) { + return false; + } + if (!Objects.equals(title, book.title)) { + return false; + } + return Objects.equals(author, book.author); + } + + @Override + public int hashCode() { + int result = bookId != null ? bookId.hashCode() : 0; + result = 31 * result + (title != null ? title.hashCode() : 0); + result = 31 * result + (author != null ? author.hashCode() : 0); + return result; + } + + public Integer getBookId() { + return bookId; + } + + public void setBookId(Integer bookId) { + this.bookId = bookId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } +} diff --git a/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/tocollection/JsonToCollectionUtil.java b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/tocollection/JsonToCollectionUtil.java new file mode 100644 index 0000000000..83e2de2c3b --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/main/java/com/baeldung/jackson/tocollection/JsonToCollectionUtil.java @@ -0,0 +1,24 @@ +package com.baeldung.jackson.tocollection; + +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.CollectionType; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class JsonToCollectionUtil { + + private JsonToCollectionUtil(){} + + public static List jsonArrayToList(String json, Class elementClass) throws IOException { + ObjectMapper objectMapper = new ObjectMapper(); + CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, elementClass); + return objectMapper.readValue(json, listType); + } + + public static List jsonArrayToList2(String json, Class elementClass) throws IOException { + return new ObjectMapper().readValue(json, new TypeReference>() {}); + } +} diff --git a/jackson-modules/jackson-conversions-2/src/main/resources/to-java-collection/books.json b/jackson-modules/jackson-conversions-2/src/main/resources/to-java-collection/books.json new file mode 100644 index 0000000000..6daf426736 --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/main/resources/to-java-collection/books.json @@ -0,0 +1,13 @@ +[ { + "bookId" : 1, + "title" : "A Song of Ice and Fire", + "author" : "George R. R. Martin" +}, { + "bookId" : 2, + "title" : "The Hitchhiker's Guide to the Galaxy", + "author" : "Douglas Adams" +}, { + "bookId" : 3, + "title" : "Hackers And Painters", + "author" : "Paul Graham" +} ] diff --git a/jackson-modules/jackson-conversions-2/src/main/resources/to-java-collection/books.xml b/jackson-modules/jackson-conversions-2/src/main/resources/to-java-collection/books.xml new file mode 100644 index 0000000000..b2f951315b --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/main/resources/to-java-collection/books.xml @@ -0,0 +1,17 @@ + + + 1 + A Song of Ice and Fire + George R. R. Martin + + + 2 + The Hitchhiker's Guide to the Galaxy + Douglas Adams + + + 3 + Hackers And Painters + Paul Graham + + diff --git a/jackson-modules/jackson-conversions-2/src/test/java/com/baeldung/jackson/tocollection/DeserializeToJavaCollectionUnitTest.java b/jackson-modules/jackson-conversions-2/src/test/java/com/baeldung/jackson/tocollection/DeserializeToJavaCollectionUnitTest.java new file mode 100644 index 0000000000..8ddcc2d69a --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/test/java/com/baeldung/jackson/tocollection/DeserializeToJavaCollectionUnitTest.java @@ -0,0 +1,130 @@ +package com.baeldung.jackson.tocollection; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.CollectionType; +import com.fasterxml.jackson.dataformat.xml.XmlMapper; +import org.assertj.core.util.Lists; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +public class DeserializeToJavaCollectionUnitTest { + private ObjectMapper objectMapper; + private XmlMapper xmlMapper; + private List expectedBookList; + + + @BeforeEach + void setup() { + objectMapper = new ObjectMapper(); + xmlMapper = new XmlMapper(); + expectedBookList = Lists.newArrayList( + new Book(1, "A Song of Ice and Fire", "George R. R. Martin"), + new Book(2, "The Hitchhiker's Guide to the Galaxy", "Douglas Adams"), + new Book(3, "Hackers And Painters", "Paul Graham")); + } + + private String readFile(String path) { + try (Scanner scanner = new Scanner(getClass().getResourceAsStream(path), "UTF-8")) { + return scanner.useDelimiter("\\A").next(); + } + } + + /*==================== + * JSON tests + *==================== + */ + @Test + void givenJsonString_whenDeserializingToList_thenThrowingClassCastException() throws JsonProcessingException { + String jsonString = readFile("/to-java-collection/books.json"); + List bookList = objectMapper.readValue(jsonString, ArrayList.class); + assertThat(bookList).size().isEqualTo(3); + assertThatExceptionOfType(ClassCastException.class) + .isThrownBy(() -> bookList.get(0).getBookId()) + .withMessageMatching(".*java.util.LinkedHashMap cannot be cast to .*com.baeldung.jackson.tocollection.Book.*"); + } + + @Test + void givenJsonString_whenDeserializingWithTypeReference_thenGetExpectedList() throws JsonProcessingException { + String jsonString = readFile("/to-java-collection/books.json"); + List bookList = objectMapper.readValue(jsonString, new TypeReference>() {}); + assertThat(bookList.get(0)).isInstanceOf(Book.class); + assertThat(bookList).isEqualTo(expectedBookList); + } + + @Test + void givenJsonString_whenDeserializingWithJavaType_thenGetExpectedList() throws JsonProcessingException { + String jsonString = readFile("/to-java-collection/books.json"); + CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, Book.class); + List bookList = objectMapper.readValue(jsonString, listType); + assertThat(bookList.get(0)).isInstanceOf(Book.class); + assertThat(bookList).isEqualTo(expectedBookList); + } + + @Test + void givenJsonString_whenDeserializingWithConvertValueAndTypeReference_thenGetExpectedList() throws JsonProcessingException { + String jsonString = readFile("/to-java-collection/books.json"); + JsonNode jsonNode = objectMapper.readTree(jsonString); + List bookList = objectMapper.convertValue(jsonNode, new TypeReference>() {}); + assertThat(bookList.get(0)).isInstanceOf(Book.class); + assertThat(bookList).isEqualTo(expectedBookList); + } + + @Test + void givenJsonString_whenDeserializingWithConvertValueAndJavaType_thenGetExpectedList() throws JsonProcessingException { + String jsonString = readFile("/to-java-collection/books.json"); + JsonNode jsonNode = objectMapper.readTree(jsonString); + List bookList = objectMapper.convertValue(jsonNode, objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, Book.class)); + assertThat(bookList.get(0)).isInstanceOf(Book.class); + assertThat(bookList).isEqualTo(expectedBookList); + } + + /*==================== + * XML tests + *==================== + */ + @Test + void givenXml_whenDeserializingToList_thenThrowingClassCastException() throws JsonProcessingException { + String xml = readFile("/to-java-collection/books.xml"); + List bookList = xmlMapper.readValue(xml, ArrayList.class); + assertThat(bookList).size().isEqualTo(3); + assertThatExceptionOfType(ClassCastException.class) + .isThrownBy(() -> bookList.get(0).getBookId()) + .withMessageMatching(".*java.util.LinkedHashMap cannot be cast to .*com.baeldung.jackson.tocollection.Book.*"); + } + + @Test + void givenXml_whenDeserializingWithTypeReference_thenGetExpectedList() throws JsonProcessingException { + String xml = readFile("/to-java-collection/books.xml"); + List bookList = xmlMapper.readValue(xml, new TypeReference>() {}); + assertThat(bookList.get(0)).isInstanceOf(Book.class); + assertThat(bookList).isEqualTo(expectedBookList); + } + + @Test + void givenXml_whenDeserializingWithConvertValueAndTypeReference_thenGetExpectedList() throws JsonProcessingException { + String xml = readFile("/to-java-collection/books.xml"); + List node = xmlMapper.readValue(xml, List.class); + List bookList = xmlMapper.convertValue(node, new TypeReference>() {}); + assertThat(bookList.get(0)).isInstanceOf(Book.class); + assertThat(bookList).isEqualTo(expectedBookList); + } + + @Test + void givenXml_whenDeserializingWithConvertValueAndJavaType_thenGetExpectedList() throws JsonProcessingException { + String xml = readFile("/to-java-collection/books.xml"); + List node = xmlMapper.readValue(xml, List.class); + List bookList = xmlMapper.convertValue(node, objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, Book.class)); + assertThat(bookList.get(0)).isInstanceOf(Book.class); + assertThat(bookList).isEqualTo(expectedBookList); + } +} diff --git a/jackson-modules/jackson-conversions-2/src/test/java/com/baeldung/jackson/tocollection/JsonToCollectionUtilUnitTest.java b/jackson-modules/jackson-conversions-2/src/test/java/com/baeldung/jackson/tocollection/JsonToCollectionUtilUnitTest.java new file mode 100644 index 0000000000..a08e48e069 --- /dev/null +++ b/jackson-modules/jackson-conversions-2/src/test/java/com/baeldung/jackson/tocollection/JsonToCollectionUtilUnitTest.java @@ -0,0 +1,51 @@ +package com.baeldung.jackson.tocollection; + +import org.assertj.core.util.Lists; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.List; +import java.util.Scanner; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +class JsonToCollectionUtilUnitTest { + + private List expectedBookList; + + + @BeforeEach + void setup() { + expectedBookList = Lists.newArrayList( + new Book(1, "A Song of Ice and Fire", "George R. R. Martin"), + new Book(2, "The Hitchhiker's Guide to the Galaxy", "Douglas Adams"), + new Book(3, "Hackers And Painters", "Paul Graham")); + } + + private String readFile(String path) { + try (Scanner scanner = new Scanner(getClass().getResourceAsStream(path), "UTF-8")) { + return scanner.useDelimiter("\\A").next(); + } + } + + @Test + void givenJsonString_whenCalljsonArrayToList_thenGetExpectedList() throws IOException { + String jsonString = readFile("/to-java-collection/books.json"); + List bookList = JsonToCollectionUtil.jsonArrayToList(jsonString, Book.class); + assertThat(bookList.get(0)).isInstanceOf(Book.class); + assertThat(bookList).isEqualTo(expectedBookList); + } + + @Test + void givenJsonString_whenCalljsonArrayToList2_thenGetException() throws IOException { + String jsonString = readFile("/to-java-collection/books.json"); + List bookList = JsonToCollectionUtil.jsonArrayToList2(jsonString, Book.class); + assertThat(bookList).size().isEqualTo(3); + assertThatExceptionOfType(ClassCastException.class) + .isThrownBy(() -> bookList.get(0).getBookId()) + .withMessageMatching(".*java.util.LinkedHashMap cannot be cast to .*com.baeldung.jackson.tocollection.Book.*"); + } + +} diff --git a/jackson-modules/jackson-custom-conversions/pom.xml b/jackson-modules/jackson-custom-conversions/pom.xml index c319891da9..f58b25781c 100644 --- a/jackson-modules/jackson-custom-conversions/pom.xml +++ b/jackson-modules/jackson-custom-conversions/pom.xml @@ -23,6 +23,13 @@ jackson-datatype-joda ${jackson.version} + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + diff --git a/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/deserialization/CustomDeserializationUnitTest.java b/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/deserialization/CustomDeserializationUnitTest.java index f2a2502c3e..17016149a2 100644 --- a/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/deserialization/CustomDeserializationUnitTest.java +++ b/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/deserialization/CustomDeserializationUnitTest.java @@ -60,8 +60,6 @@ public class CustomDeserializationUnitTest { String converted = objectMapper.writeValueAsString(now); // restore an instance of ZonedDateTime from String ZonedDateTime restored = objectMapper.readValue(converted, ZonedDateTime.class); - System.out.println("serialized: " + now); - System.out.println("restored: " + restored); assertThat(now, is(not(restored))); } @@ -70,15 +68,14 @@ public class CustomDeserializationUnitTest { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.findAndRegisterModules(); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + objectMapper.enable(SerializationFeature.WRITE_DATES_WITH_ZONE_ID); objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE); // construct a new instance of ZonedDateTime ZonedDateTime now = ZonedDateTime.now(ZoneId.of("Europe/Berlin")); String converted = objectMapper.writeValueAsString(now); // restore an instance of ZonedDateTime from String ZonedDateTime restored = objectMapper.readValue(converted, ZonedDateTime.class); - System.out.println("serialized: " + now); - System.out.println("restored: " + restored); - assertThat(now, is(restored)); + assertThat(restored, is(now)); } } diff --git a/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/serialization/CustomSerializationUnitTest.java b/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/serialization/CustomSerializationUnitTest.java index 6cb4019fa2..9c46a86fd8 100644 --- a/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/serialization/CustomSerializationUnitTest.java +++ b/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/serialization/CustomSerializationUnitTest.java @@ -24,7 +24,6 @@ public class CustomSerializationUnitTest { public final void whenSerializing_thenNoExceptions() throws JsonGenerationException, JsonMappingException, IOException { final Item myItem = new Item(1, "theItem", new User(2, "theUser")); final String serialized = new ObjectMapper().writeValueAsString(myItem); - System.out.println(serialized); } @Test @@ -38,7 +37,6 @@ public class CustomSerializationUnitTest { mapper.registerModule(simpleModule); final String serialized = mapper.writeValueAsString(myItem); - System.out.println(serialized); } @Test @@ -46,7 +44,6 @@ public class CustomSerializationUnitTest { final ItemWithSerializer myItem = new ItemWithSerializer(1, "theItem", new User(2, "theUser")); final String serialized = new ObjectMapper().writeValueAsString(myItem); - System.out.println(serialized); } } diff --git a/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/skipfields/IgnoreFieldsWithFilterUnitTest.java b/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/skipfields/IgnoreFieldsWithFilterUnitTest.java index e71f31bc6a..ec753019b2 100644 --- a/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/skipfields/IgnoreFieldsWithFilterUnitTest.java +++ b/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/skipfields/IgnoreFieldsWithFilterUnitTest.java @@ -37,7 +37,6 @@ public class IgnoreFieldsWithFilterUnitTest { assertThat(dtoAsString, not(containsString("intValue"))); assertThat(dtoAsString, containsString("booleanValue")); assertThat(dtoAsString, containsString("stringValue")); - System.out.println(dtoAsString); } @Test @@ -83,7 +82,6 @@ public class IgnoreFieldsWithFilterUnitTest { assertThat(dtoAsString, not(containsString("intValue"))); assertThat(dtoAsString, containsString("booleanValue")); assertThat(dtoAsString, containsString("stringValue")); - System.out.println(dtoAsString); } } diff --git a/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/skipfields/JacksonDynamicIgnoreUnitTest.java b/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/skipfields/JacksonDynamicIgnoreUnitTest.java index 6ba14f7476..2fd59e2a82 100644 --- a/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/skipfields/JacksonDynamicIgnoreUnitTest.java +++ b/jackson-modules/jackson-custom-conversions/src/test/java/com/baeldung/skipfields/JacksonDynamicIgnoreUnitTest.java @@ -51,8 +51,6 @@ public class JacksonDynamicIgnoreUnitTest { assertTrue(result.contains("john")); assertTrue(result.contains("address")); assertTrue(result.contains("usa")); - - System.out.println("Not Hidden = " + result); } @Test @@ -65,8 +63,6 @@ public class JacksonDynamicIgnoreUnitTest { assertTrue(result.contains("john")); assertFalse(result.contains("address")); assertFalse(result.contains("usa")); - - System.out.println("Address Hidden = " + result); } @Test @@ -76,8 +72,6 @@ public class JacksonDynamicIgnoreUnitTest { final String result = mapper.writeValueAsString(person); assertTrue(result.length() == 0); - - System.out.println("All Hidden = " + result); } @Test @@ -90,7 +84,5 @@ public class JacksonDynamicIgnoreUnitTest { final Person p3 = new Person("adam", ad3, false); final String result = mapper.writeValueAsString(Arrays.asList(p1, p2, p3)); - - System.out.println(result); } } diff --git a/jackson-modules/jackson/README.md b/jackson-modules/jackson/README.md index bcf8c3036f..50e13a5b75 100644 --- a/jackson-modules/jackson/README.md +++ b/jackson-modules/jackson/README.md @@ -10,6 +10,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Using Optional with Jackson](https://www.baeldung.com/jackson-optional) - [Compare Two JSON Objects with Jackson](https://www.baeldung.com/jackson-compare-two-json-objects) - [Jackson vs Gson](https://www.baeldung.com/jackson-vs-gson) -- [Jackson JSON Tutorial](https://www.baeldung.com/jackson) - [Inheritance with Jackson](https://www.baeldung.com/jackson-inheritance) - [Working with Tree Model Nodes in Jackson](https://www.baeldung.com/jackson-json-node-tree-model) diff --git a/java-collections-maps-3/README.md b/java-collections-maps-3/README.md index 4da8547824..bd1029c9cf 100644 --- a/java-collections-maps-3/README.md +++ b/java-collections-maps-3/README.md @@ -1,3 +1,5 @@ ### Relevant Articles: - [Java Map With Case-Insensitive Keys](https://www.baeldung.com/java-map-with-case-insensitive-keys) +- [Using a Byte Array as Map Key in Java](https://www.baeldung.com/java-map-key-byte-array) +- [Using the Map.Entry Java Class](https://www.baeldung.com/java-map-entry) diff --git a/java-collections-maps-3/src/main/java/com/baeldung/map/bytearrays/BytesKey.java b/java-collections-maps-3/src/main/java/com/baeldung/map/bytearrays/BytesKey.java new file mode 100644 index 0000000000..4bdcfe4b06 --- /dev/null +++ b/java-collections-maps-3/src/main/java/com/baeldung/map/bytearrays/BytesKey.java @@ -0,0 +1,28 @@ +package com.baeldung.map.bytearrays; + +import java.util.Arrays; + +public final class BytesKey { + private final byte[] array; + + public BytesKey(byte[] array) { + this.array = array; + } + + public byte[] getArray() { + return array.clone(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + BytesKey bytesKey = (BytesKey) o; + return Arrays.equals(array, bytesKey.array); + } + + @Override + public int hashCode() { + return Arrays.hashCode(array); + } +} diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Book.java b/java-collections-maps-3/src/main/java/com/baeldung/map/entry/Book.java similarity index 52% rename from persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Book.java rename to java-collections-maps-3/src/main/java/com/baeldung/map/entry/Book.java index 507043dd56..7e47e22908 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Book.java +++ b/java-collections-maps-3/src/main/java/com/baeldung/map/entry/Book.java @@ -1,20 +1,12 @@ -package com.baeldung.persistence.model; +package com.baeldung.map.entry; -import javax.persistence.Entity; -import javax.persistence.Id; - -@Entity public class Book { - - @Id - private Long id; - private String title; - private String author; - public Long getId() { - return id; + public Book(String title, String author) { + this.title = title; + this.author = author; } public String getTitle() { @@ -33,4 +25,11 @@ public class Book { this.author = author; } + @Override + public String toString() { + return "Book{" + + "title='" + title + '\'' + + ", author='" + author + '\'' + + '}'; + } } diff --git a/java-collections-maps-3/src/main/java/com/baeldung/map/entry/MapEntryEfficiencyExample.java b/java-collections-maps-3/src/main/java/com/baeldung/map/entry/MapEntryEfficiencyExample.java new file mode 100644 index 0000000000..d64bcb38df --- /dev/null +++ b/java-collections-maps-3/src/main/java/com/baeldung/map/entry/MapEntryEfficiencyExample.java @@ -0,0 +1,34 @@ +package com.baeldung.map.entry; + +import java.util.HashMap; +import java.util.Map; + +public class MapEntryEfficiencyExample { + + public static void main(String[] args) { + MapEntryEfficiencyExample mapEntryEfficiencyExample = new MapEntryEfficiencyExample(); + Map map = new HashMap<>(); + + map.put("Robert C. Martin", "Clean Code"); + map.put("Joshua Bloch", "Effective Java"); + + System.out.println("Iterating Using Map.KeySet - 2 operations"); + mapEntryEfficiencyExample.usingKeySet(map); + + System.out.println("Iterating Using Map.Entry - 1 operation"); + mapEntryEfficiencyExample.usingEntrySet(map); + + } + + public void usingKeySet(Map bookMap) { + for (String key : bookMap.keySet()) { + System.out.println("key: " + key + " value: " + bookMap.get(key)); + } + } + + public void usingEntrySet(Map bookMap) { + for (Map.Entry book: bookMap.entrySet()) { + System.out.println("key: " + book.getKey() + " value: " + book.getValue()); + } + } +} diff --git a/java-collections-maps-3/src/main/java/com/baeldung/map/entry/MapEntryTupleExample.java b/java-collections-maps-3/src/main/java/com/baeldung/map/entry/MapEntryTupleExample.java new file mode 100644 index 0000000000..edcbd263fe --- /dev/null +++ b/java-collections-maps-3/src/main/java/com/baeldung/map/entry/MapEntryTupleExample.java @@ -0,0 +1,25 @@ +package com.baeldung.map.entry; + +import java.util.*; + +public class MapEntryTupleExample { + + public static void main(String[] args) { + Map.Entry tuple1; + Map.Entry tuple2; + Map.Entry tuple3; + + tuple1 = new AbstractMap.SimpleEntry<>("9780134685991", new Book("Effective Java 3d Edition", "Joshua Bloch")); + tuple2 = new AbstractMap.SimpleEntry<>("9780132350884", new Book("Clean Code", "Robert C Martin")); + tuple3 = new AbstractMap.SimpleEntry<>("9780132350884", new Book("Clean Code", "Robert C Martin")); + + List> orderedTuples = new ArrayList<>(); + orderedTuples.add(tuple1); + orderedTuples.add(tuple2); + orderedTuples.add(tuple3); + + for (Map.Entry tuple : orderedTuples) { + System.out.println("key: " + tuple.getKey() + " value: " + tuple.getValue()); + } + } +} diff --git a/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/Member.java b/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/Member.java new file mode 100644 index 0000000000..22b6a61d4d --- /dev/null +++ b/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/Member.java @@ -0,0 +1,6 @@ +package com.baeldung.map.hashing; + +class Member { + Integer id; + String name; +} diff --git a/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithBadHashing.java b/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithBadHashing.java new file mode 100644 index 0000000000..2a69291742 --- /dev/null +++ b/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithBadHashing.java @@ -0,0 +1,8 @@ +package com.baeldung.map.hashing; + +public class MemberWithBadHashing extends Member { + @Override + public int hashCode() { + return name.hashCode(); + } +} diff --git a/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithGuavaHashing.java b/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithGuavaHashing.java new file mode 100644 index 0000000000..bb33ace0b7 --- /dev/null +++ b/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithGuavaHashing.java @@ -0,0 +1,18 @@ +package com.baeldung.map.hashing; + +import com.google.common.base.Charsets; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hashing; + +public class MemberWithGuavaHashing extends Member { + @Override + public int hashCode() { + HashFunction hashFunction = Hashing.murmur3_32(); + return hashFunction.newHasher() + .putInt(id) + .putString(name, Charsets.UTF_8) + .hash().hashCode(); + } + + +} diff --git a/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithId.java b/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithId.java new file mode 100644 index 0000000000..5d82eb0cb7 --- /dev/null +++ b/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithId.java @@ -0,0 +1,18 @@ +package com.baeldung.map.hashing; + +public class MemberWithId extends Member { + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + MemberWithId that = (MemberWithId) o; + + return id.equals(that.id); + } + + @Override + public int hashCode() { + return id; + } +} diff --git a/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithIdAndName.java b/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithIdAndName.java new file mode 100644 index 0000000000..81ae48cf55 --- /dev/null +++ b/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithIdAndName.java @@ -0,0 +1,23 @@ +package com.baeldung.map.hashing; + +import java.util.Objects; + +public class MemberWithIdAndName extends Member { + public static final int PRIME = 31; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MemberWithObjects that = (MemberWithObjects) o; + return Objects.equals(id, that.id) && + Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + int result = id.hashCode(); + result = PRIME * result + (name == null ? 0 : name.hashCode()); + return result; + } +} diff --git a/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithObjects.java b/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithObjects.java new file mode 100644 index 0000000000..b641035e4f --- /dev/null +++ b/java-collections-maps-3/src/main/java/com/baeldung/map/hashing/MemberWithObjects.java @@ -0,0 +1,19 @@ +package com.baeldung.map.hashing; + +import java.util.Objects; + +public class MemberWithObjects extends Member { + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + MemberWithObjects that = (MemberWithObjects) o; + return Objects.equals(id, that.id) && + Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } +} diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/bytearrays/ByteArrayKeyUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/bytearrays/ByteArrayKeyUnitTest.java new file mode 100644 index 0000000000..8f5b89e11e --- /dev/null +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/bytearrays/ByteArrayKeyUnitTest.java @@ -0,0 +1,104 @@ +package com.baeldung.map.bytearrays; + +import com.google.common.collect.ImmutableList; +import org.junit.jupiter.api.Test; + +import java.util.Base64; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThat; + +class ByteArrayKeyUnitTest { + @Test + void givenPrimitiveByteArrayKey_whenRetrievingFromMap_shouldRetrieveDifferentObjects() { + // given + byte[] key1 = {1, 2, 3}; + byte[] key2 = {1, 2, 3}; + String value1 = "value1"; + String value2 = "value2"; + Map map = new HashMap<>(); + map.put(key1, value1); + map.put(key2, value2); + + // when + String retrievedValue1 = map.get(key1); + String retrievedValue2 = map.get(key2); + String retrievedValue3 = map.get(new byte[]{1, 2, 3}); + + // then + assertThat(retrievedValue1).isEqualTo(value1); + assertThat(retrievedValue2).isEqualTo(value2); + assertThat(retrievedValue3).isNull(); + } + + @Test + void givenEncodedStringKey_whenRetrievingFromMap_shouldRetrieveLastPutObject() { + // given + String key1 = Base64.getEncoder().encodeToString(new byte[]{1, 2, 3}); + String key2 = Base64.getEncoder().encodeToString(new byte[]{1, 2, 3}); + String value1 = "value1"; + String value2 = "value2"; + Map map = new HashMap<>(); + map.put(key1, value1); + map.put(key2, value2); + + // when + String retrievedValue1 = map.get(key1); + String retrievedValue2 = map.get(key2); + + // then + assertThat(key1).isEqualTo(key2); + assertThat(retrievedValue1).isEqualTo(value2); + assertThat(retrievedValue2).isEqualTo(value2); + assertThat(retrievedValue1).isEqualTo(retrievedValue2); + } + + @Test + void givenByteListKey_whenRetrievingFromMap_shouldRetrieveLastPutObject() { + // given + List key1 = ImmutableList.of((byte)1, (byte)2, (byte)3); + List key2 = ImmutableList.of((byte)1, (byte)2, (byte)3); + String value1 = "value1"; + String value2 = "value2"; + Map, String> map = new HashMap<>(); + map.put(key1, value1); + map.put(key2, value2); + + // when + String retrievedValue1 = map.get(key1); + String retrievedValue2 = map.get(key2); + + // then + assertThat(key1).isEqualTo(key2); + assertThat(retrievedValue1).isEqualTo(value2); + assertThat(retrievedValue2).isEqualTo(value2); + assertThat(retrievedValue1).isEqualTo(retrievedValue2); + } + + @Test + void givenCustomWrapperKey_whenRetrievingFromMap_shouldRetrieveLastPutObject() { + // given + BytesKey key1 = new BytesKey(new byte[]{1, 2, 3}); + BytesKey key2 = new BytesKey(new byte[]{1, 2, 3}); + String value1 = "value1"; + String value2 = "value2"; + Map map = new HashMap<>(); + map.put(key1, value1); + map.put(key2, value2); + + // when + String retrievedValue1 = map.get(key1); + String retrievedValue2 = map.get(key2); + String retrievedValue3 = map.get(new BytesKey(new byte[]{1, 2, 3})); + + // then + assertThat(key1).isEqualTo(key2); + assertThat(retrievedValue1).isEqualTo(value2); + assertThat(retrievedValue2).isEqualTo(value2); + assertThat(retrievedValue1).isEqualTo(retrievedValue2); + assertThat(retrievedValue3).isEqualTo(value2); + + } +} diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/entry/MapEntryUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/entry/MapEntryUnitTest.java new file mode 100644 index 0000000000..7340558023 --- /dev/null +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/entry/MapEntryUnitTest.java @@ -0,0 +1,33 @@ +package com.baeldung.map.entry; + +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +public class MapEntryUnitTest { + + @Test + public void givenSimpleEntryList_whenAddDuplicateKey_thenDoesNotOverwriteExistingKey() { + List> orderedTuples = new ArrayList<>(); + orderedTuples.add(new AbstractMap.SimpleEntry<>("9780134685991", new Book("Effective Java 3d Edition", "Joshua Bloch"))); + orderedTuples.add(new AbstractMap.SimpleEntry<>("9780132350884", new Book("Clean Code", "Robert C Martin"))); + orderedTuples.add(new AbstractMap.SimpleEntry<>("9780132350884", new Book("Clean Code", "Robert C Martin"))); + + assertEquals(3, orderedTuples.size()); + assertEquals("9780134685991", orderedTuples.get(0).getKey()); + assertEquals("9780132350884", orderedTuples.get(1).getKey()); + assertEquals("9780132350884", orderedTuples.get(2).getKey()); + } + + @Test + public void givenRegularMap_whenAddDuplicateKey_thenOverwritesExistingKey() { + Map entries = new HashMap<>(); + entries.put("9780134685991", new Book("Effective Java 3d Edition", "Joshua Bloch")); + entries.put("9780132350884", new Book("Clean Code", "Robert C Martin")); + entries.put("9780132350884", new Book("Clean Code", "Robert C Martin")); + + assertEquals(2, entries.size()); + } +} diff --git a/java-collections-maps-3/src/test/java/com/baeldung/map/hashing/HashingUnitTest.java b/java-collections-maps-3/src/test/java/com/baeldung/map/hashing/HashingUnitTest.java new file mode 100644 index 0000000000..d28a3b50b5 --- /dev/null +++ b/java-collections-maps-3/src/test/java/com/baeldung/map/hashing/HashingUnitTest.java @@ -0,0 +1,76 @@ +package com.baeldung.map.hashing; + +import com.google.common.base.Stopwatch; +import org.junit.jupiter.api.Test; + +import java.time.Duration; +import java.util.HashMap; +import java.util.SplittableRandom; +import java.util.function.Supplier; + +public class HashingUnitTest { + + public static final int SAMPLES = 1000000; + private SplittableRandom random = new SplittableRandom(); + + private String[] names = {"John", "Adam", "Suzie"}; + + @Test + void givenPrimitiveByteArrayKey_whenRetrievingFromMap_shouldRetrieveDifferentObjects() { + // bad hashing example is prohibitively slow for bigger samples +// Duration[] badHashing = testDuration(MemberWithBadHashing::new); + Duration[] withId = testDuration(MemberWithId::new); + Duration[] withObjects = testDuration(MemberWithObjects::new); + Duration[] withIdAndName = testDuration(MemberWithIdAndName::new); + +// System.out.println("Inserting with bad hashing:"); +// System.out.println(badHashing[0]); +// System.out.println("Getting with bad hashing:"); +// System.out.println(badHashing[1]); + + System.out.println("Inserting with id hashing:"); + System.out.println(withId[0]); + System.out.println("Getting with id hashing:"); + System.out.println(withId[1]); + + System.out.println("Inserting with id and name hashing:"); + System.out.println(withIdAndName[0]); + System.out.println("Getting with id and name hashing:"); + System.out.println(withIdAndName[1]); + + System.out.println("Inserting with Objects hashing:"); + System.out.println(withObjects[0]); + System.out.println("Getting with Objects hashing:"); + System.out.println(withObjects[1]); + } + + private String randomName() { + return names[random.nextInt(2)]; + } + + private Duration[] testDuration(Supplier factory) { + HashMap map = new HashMap<>(); + Stopwatch stopwatch = Stopwatch.createUnstarted(); + + stopwatch.start(); + for(int i = 0; i < SAMPLES; i++) { + T member = factory.get(); + member.id = i; + member.name = randomName(); + map.put(member, member.name); + } + stopwatch.stop(); + Duration elapsedInserting = stopwatch.elapsed(); + stopwatch.reset(); + + stopwatch.start(); + for (T key : map.keySet()) { + map.get(key); + } + stopwatch.stop(); + Duration elapsedGetting = stopwatch.elapsed(); + stopwatch.reset(); + + return new Duration[]{elapsedInserting, elapsedGetting}; + } +} diff --git a/java-native/README.md b/java-native/README.md new file mode 100644 index 0000000000..4f85342a38 --- /dev/null +++ b/java-native/README.md @@ -0,0 +1,9 @@ +## JNI + +This module contains articles about the Java Native Interface (JNI). + +### Relevant Articles: + +- [Guide to JNI (Java Native Interface)](https://www.baeldung.com/jni) +- [Using JNA to Access Native Dynamic Libraries](https://www.baeldung.com/java-jna-dynamic-libraries) +- [Check if a Java Program Is Running in 64-Bit or 32-Bit JVM](https://www.baeldung.com/java-detect-jvm-64-or-32-bit) diff --git a/java-native/pom.xml b/java-native/pom.xml new file mode 100644 index 0000000000..29fc13b8d8 --- /dev/null +++ b/java-native/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + java-native + java-native + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + 5.6.0 + + + + + net.java.dev.jna + jna-platform + ${jna.version} + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + false + + + + + \ No newline at end of file diff --git a/jni/src/main/cpp/com_baeldung_jni_ExampleObjectsJNI.cpp b/java-native/src/main/cpp/com_baeldung_jni_ExampleObjectsJNI.cpp similarity index 100% rename from jni/src/main/cpp/com_baeldung_jni_ExampleObjectsJNI.cpp rename to java-native/src/main/cpp/com_baeldung_jni_ExampleObjectsJNI.cpp diff --git a/jni/src/main/cpp/com_baeldung_jni_ExampleObjectsJNI.h b/java-native/src/main/cpp/com_baeldung_jni_ExampleObjectsJNI.h similarity index 100% rename from jni/src/main/cpp/com_baeldung_jni_ExampleObjectsJNI.h rename to java-native/src/main/cpp/com_baeldung_jni_ExampleObjectsJNI.h diff --git a/jni/src/main/cpp/com_baeldung_jni_ExampleParametersJNI.cpp b/java-native/src/main/cpp/com_baeldung_jni_ExampleParametersJNI.cpp similarity index 100% rename from jni/src/main/cpp/com_baeldung_jni_ExampleParametersJNI.cpp rename to java-native/src/main/cpp/com_baeldung_jni_ExampleParametersJNI.cpp diff --git a/jni/src/main/cpp/com_baeldung_jni_ExampleParametersJNI.h b/java-native/src/main/cpp/com_baeldung_jni_ExampleParametersJNI.h similarity index 100% rename from jni/src/main/cpp/com_baeldung_jni_ExampleParametersJNI.h rename to java-native/src/main/cpp/com_baeldung_jni_ExampleParametersJNI.h diff --git a/jni/src/main/cpp/com_baeldung_jni_HelloWorldJNI.cpp b/java-native/src/main/cpp/com_baeldung_jni_HelloWorldJNI.cpp similarity index 100% rename from jni/src/main/cpp/com_baeldung_jni_HelloWorldJNI.cpp rename to java-native/src/main/cpp/com_baeldung_jni_HelloWorldJNI.cpp diff --git a/jni/src/main/cpp/com_baeldung_jni_HelloWorldJNI.h b/java-native/src/main/cpp/com_baeldung_jni_HelloWorldJNI.h similarity index 100% rename from jni/src/main/cpp/com_baeldung_jni_HelloWorldJNI.h rename to java-native/src/main/cpp/com_baeldung_jni_HelloWorldJNI.h diff --git a/jni/src/main/cpp/generateNativeLib.bat b/java-native/src/main/cpp/generateNativeLib.bat similarity index 100% rename from jni/src/main/cpp/generateNativeLib.bat rename to java-native/src/main/cpp/generateNativeLib.bat diff --git a/jni/src/main/cpp/generateNativeLib.sh b/java-native/src/main/cpp/generateNativeLib.sh old mode 100755 new mode 100644 similarity index 100% rename from jni/src/main/cpp/generateNativeLib.sh rename to java-native/src/main/cpp/generateNativeLib.sh diff --git a/jni/src/main/cpp/generateNativeLibMac.sh b/java-native/src/main/cpp/generateNativeLibMac.sh old mode 100755 new mode 100644 similarity index 100% rename from jni/src/main/cpp/generateNativeLibMac.sh rename to java-native/src/main/cpp/generateNativeLibMac.sh diff --git a/java-native/src/main/java/com/baeldung/jna/CMath.java b/java-native/src/main/java/com/baeldung/jna/CMath.java new file mode 100644 index 0000000000..3ab5bdf48b --- /dev/null +++ b/java-native/src/main/java/com/baeldung/jna/CMath.java @@ -0,0 +1,10 @@ +package com.baeldung.jna; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Platform; + +public interface CMath extends Library { + CMath INSTANCE = Native.load(Platform.isWindows() ? "msvcrt" : "c", CMath.class); + double cosh(double value); +} diff --git a/java-native/src/main/java/com/baeldung/jna/Main.java b/java-native/src/main/java/com/baeldung/jna/Main.java new file mode 100644 index 0000000000..a81c878cde --- /dev/null +++ b/java-native/src/main/java/com/baeldung/jna/Main.java @@ -0,0 +1,8 @@ +package com.baeldung.jna; + +public class Main { + + public static void main(String[] args) { + + } +} \ No newline at end of file diff --git a/java-native/src/main/java/com/baeldung/jna/NativeFS.java b/java-native/src/main/java/com/baeldung/jna/NativeFS.java new file mode 100644 index 0000000000..58f2bda035 --- /dev/null +++ b/java-native/src/main/java/com/baeldung/jna/NativeFS.java @@ -0,0 +1,46 @@ +package com.baeldung.jna; + +import java.util.Collections; +import java.util.Map; + +import com.sun.jna.FunctionMapper; +import com.sun.jna.LastErrorException; +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.NativeLong; +import com.sun.jna.Platform; +import com.sun.jna.Structure; +import com.sun.jna.Structure.FieldOrder; + +public interface NativeFS extends Library { + + FunctionMapper mapper = (library,method) -> { + if (Platform.isWindows()) { + return "_" + method.getName(); + } + else { + return "__x" + method.getName(); // On Linux, stat is actually _xstat + } + }; + + public NativeFS INSTANCE = Native.load(Platform.isWindows() ? "msvcrt" : "c", + NativeFS.class, + Collections.singletonMap(Library.OPTION_FUNCTION_MAPPER, mapper)); + + int stat(String path, Stat stat) throws LastErrorException; + + @FieldOrder({"st_dev","st_ino","st_mode","st_nlink","st_uid","st_gid","st_rdev","st_size","st_atime","st_mtime","st_ctime"}) + public class Stat extends Structure { + public int st_dev; + public int st_ino; + public short st_mode; + public short st_nlink; + public short st_uid; + public short st_gid; + public int st_rdev; + public NativeLong st_size; + public NativeLong st_atime; + public NativeLong st_mtime; + public NativeLong st_ctime; + } +} diff --git a/java-native/src/main/java/com/baeldung/jna/StdC.java b/java-native/src/main/java/com/baeldung/jna/StdC.java new file mode 100644 index 0000000000..1adbe684c4 --- /dev/null +++ b/java-native/src/main/java/com/baeldung/jna/StdC.java @@ -0,0 +1,17 @@ +package com.baeldung.jna; + +import com.sun.jna.LastErrorException; +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Platform; +import com.sun.jna.Pointer; + +public interface StdC extends Library { + StdC INSTANCE = Native.load(Platform.isWindows() ? "msvcrt" : "c", StdC.class ); + Pointer malloc(long n); + void free(Pointer p); + Pointer memset(Pointer p, int c, long n); + int open(String path, int flags) throws LastErrorException; + int close(int fd) throws LastErrorException; +} + diff --git a/jni/src/main/java/com/baeldung/jni/ExampleObjectsJNI.java b/java-native/src/main/java/com/baeldung/jni/ExampleObjectsJNI.java similarity index 100% rename from jni/src/main/java/com/baeldung/jni/ExampleObjectsJNI.java rename to java-native/src/main/java/com/baeldung/jni/ExampleObjectsJNI.java diff --git a/jni/src/main/java/com/baeldung/jni/ExampleParametersJNI.java b/java-native/src/main/java/com/baeldung/jni/ExampleParametersJNI.java similarity index 100% rename from jni/src/main/java/com/baeldung/jni/ExampleParametersJNI.java rename to java-native/src/main/java/com/baeldung/jni/ExampleParametersJNI.java diff --git a/jni/src/main/java/com/baeldung/jni/HelloWorldJNI.java b/java-native/src/main/java/com/baeldung/jni/HelloWorldJNI.java similarity index 100% rename from jni/src/main/java/com/baeldung/jni/HelloWorldJNI.java rename to java-native/src/main/java/com/baeldung/jni/HelloWorldJNI.java diff --git a/jni/src/main/java/com/baeldung/jni/UserData.java b/java-native/src/main/java/com/baeldung/jni/UserData.java similarity index 100% rename from jni/src/main/java/com/baeldung/jni/UserData.java rename to java-native/src/main/java/com/baeldung/jni/UserData.java diff --git a/java-native/src/main/java/com/baeldung/jvmbitversion/JVMBitVersion.java b/java-native/src/main/java/com/baeldung/jvmbitversion/JVMBitVersion.java new file mode 100644 index 0000000000..63684fec49 --- /dev/null +++ b/java-native/src/main/java/com/baeldung/jvmbitversion/JVMBitVersion.java @@ -0,0 +1,24 @@ +package com.baeldung.jvmbitversion; + +import com.sun.jna.Platform; + +public class JVMBitVersion { + + public String getUsingSystemClass() { + return System.getProperty("sun.arch.data.model") + "-bit"; + } + + public String getUsingNativeClass() { + if (com.sun.jna.Native.POINTER_SIZE == 8) { + return "64-bit"; + } else if (com.sun.jna.Native.POINTER_SIZE == 4) { + return "32-bit"; + } else + return "unknown"; + } + + public boolean getUsingPlatformClass() { + return (Platform.is64Bit()); + } + +} diff --git a/jni/src/main/resources/logback.xml b/java-native/src/main/resources/logback.xml similarity index 100% rename from jni/src/main/resources/logback.xml rename to java-native/src/main/resources/logback.xml diff --git a/java-native/src/test/java/com/baeldung/jna/CMathUnitTest.java b/java-native/src/test/java/com/baeldung/jna/CMathUnitTest.java new file mode 100644 index 0000000000..a9cc6ed1c4 --- /dev/null +++ b/java-native/src/test/java/com/baeldung/jna/CMathUnitTest.java @@ -0,0 +1,18 @@ +package com.baeldung.jna; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.Test; + +import com.sun.jna.Native; +import com.sun.jna.Platform; + +class CMathUnitTest { + @Test + void whenCallNative_thenSuccess() { + CMath lib = Native.load(Platform.isWindows() ? "msvcrt" : "c", CMath.class); + double result = lib.cosh(0); + assertEquals(1.0,result); + } + +} diff --git a/java-native/src/test/java/com/baeldung/jna/NativeFSUnitTest.java b/java-native/src/test/java/com/baeldung/jna/NativeFSUnitTest.java new file mode 100644 index 0000000000..d296f9e2ca --- /dev/null +++ b/java-native/src/test/java/com/baeldung/jna/NativeFSUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.jna; + +import static org.junit.Assert.fail; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; + +import org.junit.jupiter.api.Test; + +import com.baeldung.jna.NativeFS.Stat; +import com.sun.jna.LastErrorException; +import com.sun.jna.Platform; + +public class NativeFSUnitTest { + + + @Test + public void whenCallNative_thenSuccess() throws IOException { + NativeFS lib = NativeFS.INSTANCE; + + File f = Files.createTempFile("junit", ".bin").toFile(); + f.deleteOnExit(); + Stat stat = new Stat(); + try { + if (Platform.isWindows()) { + int rc = lib.stat(f.getAbsolutePath(), stat); + assertEquals(0, rc); + assertEquals(0,stat.st_size.longValue()); + } + } + catch(LastErrorException error) { + fail("stat failed: error code=" + error.getErrorCode()); + } + + } +} diff --git a/java-native/src/test/java/com/baeldung/jna/StdCUnitTest.java b/java-native/src/test/java/com/baeldung/jna/StdCUnitTest.java new file mode 100644 index 0000000000..c536fd63d5 --- /dev/null +++ b/java-native/src/test/java/com/baeldung/jna/StdCUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.jna; + +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.BeforeClass; +import org.junit.jupiter.api.Test; + +import com.sun.jna.Native; +import com.sun.jna.Platform; +import com.sun.jna.Pointer; + +class StdCUnitTest { + + @BeforeClass + public static void setupProtectedMode() { + Native.setProtected(true); + } + + @Test + public void whenMalloc_thenSuccess() { + StdC lib = StdC.INSTANCE; + Pointer p = lib.malloc(1024); + p.setMemory(0l, 1024l, (byte) 0); + lib.free(p); + } + + @Test + public void whenAccessViolation_thenShouldThrowError() { + // Running this test on Linux requires additional setup using libjsig.so + // Details here: http://java-native-access.github.io/jna/5.6.0/javadoc/overview-summary.html#crash-protection + // IMPORTANT NOTICE: Code for illustration purposes only. DON'T DO THIS IN YOUR OWN CODE + if ( Platform.isWindows()) { + Error e = null; + Pointer p = new Pointer(0l); + + try { + p.setMemory(0, 100*1024, (byte) 0); + } + catch(Error err) { + e = err; + } + + assertNotNull(e, "Should throw Error"); + } + } + +} diff --git a/jni/src/test/java/com/baeldung/jni/JNINativeManualTest.java b/java-native/src/test/java/com/baeldung/jni/JNINativeManualTest.java similarity index 100% rename from jni/src/test/java/com/baeldung/jni/JNINativeManualTest.java rename to java-native/src/test/java/com/baeldung/jni/JNINativeManualTest.java diff --git a/java-native/src/test/java/com/baeldung/jvmbitversion/JVMBitVersionUnitTest.java b/java-native/src/test/java/com/baeldung/jvmbitversion/JVMBitVersionUnitTest.java new file mode 100644 index 0000000000..35357dec77 --- /dev/null +++ b/java-native/src/test/java/com/baeldung/jvmbitversion/JVMBitVersionUnitTest.java @@ -0,0 +1,45 @@ +package com.baeldung.jvmbitversion; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +import com.sun.jna.Platform; + +public class JVMBitVersionUnitTest { + + private JVMBitVersion jvmVersion; + + @Before + public void setup() { + jvmVersion = new JVMBitVersion(); + } + + @Test + public void whenUsingSystemClass_thenOutputIsAsExpected() { + if ("64".equals(System.getProperty("sun.arch.data.model"))) { + assertEquals("64-bit", jvmVersion.getUsingSystemClass()); + } else if ("32".equals(System.getProperty("sun.arch.data.model"))) { + assertEquals("32-bit", jvmVersion.getUsingSystemClass()); + } + } + + @Test + public void whenUsingNativeClass_thenResultIsAsExpected() { + if (com.sun.jna.Native.POINTER_SIZE == 8) { + assertEquals("64-bit", jvmVersion.getUsingNativeClass()); + } else if (com.sun.jna.Native.POINTER_SIZE == 4) { + assertEquals("32-bit", jvmVersion.getUsingNativeClass()); + } + } + + @Test + public void whenUsingPlatformClass_thenResultIsAsExpected() { + if (Platform.is64Bit() == Boolean.TRUE) { + assertEquals(Boolean.TRUE, jvmVersion.getUsingPlatformClass()); + } else if (com.sun.jna.Native.POINTER_SIZE == 4) { + assertEquals(Boolean.FALSE, jvmVersion.getUsingPlatformClass()); + } + } +} diff --git a/java-numbers-3/pom.xml b/java-numbers-3/pom.xml index 495618885a..62225a898f 100644 --- a/java-numbers-3/pom.xml +++ b/java-numbers-3/pom.xml @@ -27,7 +27,7 @@ org.apache.commons commons-lang3 - ${commons.version} + ${commons-lang3.version} test @@ -51,7 +51,6 @@ 2.6.0 0.10.2 - 3.9 3.6.1 diff --git a/java-numbers-4/README.md b/java-numbers-4/README.md index 344d348733..cdd53692e0 100644 --- a/java-numbers-4/README.md +++ b/java-numbers-4/README.md @@ -1,3 +1,5 @@ ### Relevant Articles: - [Probability in Java](https://www.baeldung.com/java-probability) +- [Understanding the & 0xff Value in Java](https://www.baeldung.com/java-and-0xff) +- [Determine if an Integer’s Square Root Is an Integer in Java](https://www.baeldung.com/java-find-if-square-root-is-integer) diff --git a/java-numbers-4/pom.xml b/java-numbers-4/pom.xml index e1722fb039..f4b0e23bd7 100644 --- a/java-numbers-4/pom.xml +++ b/java-numbers-4/pom.xml @@ -22,7 +22,7 @@ org.apache.commons commons-lang3 - ${commons.version} + ${commons-lang3.version} test @@ -45,7 +45,6 @@ 0.10.2 - 3.9 3.6.1 diff --git a/java-numbers-4/src/main/java/com/baeldung/number_0xff/Number0xff.java b/java-numbers-4/src/main/java/com/baeldung/number_0xff/Number0xff.java new file mode 100644 index 0000000000..1708afb5a2 --- /dev/null +++ b/java-numbers-4/src/main/java/com/baeldung/number_0xff/Number0xff.java @@ -0,0 +1,20 @@ +package com.baeldung.number_0xff; + +public class Number0xff { + + public static int getRedColor(int rgba) { + return rgba >> 24 & 0xff; + } + + public static int getGreenColor(int rgba) { + return rgba >> 16 & 0xff; + } + + public static int getBlueColor(int rgba) { + return rgba >> 8 & 0xff; + } + + public static int getAlfa(int rgba) { + return rgba & 0xff; + } +} diff --git a/java-numbers-4/src/main/java/com/baeldung/perfectsquare/PerfectSquareUtil.java b/java-numbers-4/src/main/java/com/baeldung/perfectsquare/PerfectSquareUtil.java new file mode 100644 index 0000000000..61093ba816 --- /dev/null +++ b/java-numbers-4/src/main/java/com/baeldung/perfectsquare/PerfectSquareUtil.java @@ -0,0 +1,49 @@ +package com.baeldung.perfectsquare; + +public class PerfectSquareUtil { + + public static boolean isPerfectSquareByUsingSqrt(long n) { + if (n <= 0) + return false; + double perfectSquare = Math.sqrt(n); + long tst = (long)(perfectSquare + 0.5); + return tst*tst == n; + } + + public static boolean isPerfectSquareByUsingBinarySearch(long low, long high, long number) { + long check = (low + high) / 2L; + if (high < low) + return false; + if (number == check * check) { + return true; + } else if (number < check * check) { + high = check - 1L; + return isPerfectSquareByUsingBinarySearch(low, high, number); + } else { + low = check + 1L; + return isPerfectSquareByUsingBinarySearch(low, high, number); + } + } + + public static boolean isPerfectSquareByUsingNewtonMethod(long n) { + long x1 = n; + long x2 = 1L; + while (x1 > x2) { + x1 = (x1 + x2) / 2L; + x2 = n / x1; + } + return x1 == x2 && n % x1 == 0L; + } + + public static boolean isPerfectSquareWithOptimization(long n) { + if (n < 0) + return false; + switch ((int) (n & 0xF)) { + case 0: case 1: case 4: case 9: + long tst = (long) Math.sqrt(n); + return tst * tst == n; + default: + return false; + } + } +} diff --git a/java-numbers-4/src/test/java/com/baeldung/number_0xff/Number0xffUnitTest.java b/java-numbers-4/src/test/java/com/baeldung/number_0xff/Number0xffUnitTest.java new file mode 100644 index 0000000000..b0feaf8628 --- /dev/null +++ b/java-numbers-4/src/test/java/com/baeldung/number_0xff/Number0xffUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung.number_0xff; + +import org.junit.Test; +import static org.junit.Assert.assertEquals; + +public class Number0xffUnitTest { + + @Test + public void test0xFFAssignedToInteger() { + int x = 0xff; + int expectedValue = 255; + assertEquals(expectedValue, x); + } + + @Test + public void test0xFFAssignedToByte() { + byte y = (byte) 0xff; + int expectedValue = -1; + assertEquals(expectedValue, y); + } + + @Test + public void givenColor_whenGetRedColor_thenExtractRedColor() { + int rgba = 272214023; + int expectedValue = 16; + assertEquals(expectedValue, Number0xff.getRedColor(rgba)); + } + + @Test + public void givenColor_whenGetGreenColor_thenExtractGreenColor() { + int rgba = 272214023; + int expectedValue = 57; + assertEquals(expectedValue, Number0xff.getGreenColor(rgba)); + } + + @Test + public void givenColor_whenGetBlueColor_thenExtractBlueColor() { + int rgba = 272214023; + int expectedValue = 168; + assertEquals(expectedValue, Number0xff.getBlueColor(rgba)); + } + + @Test + public void givenColor_whenGetAlfa_thenExtractAlfa() { + int rgba = 272214023; + int expectedValue = 7; + assertEquals(expectedValue, Number0xff.getAlfa(rgba)); + } +} diff --git a/java-numbers-4/src/test/java/com/baeldung/perfectsquare/PerfectSquareUnitTest.java b/java-numbers-4/src/test/java/com/baeldung/perfectsquare/PerfectSquareUnitTest.java new file mode 100644 index 0000000000..83fce31047 --- /dev/null +++ b/java-numbers-4/src/test/java/com/baeldung/perfectsquare/PerfectSquareUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.perfectsquare; + +import org.junit.Test; +import static org.junit.Assert.assertEquals; + +public class PerfectSquareUnitTest { + + @Test + public void testIsNumberPerfectSquare() { + long n = 18676209273604L; //‬ 18676209273604 = 43621598 * 43621598 + boolean expectedValue = true; + assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareByUsingSqrt(n)); + assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareByUsingBinarySearch(1, Integer.MAX_VALUE, n)); + assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareByUsingNewtonMethod(n)); + assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareWithOptimization(n)); + + n = 549790047707L; // prime number + expectedValue = false; + assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareByUsingSqrt(n)); + assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareByUsingBinarySearch(1, Integer.MAX_VALUE, n)); + assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareByUsingNewtonMethod(n)); + assertEquals(expectedValue, PerfectSquareUtil.isPerfectSquareWithOptimization(n)); + } + + +} diff --git a/java-numbers/README.md b/java-numbers/README.md index f4b76c3c98..3007e1746c 100644 --- a/java-numbers/README.md +++ b/java-numbers/README.md @@ -3,12 +3,12 @@ This module contains articles about numbers in Java. ### Relevant Articles: -- [Number of Digits in an Integer in Java](http://www.baeldung.com/java-number-of-digits-in-int) -- [How to Round a Number to N Decimal Places in Java](http://www.baeldung.com/java-round-decimal-number) -- [BigDecimal and BigInteger in Java](http://www.baeldung.com/java-bigdecimal-biginteger) -- [Find All Pairs of Numbers in an Array That Add Up to a Given Sum](http://www.baeldung.com/java-algorithm-number-pairs-sum) -- [Java – Random Long, Float, Integer and Double](http://www.baeldung.com/java-generate-random-long-float-integer-double) -- [A Practical Guide to DecimalFormat](http://www.baeldung.com/java-decimalformat) +- [Number of Digits in an Integer in Java](https://www.baeldung.com/java-number-of-digits-in-int) +- [How to Round a Number to N Decimal Places in Java](https://www.baeldung.com/java-round-decimal-number) +- [BigDecimal and BigInteger in Java](https://www.baeldung.com/java-bigdecimal-biginteger) +- [Find All Pairs of Numbers in an Array That Add Up to a Given Sum in Java](https://www.baeldung.com/java-algorithm-number-pairs-sum) +- [Java – Random Long, Float, Integer and Double](https://www.baeldung.com/java-generate-random-long-float-integer-double) +- [A Practical Guide to DecimalFormat](https://www.baeldung.com/java-decimalformat) - [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) diff --git a/javafx/src/main/java/com/baeldung/view/SearchController.java b/javafx/src/main/java/com/baeldung/view/SearchController.java index 430580f8b5..3bde84958c 100644 --- a/javafx/src/main/java/com/baeldung/view/SearchController.java +++ b/javafx/src/main/java/com/baeldung/view/SearchController.java @@ -10,6 +10,7 @@ import javafx.scene.Node; import javafx.scene.control.*; import javafx.scene.input.KeyCode; import javafx.scene.layout.VBox; +import javafx.scene.control.cell.PropertyValueFactory; import java.util.stream.Collectors; @@ -22,11 +23,14 @@ public class SearchController { @FXML private Button searchButton; @FXML - private Pagination pagination; - @FXML private Label searchLabel; - + @FXML + private TableView tableView; + @FXML + private VBox dataContainer; + private ObservableList masterData = FXCollections.observableArrayList(); + private ObservableList results = FXCollections.observableList(masterData); public SearchController() { masterData.add(new Person(5, "John", true)); @@ -40,7 +44,7 @@ public class SearchController { // search panel searchButton.setText("Search"); searchButton.setOnAction(event -> loadData()); - searchButton.setStyle("-fx-background-color: #457ecd; -fx-text-fill: #ffffff;"); + searchButton.setStyle("-fx-background-color: slateblue; -fx-text-fill: white;"); searchField.setOnKeyPressed(event -> { if (event.getCode().equals(KeyCode.ENTER)) { @@ -52,22 +56,23 @@ public class SearchController { searchLabel.setText(newValue); }); - pagination.setPageFactory(SearchController.this::createPage); + initTable(); + } - private Node createPage(Integer pageIndex) { + private void initTable() { + tableView = new TableView<>(FXCollections.observableList(masterData)); + tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); - VBox dataContainer = new VBox(); - - TableView tableView = new TableView<>(masterData); TableColumn id = new TableColumn("ID"); + id.setCellValueFactory(new PropertyValueFactory("id")); TableColumn name = new TableColumn("NAME"); + name.setCellValueFactory(new PropertyValueFactory("name")); TableColumn employed = new TableColumn("EMPLOYED"); - + employed.setCellValueFactory(new PropertyValueFactory("isEmployed")); tableView.getColumns().addAll(id, name, employed); + dataContainer.getChildren().add(tableView); - - return dataContainer; } private void loadData() { @@ -86,11 +91,10 @@ public class SearchController { }; task.setOnSucceeded(event -> { - masterData = task.getValue(); - pagination.setVisible(true); - pagination.setPageCount(masterData.size() / PAGE_ITEMS_COUNT); + results = task.getValue(); + tableView.setItems(FXCollections.observableList(results)); }); - + Thread th = new Thread(task); th.setDaemon(true); th.start(); diff --git a/javafx/src/main/resources/SearchController.fxml b/javafx/src/main/resources/SearchController.fxml index 5e83024d03..b1e11a8864 100644 --- a/javafx/src/main/resources/SearchController.fxml +++ b/javafx/src/main/resources/SearchController.fxml @@ -20,14 +20,13 @@ diff --git a/javax-servlets/src/main/java/com/baeldung/servlets/UpdateServlet.java b/javax-servlets/src/main/java/com/baeldung/servlets/UpdateServlet.java index d0404d0cd4..35c9819a6f 100644 --- a/javax-servlets/src/main/java/com/baeldung/servlets/UpdateServlet.java +++ b/javax-servlets/src/main/java/com/baeldung/servlets/UpdateServlet.java @@ -1,6 +1,5 @@ package com.baeldung.servlets; - import java.io.IOException; import javax.servlet.RequestDispatcher; @@ -18,10 +17,14 @@ public class UpdateServlet extends HttpServlet { HttpSession session = request.getSession(false); - session.setAttribute("userName", request.getParameter("userName")); - session.setAttribute("age", request.getParameter("age")); + if (session != null) { + + session.setAttribute("userName", request.getParameter("userName")); + session.setAttribute("age", request.getParameter("age")); + + request.setAttribute("sessionData", session); + } - request.setAttribute("sessionData", session); RequestDispatcher requestDispather = request.getRequestDispatcher("update.jsp"); requestDispather.forward(request, response); diff --git a/jee-kotlin/README.md b/jee-kotlin/README.md deleted file mode 100644 index e8975a7f62..0000000000 --- a/jee-kotlin/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## JEE in Kotlin - -This module contains articles about Java EE with Kotlin. - -### Relevant Articles: -- [Jakarta EE Application with Kotlin](https://www.baeldung.com/java-ee-kotlin-app) diff --git a/jee-kotlin/pom.xml b/jee-kotlin/pom.xml deleted file mode 100644 index 45d5d8ece1..0000000000 --- a/jee-kotlin/pom.xml +++ /dev/null @@ -1,288 +0,0 @@ - - - 4.0.0 - jee-kotlin - jee-kotlin - war - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - - - - org.jboss.arquillian - arquillian-bom - ${arquillian_core.version} - import - pom - - - org.jboss.arquillian.extension - arquillian-drone-bom - ${arquillian-drone-bom.version} - pom - import - - - - - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - - - org.jetbrains.kotlin - kotlin-test-junit - ${kotlin.version} - test - - - junit - junit - ${junit.version} - test - - - javax - javaee-api - ${javaee-api.version} - jar - provided - - - com.fasterxml.jackson.core - jackson-annotations - ${jackson.version} - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - test - - - org.jboss.arquillian.junit - arquillian-junit-container - ${arquillian_core.version} - test - - - org.jboss.shrinkwrap.resolver - shrinkwrap-resolver-depchain - ${shrinkwrap.version} - pom - test - - - org.jboss.arquillian.extension - arquillian-rest-client-impl-jersey - ${arquillian-rest-client.version} - - - org.jetbrains.kotlin - kotlin-test - ${kotlin.version} - test - - - - - src/main/kotlin - src/test/kotlin - - - - org.jetbrains.kotlin - kotlin-maven-plugin - ${kotlin.version} - - - compile - compile - - compile - - - - test-compile - test-compile - - test-compile - - - - - 1.8 - - - - - org.apache.maven.plugins - maven-war-plugin - ${maven-war-plugin.version} - - webapp - kotlin - - - - org.apache.maven.plugins - maven-compiler-plugin - - - default-compile - none - - - default-testCompile - none - - - compile - compile - - compile - - - - testCompile - test-compile - - testCompile - - - - - - - - - - wildfly-managed-arquillian - - true - - - - org.wildfly - wildfly-arquillian-container-embedded - ${wildfly.version} - - - org.wildfly - wildfly-embedded - ${wildfly.version} - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - ${maven-dependency-plugin.version} - - - unpack - process-test-classes - - unpack - - - - - org.wildfly - wildfly-dist - ${wildfly.version} - zip - false - target - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - - - always - - org.jboss.logmanager.LogManager - ${project.basedir}/target/wildfly-${wildfly.version} - 8756 - ${project.basedir}/target/wildfly-${wildfly.version}/modules - - false - - - - - - - wildfly-remote-arquillian-disabled - - - org.jboss.resteasy - resteasy-client - ${resteasy.version} - test - - - org.jboss.resteasy - resteasy-jaxb-provider - ${resteasy.version} - test - - - org.jboss.resteasy - resteasy-json-p-provider - ${resteasy.version} - test - - - org.wildfly.arquillian - wildfly-arquillian-container-remote - ${wildfly.arquillian.version} - test - - - - - - - 2.2.0.Final - UTF-8 - false - 8.0 - - 1.3.41 - official - true - - 8.2.1.Final - 2.21.0 - 3.1.1 - - 1.4.1.Final - 2.0.1.Final - 1.0.0.Alpha4 - - 1.1.7 - - 3.8.0.Final - 3.1.3 - - - diff --git a/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/entity/Student.kt b/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/entity/Student.kt deleted file mode 100644 index 07f54a39d1..0000000000 --- a/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/entity/Student.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.jeekotlin.entity - -import com.fasterxml.jackson.annotation.JsonProperty -import javax.persistence.* - -@Entity -data class Student constructor ( - - @SequenceGenerator(name = "student_id_seq", sequenceName = "student_id_seq", allocationSize = 1) - @GeneratedValue(generator = "student_id_seq", strategy = GenerationType.SEQUENCE) - @Id - var id: Long?, - - var firstName: String, - - var lastName: String - -) { - constructor() : this(null, "", "") - - constructor(firstName: String, lastName: String) : this(null, firstName, lastName) -} diff --git a/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/rest/ApplicationConfig.kt b/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/rest/ApplicationConfig.kt deleted file mode 100644 index 12511ed320..0000000000 --- a/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/rest/ApplicationConfig.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.baeldung.jeekotlin.rest - -import javax.ws.rs.ApplicationPath -import javax.ws.rs.core.Application - -@ApplicationPath("/") -class ApplicationConfig : Application() { - override fun getClasses() = setOf(StudentResource::class.java) -} diff --git a/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/rest/StudentResource.kt b/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/rest/StudentResource.kt deleted file mode 100644 index 91fa3ff62b..0000000000 --- a/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/rest/StudentResource.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.jeekotlin.rest - -import com.baeldung.jeekotlin.entity.Student -import com.baeldung.jeekotlin.service.StudentService -import javax.inject.Inject -import javax.ws.rs.* -import javax.ws.rs.core.MediaType -import javax.ws.rs.core.Response - -@Path("/student") -open class StudentResource { - - @Inject - private lateinit var service: StudentService - - @POST - open fun create(student: Student): Response { - service.create(student) - return Response.ok().build() - } - - @GET - @Path("/{id}") - open fun read(@PathParam("id") id: Long): Response { - val student = service.read(id) - return Response.ok(student, MediaType.APPLICATION_JSON_TYPE).build() - } - - @PUT - open fun update(student: Student): Response { - service.update(student) - return Response.ok(student, MediaType.APPLICATION_JSON_TYPE).build() - } - - @DELETE - @Path("/{id}") - open fun delete(@PathParam("id") id: Long): Response { - service.delete(id) - return Response.noContent().build() - } - -} \ No newline at end of file diff --git a/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/service/StudentService.kt b/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/service/StudentService.kt deleted file mode 100644 index 3977a45e96..0000000000 --- a/jee-kotlin/src/main/kotlin/com/baeldung/jeekotlin/service/StudentService.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.jeekotlin.service - -import com.baeldung.jeekotlin.entity.Student -import javax.ejb.Stateless -import javax.persistence.EntityManager -import javax.persistence.PersistenceContext - -@Stateless -open class StudentService { - - @PersistenceContext - private lateinit var entityManager: EntityManager - - open fun create(student: Student) = entityManager.persist(student) - - open fun read(id: Long): Student? = entityManager.find(Student::class.java, id) - - open fun update(student: Student) = entityManager.merge(student) - - open fun delete(id: Long) = entityManager.remove(read(id)) -} \ No newline at end of file diff --git a/jee-kotlin/src/main/resources/META-INF/persistence.xml b/jee-kotlin/src/main/resources/META-INF/persistence.xml deleted file mode 100644 index 0093792810..0000000000 --- a/jee-kotlin/src/main/resources/META-INF/persistence.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - org.hibernate.jpa.HibernatePersistenceProvider - - java:jboss/datasources/ExampleDS - - com.baeldung.jeekotlin.entity.Student - - - - - - - - diff --git a/jee-kotlin/src/main/webapp/WEB-INF/beans.xml b/jee-kotlin/src/main/webapp/WEB-INF/beans.xml deleted file mode 100644 index ae0f4bf2ee..0000000000 --- a/jee-kotlin/src/main/webapp/WEB-INF/beans.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - \ No newline at end of file diff --git a/jee-kotlin/src/test/kotlin/com/baeldung/jeekotlin/StudentResourceIntegrationTest.java b/jee-kotlin/src/test/kotlin/com/baeldung/jeekotlin/StudentResourceIntegrationTest.java deleted file mode 100644 index d48a3a96da..0000000000 --- a/jee-kotlin/src/test/kotlin/com/baeldung/jeekotlin/StudentResourceIntegrationTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.baeldung.jeekotlin; - -import com.baeldung.jeekotlin.entity.Student; -import org.jboss.arquillian.container.test.api.Deployment; -import org.jboss.arquillian.container.test.api.RunAsClient; -import org.jboss.arquillian.test.api.ArquillianResource; -import org.jboss.arquillian.junit.Arquillian; -import org.jboss.shrinkwrap.api.Filters; -import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.asset.EmptyAsset; -import org.jboss.shrinkwrap.api.spec.JavaArchive; -import org.jboss.shrinkwrap.api.spec.WebArchive; -import org.jboss.shrinkwrap.resolver.api.maven.Maven; -import org.junit.Test; -import org.junit.runner.RunWith; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -import javax.ws.rs.client.Entity; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.WebTarget; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import java.net.URISyntaxException; -import java.net.URL; - -import static org.junit.Assert.assertEquals; - -@RunWith(Arquillian.class) -public class StudentResourceIntegrationTest { - - @Deployment - public static WebArchive createDeployment() { - JavaArchive[] kotlinRuntime = Maven.configureResolver() - .workOffline() - .withMavenCentralRepo(true) - .withClassPathResolution(true) - .loadPomFromFile("pom.xml") - .resolve("org.jetbrains.kotlin:kotlin-stdlib:1.3.41") - .withTransitivity() - .as(JavaArchive.class); - - return ShrinkWrap.create(WebArchive.class, "kotlin.war") - .addPackages(true, Filters.exclude(".*Test*"), - "com.baeldung.jeekotlin" - ) - .addAsLibraries(kotlinRuntime) - .addAsResource("META-INF/persistence.xml") - .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"); - } - - @Test - @RunAsClient - public void when_post__then_return_ok(@ArquillianResource URL url) throws URISyntaxException, JsonProcessingException { - String student = new ObjectMapper().writeValueAsString(new Student("firstName", "lastName")); - WebTarget webTarget = ClientBuilder.newClient().target(url.toURI()); - - Response response = webTarget - .path("/student") - .request(MediaType.APPLICATION_JSON) - .post(Entity.json(student)); - - assertEquals(200, response.getStatus()); - } - - @Test - @RunAsClient - public void when_get__then_return_ok(@ArquillianResource URL url) throws URISyntaxException, JsonProcessingException { - WebTarget webTarget = ClientBuilder.newClient().target(url.toURI()); - - Response response = webTarget - .path("/student/1") - .request(MediaType.APPLICATION_JSON) - .get(); - - assertEquals(200, response.getStatus()); - } - - @Test - @RunAsClient - public void when_put__then_return_ok(@ArquillianResource URL url) throws URISyntaxException, JsonProcessingException { - Student student = new Student("firstName", "lastName"); - student.setId(1L); - String studentJson = new ObjectMapper().writeValueAsString(student); - WebTarget webTarget = ClientBuilder.newClient().target(url.toURI()); - - Response response = webTarget - .path("/student") - .request(MediaType.APPLICATION_JSON) - .put(Entity.json(studentJson)); - - assertEquals(200, response.getStatus()); - } - - @Test - @RunAsClient - public void when_delete__then_return_ok(@ArquillianResource URL url) throws URISyntaxException, JsonProcessingException { - WebTarget webTarget = ClientBuilder.newClient().target(url.toURI()); - - Response response = webTarget - .path("/student/1") - .request() - .delete(); - - assertEquals(204, response.getStatus()); - } - -} \ No newline at end of file diff --git a/jee-kotlin/src/test/resources/arquillian.xml b/jee-kotlin/src/test/resources/arquillian.xml deleted file mode 100644 index 5e6d7c54e8..0000000000 --- a/jee-kotlin/src/test/resources/arquillian.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - target/wildfly-8.2.1.Final - standalone.xml - true - 9990 - - - - - - 127.0.0.1 - 9990 - admin - pass - true - - - - \ No newline at end of file diff --git a/jhipster/jhipster-microservice/car-app/pom.xml b/jhipster/jhipster-microservice/car-app/pom.xml index c53ea8358e..477192438f 100644 --- a/jhipster/jhipster-microservice/car-app/pom.xml +++ b/jhipster/jhipster-microservice/car-app/pom.xml @@ -21,8 +21,6 @@ -Djava.security.egd=file:/dev/./urandom -Xmx256m 3.6.2 2.0.0 - 2.5 - 3.5 0.4.13 1.2 5.2.8.Final @@ -267,7 +265,7 @@ org.apache.commons commons-lang3 - ${commons-lang.version} + ${commons-lang3.version} org.assertj diff --git a/jhipster/jhipster-microservice/dealer-app/pom.xml b/jhipster/jhipster-microservice/dealer-app/pom.xml index a0bcc73e31..59df7d3b69 100644 --- a/jhipster/jhipster-microservice/dealer-app/pom.xml +++ b/jhipster/jhipster-microservice/dealer-app/pom.xml @@ -20,8 +20,6 @@ -Djava.security.egd=file:/dev/./urandom -Xmx256m 3.6.2 2.0.0 - 2.5 - 3.5 0.4.13 1.2 5.2.8.Final @@ -266,7 +264,7 @@ org.apache.commons commons-lang3 - ${commons-lang.version} + ${commons-lang3.version} org.assertj diff --git a/jhipster/jhipster-microservice/gateway-app/pom.xml b/jhipster/jhipster-microservice/gateway-app/pom.xml index c6dcbb3f3e..a50c2bbdd1 100644 --- a/jhipster/jhipster-microservice/gateway-app/pom.xml +++ b/jhipster/jhipster-microservice/gateway-app/pom.xml @@ -22,8 +22,6 @@ 2.0.0 3.6.0 1.10 - 2.5 - 3.5 0.4.13 1.3 1.2 @@ -299,7 +297,7 @@ org.apache.commons commons-lang3 - ${commons-lang.version} + ${commons-lang3.version} org.assertj diff --git a/jhipster/jhipster-monolithic/pom.xml b/jhipster/jhipster-monolithic/pom.xml index 04f790faf5..97f2b85b2f 100644 --- a/jhipster/jhipster-monolithic/pom.xml +++ b/jhipster/jhipster-monolithic/pom.xml @@ -171,7 +171,7 @@ org.apache.commons commons-lang3 - ${commons-lang.version} + ${commons-lang3.version} org.assertj @@ -887,8 +887,6 @@ -Djava.security.egd=file:/dev/./urandom -Xmx256m 3.6.2 2.0.0 - 2.5 - 3.5 0.4.13 1.3 2.2.1 diff --git a/jni/README.md b/jni/README.md deleted file mode 100644 index 6b984e6590..0000000000 --- a/jni/README.md +++ /dev/null @@ -1,7 +0,0 @@ -## JNI - -This module contains articles about the Java Native Interface (JNI). - -### Relevant Articles: - -- [Guide to JNI (Java Native Interface)](https://www.baeldung.com/jni) diff --git a/jni/native/linux_x86_64/libnative.so b/jni/native/linux_x86_64/libnative.so deleted file mode 100755 index 213491e268..0000000000 Binary files a/jni/native/linux_x86_64/libnative.so and /dev/null differ diff --git a/jni/native/macos/libnative.dylib b/jni/native/macos/libnative.dylib deleted file mode 100755 index 6d1264d696..0000000000 Binary files a/jni/native/macos/libnative.dylib and /dev/null differ diff --git a/jni/pom.xml b/jni/pom.xml deleted file mode 100644 index d64fa12c5a..0000000000 --- a/jni/pom.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - 4.0.0 - jni - jni - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - \ No newline at end of file diff --git a/json-2/pom.xml b/json-2/pom.xml index c5f11754f4..e27d1c83f6 100644 --- a/json-2/pom.xml +++ b/json-2/pom.xml @@ -53,12 +53,12 @@ com.fasterxml.jackson.core jackson-annotations - 2.11.0 + ${jackson.version} com.fasterxml.jackson.core jackson-databind - 2.11.0 + ${jackson.version} com.io-informatics.oss @@ -114,7 +114,6 @@ 0.9.23 3.11.1 1.9.2 - 3.9 diff --git a/kotlin-js/.gitignore b/kotlin-js/.gitignore deleted file mode 100644 index 1db5e66882..0000000000 --- a/kotlin-js/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -/bin/ - -#ignore gradle -.gradle/ - - -#ignore build and generated files -build/ -node/ - -#ignore installed node modules and package lock file -node_modules/ -package-lock.json diff --git a/kotlin-js/README.md b/kotlin-js/README.md deleted file mode 100644 index 2ec50bad78..0000000000 --- a/kotlin-js/README.md +++ /dev/null @@ -1,7 +0,0 @@ -## JavaScript in Kotlin - -This module contains articles about JavaScript in Kotlin. - -### Relevant Articles: - -- [Kotlin and Javascript](https://www.baeldung.com/kotlin-javascript) diff --git a/kotlin-js/build.gradle b/kotlin-js/build.gradle deleted file mode 100755 index 9efef0f475..0000000000 --- a/kotlin-js/build.gradle +++ /dev/null @@ -1,27 +0,0 @@ -buildscript { - ext.kotlin_version = '1.2.41' - repositories { - mavenCentral() - } - dependencies { - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -group 'com.baeldung' -version '1.0-SNAPSHOT' -apply plugin: 'kotlin2js' - -repositories { - mavenCentral() -} - -dependencies { - compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version" - testCompile "org.jetbrains.kotlin:kotlin-test-js:$kotlin_version" -} - -compileKotlin2Js.kotlinOptions { - moduleKind = "commonjs" - outputFile = "node/crypto.js" -} diff --git a/kotlin-js/gradle/wrapper/gradle-wrapper.jar b/kotlin-js/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 01b8bf6b1f..0000000000 Binary files a/kotlin-js/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/kotlin-js/gradlew b/kotlin-js/gradlew deleted file mode 100755 index cccdd3d517..0000000000 --- a/kotlin-js/gradlew +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env sh - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" diff --git a/kotlin-js/gradlew.bat b/kotlin-js/gradlew.bat deleted file mode 100755 index e95643d6a2..0000000000 --- a/kotlin-js/gradlew.bat +++ /dev/null @@ -1,84 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/kotlin-js/package.json b/kotlin-js/package.json deleted file mode 100755 index c75313e3ff..0000000000 --- a/kotlin-js/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "kotlin-node.js", - "version": "1.0.0", - "description": "Example of using NodeJS in Kotlin", - "main": "crypto.js", - "dependencies": { - "express": "^4.15.2", - "fs": "0.0.1-security", - "kotlin": "^1.1.0", - "node.js": "0.0.0", - "request": "^2.85.0" - }, - "devDependencies": {}, - "scripts": { - "start": "node node/crypto.js" - } -} diff --git a/kotlin-js/settings.gradle b/kotlin-js/settings.gradle deleted file mode 100755 index 64767a30c5..0000000000 --- a/kotlin-js/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'KotlinNode' diff --git a/kotlin-js/src/main/kotlin/com/baeldung/kotlinjs/CryptoRate.kt b/kotlin-js/src/main/kotlin/com/baeldung/kotlinjs/CryptoRate.kt deleted file mode 100755 index 92ef4a7356..0000000000 --- a/kotlin-js/src/main/kotlin/com/baeldung/kotlinjs/CryptoRate.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.kotlinjs - -external fun require(module: String): dynamic - -data class CryptoCurrency(var name: String, var price: Float) - -fun main(args: Array) { - println("Crypto Currency price API!") - val express = require("express") - val app = express() - - app.get("/crypto", { _, res -> - res.send(generateCryptoRates()) - }) - - app.listen(3000, { - println("Listening on port 3000") - }) -} -fun generateCryptoRates(): Array{ - val cryptoCurrency = arrayOf( - CryptoCurrency("Bitcoin", 90000F), - CryptoCurrency("ETH",1000F), - CryptoCurrency("TRX",10F) - ); - return cryptoCurrency -} \ No newline at end of file diff --git a/kotlin-libraries-2/.gitignore b/kotlin-libraries-2/.gitignore deleted file mode 100644 index 0c017e8f8c..0000000000 --- a/kotlin-libraries-2/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -/bin/ - -#ignore gradle -.gradle/ - - -#ignore build and generated files -build/ -node/ -out/ - -#ignore installed node modules and package lock file -node_modules/ -package-lock.json diff --git a/kotlin-libraries-2/README.md b/kotlin-libraries-2/README.md deleted file mode 100644 index f725048acd..0000000000 --- a/kotlin-libraries-2/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## Kotlin Libraries - -This module contains articles about Kotlin Libraries. - -### Relevant articles: - -- [Jackson Support for Kotlin](https://www.baeldung.com/jackson-kotlin) -- [Introduction to RxKotlin](https://www.baeldung.com/rxkotlin) -- [MockK: A Mocking Library for Kotlin](https://www.baeldung.com/kotlin-mockk) -- [Kotlin Immutable Collections](https://www.baeldung.com/kotlin-immutable-collections) -- [Dependency Injection for Kotlin with Injekt](https://www.baeldung.com/kotlin-dependency-injection-with-injekt) -- [Fuel HTTP Library with Kotlin](https://www.baeldung.com/kotlin-fuel) -- [Introduction to Kovenant Library for Kotlin](https://www.baeldung.com/kotlin-kovenant) -- More articles: [[<-- prev]](/kotlin-libraries) diff --git a/kotlin-libraries-2/pom.xml b/kotlin-libraries-2/pom.xml deleted file mode 100644 index 254f2c6907..0000000000 --- a/kotlin-libraries-2/pom.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - 4.0.0 - kotlin-libraries-2 - kotlin-libraries-2 - jar - - - com.baeldung - parent-kotlin - 1.0.0-SNAPSHOT - ../parent-kotlin - - - - - com.fasterxml.jackson.module - jackson-module-kotlin - - - io.reactivex.rxjava2 - rxkotlin - ${rxkotlin.version} - - - junit - junit - test - - - com.google.guava - guava - ${guava.version} - - - - org.jetbrains.kotlinx - kotlinx-collections-immutable - ${kotlinx-collections-immutable.version} - - - uy.kohesive.injekt - injekt-core - ${injekt-core.version} - - - com.github.kittinunf.fuel - fuel - ${fuel.version} - - - com.github.kittinunf.fuel - fuel-gson - ${fuel.version} - - - com.github.kittinunf.fuel - fuel-rxjava - ${fuel.version} - - - com.github.kittinunf.fuel - fuel-coroutines - ${fuel.version} - - - nl.komponents.kovenant - kovenant - ${kovenant.version} - pom - - - - io.mockk - mockk - ${mockk.version} - test - - - - - 1.16.1 - 1.15.0 - 3.3.0 - 27.1-jre - 1.9.3 - 0.1 - 2.3.0 - - - diff --git a/kotlin-libraries-2/resources/logback.xml b/kotlin-libraries-2/resources/logback.xml deleted file mode 100644 index 9452207268..0000000000 --- a/kotlin-libraries-2/resources/logback.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - \ No newline at end of file diff --git a/kotlin-libraries-2/src/main/kotlin/com/baeldung/fuel/Interceptors.kt b/kotlin-libraries-2/src/main/kotlin/com/baeldung/fuel/Interceptors.kt deleted file mode 100644 index 377ef979dc..0000000000 --- a/kotlin-libraries-2/src/main/kotlin/com/baeldung/fuel/Interceptors.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.fuel - -import com.github.kittinunf.fuel.core.Request - -fun tokenInterceptor() = { - next: (Request) -> Request -> - { req: Request -> - req.header(mapOf("Authorization" to "Bearer AbCdEf123456")) - next(req) - } -} \ No newline at end of file diff --git a/kotlin-libraries-2/src/main/kotlin/com/baeldung/fuel/Post.kt b/kotlin-libraries-2/src/main/kotlin/com/baeldung/fuel/Post.kt deleted file mode 100644 index 035dfe7aa0..0000000000 --- a/kotlin-libraries-2/src/main/kotlin/com/baeldung/fuel/Post.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.fuel - -import com.github.kittinunf.fuel.core.ResponseDeserializable -import com.google.gson.Gson - -data class Post(var userId:Int, - var id:Int, - var title:String, - var body:String){ - - - class Deserializer : ResponseDeserializable> { - override fun deserialize(content: String): Array = Gson().fromJson(content, Array::class.java) - } -} \ No newline at end of file diff --git a/kotlin-libraries-2/src/main/kotlin/com/baeldung/fuel/PostRoutingAPI.kt b/kotlin-libraries-2/src/main/kotlin/com/baeldung/fuel/PostRoutingAPI.kt deleted file mode 100644 index 8238c41e56..0000000000 --- a/kotlin-libraries-2/src/main/kotlin/com/baeldung/fuel/PostRoutingAPI.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.fuel - -import com.github.kittinunf.fuel.core.Method -import com.github.kittinunf.fuel.util.FuelRouting - -sealed class PostRoutingAPI : FuelRouting { - - override val basePath = "https://jsonplaceholder.typicode.com" - - class posts(val id: String, override val body: String?): PostRoutingAPI() - - class comments(val postId: String, override val body: String?): PostRoutingAPI() - - override val method: Method - get() { - return when(this) { - is PostRoutingAPI.posts -> Method.GET - is PostRoutingAPI.comments -> Method.GET - } - } - - override val path: String - get() { - return when(this) { - is PostRoutingAPI.posts -> "/posts" - is PostRoutingAPI.comments -> "/comments" - } - } - - override val params: List>? - get() { - return when(this) { - is PostRoutingAPI.posts -> listOf("id" to this.id) - is PostRoutingAPI.comments -> listOf("postId" to this.postId) - } - } - - override val headers: Map? - get() { - return null - } -} diff --git a/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/DelegateInjectionApplication.kt b/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/DelegateInjectionApplication.kt deleted file mode 100644 index fb9beda621..0000000000 --- a/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/DelegateInjectionApplication.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.baeldung.injekt - -import org.slf4j.LoggerFactory -import uy.kohesive.injekt.* -import uy.kohesive.injekt.api.* -import java.util.* - -class DelegateInjectionApplication { - companion object : InjektMain() { - private val LOG = LoggerFactory.getLogger(DelegateInjectionApplication::class.java) - @JvmStatic fun main(args: Array) { - DelegateInjectionApplication().run() - } - - override fun InjektRegistrar.registerInjectables() { - addFactory { - val value = FactoryInstance("Factory" + UUID.randomUUID().toString()) - LOG.info("Constructing instance: {}", value) - value - } - - addSingletonFactory { - val value = SingletonInstance("Singleton" + UUID.randomUUID().toString()) - LOG.info("Constructing singleton instance: {}", value) - value - } - - addSingletonFactory { App() } - } - } - - data class FactoryInstance(val value: String) - data class SingletonInstance(val value: String) - - class App { - private val instance: FactoryInstance by injectValue() - private val lazyInstance: FactoryInstance by injectLazy() - private val singleton: SingletonInstance by injectValue() - private val lazySingleton: SingletonInstance by injectLazy() - - fun run() { - for (i in 1..5) { - LOG.info("Instance {}: {}", i, instance) - } - for (i in 1..5) { - LOG.info("Lazy Instance {}: {}", i, lazyInstance) - } - for (i in 1..5) { - LOG.info("Singleton {}: {}", i, singleton) - } - for (i in 1..5) { - LOG.info("Lazy Singleton {}: {}", i, lazySingleton) - } - } - } - - fun run() { - Injekt.get().run() - } -} diff --git a/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/KeyedApplication.kt b/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/KeyedApplication.kt deleted file mode 100644 index 4205678981..0000000000 --- a/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/KeyedApplication.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.baeldung.injekt - -import org.slf4j.LoggerFactory -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.InjektMain -import uy.kohesive.injekt.api.InjektRegistrar -import uy.kohesive.injekt.api.addPerKeyFactory -import uy.kohesive.injekt.api.addSingletonFactory -import uy.kohesive.injekt.api.get - -class KeyedApplication { - companion object : InjektMain() { - private val LOG = LoggerFactory.getLogger(KeyedApplication::class.java) - @JvmStatic fun main(args: Array) { - KeyedApplication().run() - } - - override fun InjektRegistrar.registerInjectables() { - val configs = mapOf( - "google" to Config("googleClientId", "googleClientSecret"), - "twitter" to Config("twitterClientId", "twitterClientSecret") - ) - addPerKeyFactory {key -> configs[key]!! } - - addSingletonFactory { App() } - } - } - - data class Config(val clientId: String, val clientSecret: String) - - class App { - fun run() { - LOG.info("Google config: {}", Injekt.get("google")) - LOG.info("Twitter config: {}", Injekt.get("twitter")) - } - } - - fun run() { - Injekt.get().run() - } -} diff --git a/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/ModularApplication.kt b/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/ModularApplication.kt deleted file mode 100644 index 96a0c9556a..0000000000 --- a/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/ModularApplication.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.baeldung.injekt - -import org.slf4j.LoggerFactory -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.InjektMain -import uy.kohesive.injekt.api.* - -class ModularApplication { - class ConfigModule(private val port: Int) : InjektModule { - override fun InjektRegistrar.registerInjectables() { - addSingleton(Config(port)) - } - } - - object ServerModule : InjektModule { - override fun InjektRegistrar.registerInjectables() { - addSingletonFactory { Server(Injekt.get()) } - } - } - - companion object : InjektMain() { - private val LOG = LoggerFactory.getLogger(Server::class.java) - @JvmStatic fun main(args: Array) { - ModularApplication().run() - } - - override fun InjektRegistrar.registerInjectables() { - importModule(ConfigModule(12345)) - importModule(ServerModule) - } - } - - data class Config( - val port: Int - ) - - class Server(private val config: Config) { - - fun start() { - LOG.info("Starting server on ${config.port}") - } - } - - fun run() { - Injekt.get().start() - } -} diff --git a/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/PerThreadApplication.kt b/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/PerThreadApplication.kt deleted file mode 100644 index f3167bc223..0000000000 --- a/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/PerThreadApplication.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.baeldung.injekt - -import org.slf4j.LoggerFactory -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.InjektMain -import uy.kohesive.injekt.api.InjektRegistrar -import uy.kohesive.injekt.api.addPerThreadFactory -import uy.kohesive.injekt.api.addSingletonFactory -import uy.kohesive.injekt.api.get -import java.util.* -import java.util.concurrent.Executors -import java.util.concurrent.TimeUnit - -class PerThreadApplication { - companion object : InjektMain() { - private val LOG = LoggerFactory.getLogger(PerThreadApplication::class.java) - @JvmStatic fun main(args: Array) { - PerThreadApplication().run() - } - - override fun InjektRegistrar.registerInjectables() { - addPerThreadFactory { - val value = FactoryInstance(UUID.randomUUID().toString()) - LOG.info("Constructing instance: {}", value) - value - } - - addSingletonFactory { App() } - } - } - - data class FactoryInstance(val value: String) - - class App { - fun run() { - val threadPool = Executors.newFixedThreadPool(5) - - for (i in 1..20) { - threadPool.submit { - val instance = Injekt.get() - LOG.info("Value for thread {}: {}", Thread.currentThread().id, instance) - TimeUnit.MILLISECONDS.sleep(100) - } - } - threadPool.awaitTermination(10, TimeUnit.SECONDS) - } - } - - fun run() { - Injekt.get().run() - } -} diff --git a/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/SimpleApplication.kt b/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/SimpleApplication.kt deleted file mode 100644 index 5c2dc28ba5..0000000000 --- a/kotlin-libraries-2/src/main/kotlin/com/baeldung/injekt/SimpleApplication.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.baeldung.injekt - -import org.slf4j.LoggerFactory -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.InjektMain -import uy.kohesive.injekt.api.InjektRegistrar -import uy.kohesive.injekt.api.addSingleton -import uy.kohesive.injekt.api.addSingletonFactory -import uy.kohesive.injekt.api.get - -class SimpleApplication { - companion object : InjektMain() { - private val LOG = LoggerFactory.getLogger(Server::class.java) - @JvmStatic fun main(args: Array) { - SimpleApplication().run() - } - - override fun InjektRegistrar.registerInjectables() { - addSingleton(Config(12345)) - addSingletonFactory { Server(Injekt.get()) } - } - } - - data class Config( - val port: Int - ) - - class Server(private val config: Config) { - - fun start() { - LOG.info("Starting server on ${config.port}") - } - } - - fun run() { - Injekt.get().start() - } -} diff --git a/kotlin-libraries-2/src/main/kotlin/com/baeldung/kotlin/jackson/Book.kt b/kotlin-libraries-2/src/main/kotlin/com/baeldung/kotlin/jackson/Book.kt deleted file mode 100644 index 4ff47ea987..0000000000 --- a/kotlin-libraries-2/src/main/kotlin/com/baeldung/kotlin/jackson/Book.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.kotlin.jackson - -import com.fasterxml.jackson.annotation.* - -@JsonInclude(JsonInclude.Include.NON_EMPTY) -data class Book(var title: String, @JsonProperty("author") var authorName: String) { - var genres: List? = emptyList() -} \ No newline at end of file diff --git a/kotlin-libraries-2/src/main/kotlin/com/baeldung/kotlin/jackson/Movie.kt b/kotlin-libraries-2/src/main/kotlin/com/baeldung/kotlin/jackson/Movie.kt deleted file mode 100644 index 445b6013d5..0000000000 --- a/kotlin-libraries-2/src/main/kotlin/com/baeldung/kotlin/jackson/Movie.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.kotlin.jackson - -data class Movie(var name: String, var studio: String, var rating: Float? = 1f) \ No newline at end of file diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/fuel/FuelHttpLiveTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/fuel/FuelHttpLiveTest.kt deleted file mode 100644 index 69b6ae88c6..0000000000 --- a/kotlin-libraries-2/src/test/kotlin/com/baeldung/fuel/FuelHttpLiveTest.kt +++ /dev/null @@ -1,280 +0,0 @@ -package com.baeldung.fuel - -import com.github.kittinunf.fuel.Fuel -import com.github.kittinunf.fuel.core.FuelManager -import com.github.kittinunf.fuel.core.interceptors.cUrlLoggingRequestInterceptor -import com.github.kittinunf.fuel.gson.responseObject -import com.github.kittinunf.fuel.httpGet -import com.github.kittinunf.fuel.rx.rx_object -import com.google.gson.Gson -import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Test -import java.io.File -import java.util.concurrent.CountDownLatch - -/** - * These live tests make connections to the external systems: http://httpbin.org, https://jsonplaceholder.typicode.com - * Make sure these hosts are up and your internet connection is on before running the tests. - */ -internal class FuelHttpLiveTest { - - @Test - fun whenMakingAsyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() { - - val latch = CountDownLatch(1) - - "http://httpbin.org/get".httpGet().response{ - request, response, result -> - - val (data, error) = result - - Assertions.assertNull(error) - Assertions.assertNotNull(data) - Assertions.assertEquals(200,response.statusCode) - - latch.countDown() - } - - latch.await() - - } - - @Test - fun whenMakingSyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() { - - val (request, response, result) = "http://httpbin.org/get".httpGet().response() - val (data, error) = result - - Assertions.assertNull(error) - Assertions.assertNotNull(data) - Assertions.assertEquals(200,response.statusCode) - - } - - @Test - fun whenMakingSyncHttpGetURLEncodedRequest_thenResponseNotNullAndErrorNullAndStatusCode200() { - - val (request, response, result) = - "https://jsonplaceholder.typicode.com/posts" - .httpGet(listOf("id" to "1")).response() - val (data, error) = result - - Assertions.assertNull(error) - Assertions.assertNotNull(data) - Assertions.assertEquals(200,response.statusCode) - - } - - @Test - fun whenMakingAsyncHttpPostRequest_thenResponseNotNullAndErrorNullAndStatusCode200() { - - val latch = CountDownLatch(1) - - Fuel.post("http://httpbin.org/post").response{ - request, response, result -> - - val (data, error) = result - - Assertions.assertNull(error) - Assertions.assertNotNull(data) - Assertions.assertEquals(200,response.statusCode) - - latch.countDown() - } - - latch.await() - - } - - @Test - fun whenMakingSyncHttpPostRequest_thenResponseNotNullAndErrorNullAndStatusCode200() { - - val (request, response, result) = Fuel.post("http://httpbin.org/post").response() - val (data, error) = result - - Assertions.assertNull(error) - Assertions.assertNotNull(data) - Assertions.assertEquals(200,response.statusCode) - } - - @Test - fun whenMakingSyncHttpPostRequestwithBody_thenResponseNotNullAndErrorNullAndStatusCode200() { - - val (request, response, result) = Fuel.post("https://jsonplaceholder.typicode.com/posts") - .body("{ \"title\" : \"foo\",\"body\" : \"bar\",\"id\" : \"1\"}") - .response() - - val (data, error) = result - - Assertions.assertNull(error) - Assertions.assertNotNull(data) - Assertions.assertEquals(201,response.statusCode) - } - - @Test - fun givenFuelInstance_whenMakingSyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() { - - FuelManager.instance.basePath = "http://httpbin.org" - FuelManager.instance.baseHeaders = mapOf("OS" to "macOS High Sierra") - - FuelManager.instance.addRequestInterceptor(cUrlLoggingRequestInterceptor()) - FuelManager.instance.addRequestInterceptor(tokenInterceptor()) - - - val (request, response, result) = "/get" - .httpGet().response() - val (data, error) = result - - Assertions.assertNull(error) - Assertions.assertNotNull(data) - Assertions.assertEquals(200,response.statusCode) - } - - @Test - fun givenInterceptors_whenMakingSyncHttpGetRequest_thenResponseNotNullAndErrorNullAndStatusCode200() { - - FuelManager.instance.basePath = "http://httpbin.org" - FuelManager.instance.addRequestInterceptor(cUrlLoggingRequestInterceptor()) - FuelManager.instance.addRequestInterceptor(tokenInterceptor()) - - val (request, response, result) = "/get" - .httpGet().response() - val (data, error) = result - - Assertions.assertNull(error) - Assertions.assertNotNull(data) - Assertions.assertEquals(200,response.statusCode) - } - - @Test - fun whenDownloadFile_thenCreateFileResponseNotNullAndErrorNullAndStatusCode200() { - - Fuel.download("http://httpbin.org/bytes/32768").destination { response, url -> - File.createTempFile("temp", ".tmp") - }.response{ - request, response, result -> - - val (data, error) = result - Assertions.assertNull(error) - Assertions.assertNotNull(data) - Assertions.assertEquals(200,response.statusCode) - } - } - - @Test - fun whenDownloadFilewithProgressHandler_thenCreateFileResponseNotNullAndErrorNullAndStatusCode200() { - - val (request, response, result) = Fuel.download("http://httpbin.org/bytes/327680") - .destination { response, url -> File.createTempFile("temp", ".tmp") - }.progress { readBytes, totalBytes -> - val progress = readBytes.toFloat() / totalBytes.toFloat() - }.response () - - val (data, error) = result - Assertions.assertNull(error) - Assertions.assertNotNull(data) - Assertions.assertEquals(200,response.statusCode) - - - } - - @Test - fun whenMakeGetRequest_thenDeserializePostwithGson() { - - val latch = CountDownLatch(1) - - "https://jsonplaceholder.typicode.com/posts/1".httpGet().responseObject { _,_, result -> - val post = result.component1() - Assertions.assertEquals(1, post?.userId) - latch.countDown() - } - - latch.await() - - } - - @Test - fun whenMakePOSTRequest_thenSerializePostwithGson() { - - val post = Post(1,1, "Lorem", "Lorem Ipse dolor sit amet") - - val (request, response, result) = Fuel.post("https://jsonplaceholder.typicode.com/posts") - .header("Content-Type" to "application/json") - .body(Gson().toJson(post).toString()) - .response() - - Assertions.assertEquals(201,response.statusCode) - - } - - @Test - fun whenMakeGETRequestWithRxJava_thenDeserializePostwithGson() { - - val latch = CountDownLatch(1) - - - "https://jsonplaceholder.typicode.com/posts?id=1" - .httpGet().rx_object(Post.Deserializer()).subscribe{ - res, throwable -> - - val post = res.component1() - Assertions.assertEquals(1, post?.get(0)?.userId) - latch.countDown() - } - - latch.await() - - } - - -// The new 1.3 coroutine APIs, aren't implemented yet in Fuel Library -// @Test -// fun whenMakeGETRequestUsingCoroutines_thenResponseStatusCode200() = runBlocking { -// val (request, response, result) = Fuel.get("http://httpbin.org/get").awaitStringResponse() -// -// result.fold({ data -> -// Assertions.assertEquals(200, response.statusCode) -// -// }, { error -> }) -// } - -// The new 1.3 coroutine APIs, aren't implemented yet in Fuel Library -// @Test -// fun whenMakeGETRequestUsingCoroutines_thenDeserializeResponse() = runBlocking { -// Fuel.get("https://jsonplaceholder.typicode.com/posts?id=1").awaitObjectResult(Post.Deserializer()) -// .fold({ data -> -// Assertions.assertEquals(1, data.get(0).userId) -// }, { error -> }) -// } - - @Test - fun whenMakeGETPostRequestUsingRoutingAPI_thenDeserializeResponse() { - - val latch = CountDownLatch(1) - - Fuel.request(PostRoutingAPI.posts("1",null)) - .responseObject(Post.Deserializer()) { - request, response, result -> - Assertions.assertEquals(1, result.component1()?.get(0)?.userId) - latch.countDown() - } - - latch.await() - } - - @Test - fun whenMakeGETCommentRequestUsingRoutingAPI_thenResponseStausCode200() { - - val latch = CountDownLatch(1) - - Fuel.request(PostRoutingAPI.comments("1",null)) - .responseString { request, response, result -> - Assertions.assertEquals(200, response.statusCode) - latch.countDown() - } - - latch.await() - } - - -} \ No newline at end of file diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/gson/GsonUnitTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/gson/GsonUnitTest.kt deleted file mode 100644 index 9159be96be..0000000000 --- a/kotlin-libraries-2/src/test/kotlin/com/baeldung/gson/GsonUnitTest.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.gson - -import com.google.gson.Gson - -import org.junit.Assert -import org.junit.Test - -class GsonUnitTest { - - var gson = Gson() - - @Test - fun givenObject_thenGetJSONString() { - var jsonString = gson.toJson(TestModel(1, "Test")) - Assert.assertEquals(jsonString, "{\"id\":1,\"description\":\"Test\"}") - } - - @Test - fun givenJSONString_thenGetObject() { - var jsonString = "{\"id\":1,\"description\":\"Test\"}"; - var testModel = gson.fromJson(jsonString, TestModel::class.java) - Assert.assertEquals(testModel.id, 1) - Assert.assertEquals(testModel.description, "Test") - } - - data class TestModel( - val id: Int, - val description: String - ) -} \ No newline at end of file diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/immutable/KotlinxImmutablesUnitTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/immutable/KotlinxImmutablesUnitTest.kt deleted file mode 100644 index 971f2de4c2..0000000000 --- a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/immutable/KotlinxImmutablesUnitTest.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.kotlin.immutable - -import junit.framework.Assert.assertEquals -import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.immutableListOf -import org.junit.Rule -import org.junit.Test -import org.junit.rules.ExpectedException - -class KotlinxImmutablesUnitTest{ - - - @Rule - @JvmField - var ee : ExpectedException = ExpectedException.none() - - @Test - fun givenKICLList_whenAddTried_checkExceptionThrown(){ - - val list: ImmutableList = immutableListOf("I", "am", "immutable") - - list.add("My new item") - - assertEquals(listOf("I", "am", "immutable"), list) - - } -} \ No newline at end of file diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/immutable/ReadOnlyUnitTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/immutable/ReadOnlyUnitTest.kt deleted file mode 100644 index 62c4a4eb88..0000000000 --- a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/immutable/ReadOnlyUnitTest.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.baeldung.kotlin.immutable - -import com.google.common.collect.ImmutableList -import com.google.common.collect.ImmutableSet -import junit.framework.Assert.assertEquals -import org.junit.Rule -import org.junit.Test -import org.junit.rules.ExpectedException - -class ReadOnlyUnitTest{ - - @Test - fun givenReadOnlyList_whenCastToMutableList_checkNewElementsAdded(){ - - val list: List = listOf("This", "Is", "Totally", "Immutable") - - (list as MutableList)[2] = "Not" - - assertEquals(listOf("This", "Is", "Not", "Immutable"), list) - - } - - @Rule - @JvmField - var ee : ExpectedException = ExpectedException.none() - - @Test - fun givenImmutableList_whenAddTried_checkExceptionThrown(){ - - val list: List = ImmutableList.of("I", "am", "actually", "immutable") - - ee.expect(UnsupportedOperationException::class.java) - - (list as MutableList).add("Oops") - - } - - @Test - fun givenMutableList_whenCopiedAndAddTried_checkExceptionThrown(){ - - val mutableList : List = listOf("I", "Am", "Definitely", "Immutable") - - (mutableList as MutableList)[2] = "100% Not" - - assertEquals(listOf("I", "Am", "100% Not", "Immutable"), mutableList) - - val list: List = ImmutableList.copyOf(mutableList) - - ee.expect(UnsupportedOperationException::class.java) - - (list as MutableList)[2] = "Really?" - - } - - @Test - fun givenImmutableSetBuilder_whenAddTried_checkExceptionThrown(){ - - val mutableList : List = listOf("Hello", "Baeldung") - val set: ImmutableSet = ImmutableSet.builder() - .add("I","am","immutable") - .addAll(mutableList) - .build() - - assertEquals(setOf("Hello", "Baeldung", "I", "am", "immutable"), set) - - ee.expect(UnsupportedOperationException::class.java) - - (set as MutableSet).add("Oops") - - } - - -} \ No newline at end of file diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/jackson/JacksonUnitTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/jackson/JacksonUnitTest.kt deleted file mode 100644 index 0c72edc2fd..0000000000 --- a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/jackson/JacksonUnitTest.kt +++ /dev/null @@ -1,122 +0,0 @@ -package com.baeldung.kotlin.jackson - -import org.junit.Test -import kotlin.test.assertTrue -import kotlin.test.assertFalse -import kotlin.test.assertEquals -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper -import com.fasterxml.jackson.module.kotlin.readValue -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.module.kotlin.KotlinModule - -class JacksonUnitTest { - //val mapper = jacksonObjectMapper() - val mapper = ObjectMapper().registerModule(KotlinModule()) - - - @Test - fun whenSerializeMovie_thenSuccess() { - val movie = Movie("Endgame", "Marvel", 9.2f) - val serialized = mapper.writeValueAsString(movie) - - val json = """{"name":"Endgame","studio":"Marvel","rating":9.2}""" - assertEquals(serialized, json) - } - - @Test - fun whenDeserializeMovie_thenSuccess() { - val json = """{"name":"Endgame","studio":"Marvel","rating":9.2}""" - // val movie: Movie = mapper.readValue(json) - val movie = mapper.readValue(json) - - assertEquals(movie.name, "Endgame") - assertEquals(movie.studio, "Marvel") - assertEquals(movie.rating, 9.2f) - } - - @Test - fun whenDeserializeMovieWithMissingValue_thenUseDefaultValue() { - val json = """{"name":"Endgame","studio":"Marvel"}""" - val movie: Movie = mapper.readValue(json) - - assertEquals(movie.name, "Endgame") - assertEquals(movie.studio, "Marvel") - assertEquals(movie.rating, 1f) - } - - @Test - fun whenSerializeMap_thenSuccess() { - val map = mapOf(1 to "one", 2 to "two") - val serialized = mapper.writeValueAsString(map) - - val json = """{"1":"one","2":"two"}""" - assertEquals(serialized, json) - } - - @Test - fun whenDeserializeMap_thenSuccess() { - val json = """{"1":"one","2":"two"}""" - val aMap: Map = mapper.readValue(json) - - assertEquals(aMap[1], "one") - assertEquals(aMap[2], "two") - - val sameMap = mapper.readValue>(json) - assertEquals(sameMap[1], "one") - assertEquals(sameMap[2], "two") - } - - @Test - fun whenSerializeList_thenSuccess() { - val movie1 = Movie("Endgame", "Marvel", 9.2f) - val movie2 = Movie("Shazam", "Warner Bros", 7.6f) - val movieList = listOf(movie1, movie2) - val serialized = mapper.writeValueAsString(movieList) - - val json = """[{"name":"Endgame","studio":"Marvel","rating":9.2},{"name":"Shazam","studio":"Warner Bros","rating":7.6}]""" - assertEquals(serialized, json) - } - - @Test - fun whenDeserializeList_thenSuccess() { - val json = """[{"name":"Endgame","studio":"Marvel","rating":9.2},{"name":"Shazam","studio":"Warner Bros","rating":7.6}]""" - val movieList: List = mapper.readValue(json) - - val movie1 = Movie("Endgame", "Marvel", 9.2f) - val movie2 = Movie("Shazam", "Warner Bros", 7.6f) - assertTrue(movieList.contains(movie1)) - assertTrue(movieList.contains(movie2)) - - val sameList = mapper.readValue>(json) - assertTrue(sameList.contains(movie1)) - assertTrue(sameList.contains(movie2)) - } - - @Test - fun whenSerializeBook_thenSuccess() { - val book = Book("Oliver Twist", "Charles Dickens") - val serialized = mapper.writeValueAsString(book) - - val json = """{"title":"Oliver Twist","author":"Charles Dickens"}""" - assertEquals(serialized, json) - } - - @Test - fun whenDeserializeBook_thenSuccess() { - val json = """{"title":"Oliver Twist","author":"Charles Dickens"}""" - val book: Book = mapper.readValue(json) - - assertEquals(book.title, "Oliver Twist") - assertEquals(book.authorName, "Charles Dickens") - } - - @Test - fun givenJsonInclude_whenSerializeBook_thenEmptyFieldExcluded() { - val book = Book("Oliver Twist", "Charles Dickens") - val serialized = mapper.writeValueAsString(book) - - val json = """{"title":"Oliver Twist","author":"Charles Dickens"}""" - assertEquals(serialized, json) - } - -} \ No newline at end of file diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt deleted file mode 100644 index 979ed3f809..0000000000 --- a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt +++ /dev/null @@ -1,157 +0,0 @@ -package com.baeldung.kotlin.rxkotlin - -import io.reactivex.Maybe -import io.reactivex.Observable -import io.reactivex.functions.BiFunction -import io.reactivex.rxkotlin.* -import io.reactivex.subjects.PublishSubject -import org.junit.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse - -class RxKotlinTest { - - @Test - fun whenBooleanArrayToObserver_thenBooleanObserver() { - val observable = listOf(true, false, false).toObservable() - observable.test().assertValues(true, false, false) - } - - @Test - fun whenBooleanArrayToFlowable_thenBooleanFlowable() { - val flowable = listOf(true, false, false).toFlowable() - flowable.buffer(2).test().assertValues(listOf(true, false), listOf(false)) - } - - @Test - fun whenIntArrayToObserver_thenIntObserver() { - val observable = listOf(1, 1, 2, 3).toObservable() - observable.test().assertValues(1, 1, 2, 3) - } - - @Test - fun whenIntArrayToFlowable_thenIntFlowable() { - val flowable = listOf(1, 1, 2, 3).toFlowable() - flowable.buffer(2).test().assertValues(listOf(1, 1), listOf(2, 3)) - } - - @Test - fun whenObservablePairToMap_thenSingleNoDuplicates() { - val list = listOf(Pair("a", 1), Pair("b", 2), Pair("c", 3), Pair("a", 4)) - val observable = list.toObservable() - val map = observable.toMap() - assertEquals(mapOf(Pair("a", 4), Pair("b", 2), Pair("c", 3)), map.blockingGet()) - } - - @Test - fun whenObservablePairToMap_thenSingleWithDuplicates() { - val list = listOf(Pair("a", 1), Pair("b", 2), Pair("c", 3), Pair("a", 4)) - val observable = list.toObservable() - val map = observable.toMultimap() - assertEquals( - mapOf(Pair("a", listOf(1, 4)), Pair("b", listOf(2)), Pair("c", listOf(3))), - map.blockingGet()) - } - - @Test - fun whenMergeAll_thenStream() { - val subject = PublishSubject.create>() - val observable = subject.mergeAll() - val testObserver = observable.test() - subject.onNext(Observable.just("first", "second")) - testObserver.assertValues("first", "second") - subject.onNext(Observable.just("third", "fourth")) - subject.onNext(Observable.just("fifth")) - testObserver.assertValues("first", "second", "third", "fourth", "fifth") - } - - @Test - fun whenConcatAll_thenStream() { - val subject = PublishSubject.create>() - val observable = subject.concatAll() - val testObserver = observable.test() - subject.onNext(Observable.just("first", "second")) - testObserver.assertValues("first", "second") - subject.onNext(Observable.just("third", "fourth")) - subject.onNext(Observable.just("fifth")) - testObserver.assertValues("first", "second", "third", "fourth", "fifth") - } - - @Test - fun whenSwitchLatest_thenStream() { - val subject = PublishSubject.create>() - val observable = subject.switchLatest() - val testObserver = observable.test() - subject.onNext(Observable.just("first", "second")) - testObserver.assertValues("first", "second") - subject.onNext(Observable.just("third", "fourth")) - subject.onNext(Observable.just("fifth")) - testObserver.assertValues("first", "second", "third", "fourth", "fifth") - } - - @Test - fun whenMergeAllMaybes_thenObservable() { - val subject = PublishSubject.create>() - val observable = subject.mergeAllMaybes() - val testObserver = observable.test() - subject.onNext(Maybe.just(1)) - subject.onNext(Maybe.just(2)) - subject.onNext(Maybe.empty()) - testObserver.assertValues(1, 2) - subject.onNext(Maybe.error(Exception(""))) - subject.onNext(Maybe.just(3)) - testObserver.assertValues(1, 2).assertError(Exception::class.java) - } - - @Test - fun whenMerge_thenStream() { - val observables = mutableListOf(Observable.just("first", "second")) - val observable = observables.merge() - observables.add(Observable.just("third", "fourth")) - observables.add(Observable.error(Exception("e"))) - observables.add(Observable.just("fifth")) - - observable.test().assertValues("first", "second", "third", "fourth").assertError(Exception::class.java) - } - - @Test - fun whenMergeDelayError_thenStream() { - val observables = mutableListOf>(Observable.error(Exception("e1"))) - val observable = observables.mergeDelayError() - observables.add(Observable.just("1", "2")) - observables.add(Observable.error(Exception("e2"))) - observables.add(Observable.just("3")) - - observable.test().assertValues("1", "2", "3").assertError(Exception::class.java) - } - - @Test - fun whenCast_thenUniformType() { - val observable = Observable.just(1, 1, 2, 3) - observable.cast().test().assertValues(1, 1, 2, 3) - } - - @Test - fun whenOfType_thenFilter() { - val observable = Observable.just(1, "and", 2, "and") - observable.ofType().test().assertValues(1, 2) - } - - @Test - fun whenFunction_thenCompletable() { - var value = 0 - val completable = { value = 3 }.toCompletable() - assertFalse(completable.test().isCancelled) - assertEquals(3, value) - } - - @Test - fun whenHelper_thenMoreIdiomaticKotlin() { - val zipWith = Observable.just(1).zipWith(Observable.just(2)) { a, b -> a + b } - zipWith.subscribeBy(onNext = { println(it) }) - val zip = Observables.zip(Observable.just(1), Observable.just(2)) { a, b -> a + b } - zip.subscribeBy(onNext = { println(it) }) - val zipOrig = Observable.zip(Observable.just(1), Observable.just(2), BiFunction { a, b -> a + b }) - zipOrig.subscribeBy(onNext = { println(it) }) - } -} diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kovenant/KovenantTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/kovenant/KovenantTest.kt deleted file mode 100644 index 046b7380f7..0000000000 --- a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kovenant/KovenantTest.kt +++ /dev/null @@ -1,192 +0,0 @@ -package com.baeldung.kovenant - -import nl.komponents.kovenant.* -import nl.komponents.kovenant.Kovenant.deferred -import nl.komponents.kovenant.combine.and -import nl.komponents.kovenant.combine.combine -import org.junit.Assert -import org.junit.Before -import org.junit.Test -import java.io.IOException -import java.util.* -import java.util.concurrent.TimeUnit - -class KovenantTest { - - @Before - fun setupTestMode() { - Kovenant.testMode { error -> - println("An unexpected error occurred") - Assert.fail(error.message) - } - } - - @Test - fun testSuccessfulDeferred() { - val def = deferred() - Assert.assertFalse(def.promise.isDone()) - - def.resolve(1L) - Assert.assertTrue(def.promise.isDone()) - Assert.assertTrue(def.promise.isSuccess()) - Assert.assertFalse(def.promise.isFailure()) - } - - @Test - fun testFailedDeferred() { - val def = deferred() - Assert.assertFalse(def.promise.isDone()) - - def.reject(RuntimeException()) - Assert.assertTrue(def.promise.isDone()) - Assert.assertFalse(def.promise.isSuccess()) - Assert.assertTrue(def.promise.isFailure()) - } - - @Test - fun testResolveDeferredTwice() { - val def = deferred() - def.resolve(1L) - try { - def.resolve(1L) - } catch (e: AssertionError) { - // Expected. - // This is slightly unusual. The AssertionError comes from Assert.fail() from setupTestMode() - } - } - - @Test - fun testSuccessfulTask() { - val promise = task { 1L } - Assert.assertTrue(promise.isDone()) - Assert.assertTrue(promise.isSuccess()) - Assert.assertFalse(promise.isFailure()) - } - - @Test - fun testFailedTask() { - val promise = task { throw RuntimeException() } - Assert.assertTrue(promise.isDone()) - Assert.assertFalse(promise.isSuccess()) - Assert.assertTrue(promise.isFailure()) - } - - @Test - fun testCallbacks() { - val promise = task { 1L } - - promise.success { - println("This was a success") - Assert.assertEquals(1L, it) - } - - promise.fail { - println(it) - Assert.fail("This shouldn't happen") - } - - promise.always { - println("This always happens") - } - } - - @Test - fun testGetValues() { - val promise = task { 1L } - Assert.assertEquals(1L, promise.get()) - } - - @Test - fun testAllSucceed() { - val numbers = all( - task { 1L }, - task { 2L }, - task { 3L } - ) - - Assert.assertEquals(listOf(1L, 2L, 3L), numbers.get()) - } - - @Test - fun testOneFails() { - val runtimeException = RuntimeException() - - val numbers = all( - task { 1L }, - task { 2L }, - task { throw runtimeException } - ) - - Assert.assertEquals(runtimeException, numbers.getError()) - } - - @Test - fun testAnySucceeds() { - val promise = any( - task { - TimeUnit.SECONDS.sleep(3) - 1L - }, - task { - TimeUnit.SECONDS.sleep(2) - 2L - }, - task { - TimeUnit.SECONDS.sleep(1) - 3L - } - ) - - Assert.assertTrue(promise.isDone()) - Assert.assertTrue(promise.isSuccess()) - Assert.assertFalse(promise.isFailure()) - } - - @Test - fun testAllFails() { - val runtimeException = RuntimeException() - val ioException = IOException() - val illegalStateException = IllegalStateException() - val promise = any( - task { - TimeUnit.SECONDS.sleep(3) - throw runtimeException - }, - task { - TimeUnit.SECONDS.sleep(2) - throw ioException - }, - task { - TimeUnit.SECONDS.sleep(1) - throw illegalStateException - } - ) - - Assert.assertTrue(promise.isDone()) - Assert.assertFalse(promise.isSuccess()) - Assert.assertTrue(promise.isFailure()) - } - - @Test - fun testSimpleCombine() { - val promise = task { 1L } and task { "Hello" } - val result = promise.get() - - Assert.assertEquals(1L, result.first) - Assert.assertEquals("Hello", result.second) - } - - @Test - fun testLongerCombine() { - val promise = combine( - task { 1L }, - task { "Hello" }, - task { Currency.getInstance("USD") } - ) - val result = promise.get() - - Assert.assertEquals(1L, result.first) - Assert.assertEquals("Hello", result.second) - Assert.assertEquals(Currency.getInstance("USD"), result.third) - } -} diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kovenant/KovenantTimeoutTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/kovenant/KovenantTimeoutTest.kt deleted file mode 100644 index d98f9c538f..0000000000 --- a/kotlin-libraries-2/src/test/kotlin/com/baeldung/kovenant/KovenantTimeoutTest.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.baeldung.kovenant - -import nl.komponents.kovenant.Promise -import nl.komponents.kovenant.any -import nl.komponents.kovenant.task -import org.junit.Assert -import org.junit.Ignore -import org.junit.Test - -@Ignore -// Note that this can not run in the same test run if KovenantTest has already been executed -class KovenantTimeoutTest { - @Test - fun testTimeout() { - val promise = timedTask(1000) { "Hello" } - val result = promise.get() - Assert.assertEquals("Hello", result) - } - - @Test - fun testTimeoutExpired() { - val promise = timedTask(1000) { - Thread.sleep(3000) - "Hello" - } - val result = promise.get() - Assert.assertNull(result) - } - - fun timedTask(millis: Long, body: () -> T) : Promise> { - val timeoutTask = task { - Thread.sleep(millis) - null - } - val activeTask = task(body = body) - return any(activeTask, timeoutTask) - } -} diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/mockk/AnnotationMockKUnitTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/mockk/AnnotationMockKUnitTest.kt deleted file mode 100644 index 56cd8b43eb..0000000000 --- a/kotlin-libraries-2/src/test/kotlin/com/baeldung/mockk/AnnotationMockKUnitTest.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.baeldung.mockk - -import io.mockk.MockKAnnotations -import io.mockk.every -import io.mockk.impl.annotations.InjectMockKs -import io.mockk.impl.annotations.MockK -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import kotlin.test.assertEquals - -class InjectTestService { - lateinit var service1: TestableService - lateinit var service2: TestableService - - fun invokeService1(): String { - return service1.getDataFromDb("Test Param") - } -} - -class AnnotationMockKUnitTest { - - @MockK - lateinit var service1: TestableService - - @MockK - lateinit var service2: TestableService - - @InjectMockKs - var objectUnderTest = InjectTestService() - - @BeforeEach - fun setUp() = MockKAnnotations.init(this) - - @Test - fun givenServiceMock_whenCallingMockedMethod_thenCorrectlyVerified() { - // given - every { service1.getDataFromDb("Test Param") } returns "No" - // when - val result = objectUnderTest.invokeService1() - // then - assertEquals("No", result) - } - -} \ No newline at end of file diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/mockk/BasicMockKUnitTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/mockk/BasicMockKUnitTest.kt deleted file mode 100644 index df4c03be09..0000000000 --- a/kotlin-libraries-2/src/test/kotlin/com/baeldung/mockk/BasicMockKUnitTest.kt +++ /dev/null @@ -1,92 +0,0 @@ -package com.baeldung.mockk - -import io.mockk.* -import org.junit.jupiter.api.Test -import kotlin.test.assertEquals - - -class BasicMockKUnitTest { - - @Test - fun givenServiceMock_whenCallingMockedMethod_thenCorrectlyVerified() { - // given - val service = mockk() - every { service.getDataFromDb("Expected Param") } returns "Expected Output" - // when - val result = service.getDataFromDb("Expected Param") - // then - verify { service.getDataFromDb("Expected Param") } - assertEquals("Expected Output", result) - } - - @Test - fun givenServiceSpy_whenMockingOnlyOneMethod_thenOtherMethodsShouldBehaveAsOriginalObject() { - // given - val service = spyk() - every { service.getDataFromDb(any()) } returns "Mocked Output" - // when checking mocked method - val firstResult = service.getDataFromDb("Any Param") - // then - assertEquals("Mocked Output", firstResult) - // when checking not mocked method - val secondResult = service.doSomethingElse("Any Param") - // then - assertEquals("I don't want to!", secondResult) - } - - @Test - fun givenRelaxedMock_whenCallingNotMockedMethod_thenReturnDefaultValue() { - // given - val service = mockk(relaxed = true) - // when - val result = service.getDataFromDb("Any Param") - // then - assertEquals("", result) - } - - @Test - fun givenObject_whenMockingIt_thenMockedMethodShouldReturnProperValue() { - // given - val service = TestableService() - mockkObject(service) - // when calling not mocked method - val firstResult = service.getDataFromDb("Any Param") - // then return real response - assertEquals("Value from DB", firstResult) - - // when calling mocked method - every { service.getDataFromDb(any()) } returns "Mocked Output" - val secondResult = service.getDataFromDb("Any Param") - // then return mocked response - assertEquals("Mocked Output", secondResult) - } - - @Test - fun givenMock_whenCapturingParamValue_thenProperValueShouldBeCaptured() { - // given - val service = mockk() - val slot = slot() - every { service.getDataFromDb(capture(slot)) } returns "Expected Output" - // when - service.getDataFromDb("Expected Param") - // then - assertEquals("Expected Param", slot.captured) - } - - @Test - fun givenMock_whenCapturingParamsValues_thenProperValuesShouldBeCaptured() { - // given - val service = mockk() - val list = mutableListOf() - every { service.getDataFromDb(capture(list)) } returns "Expected Output" - // when - service.getDataFromDb("Expected Param 1") - service.getDataFromDb("Expected Param 2") - // then - assertEquals(2, list.size) - assertEquals("Expected Param 1", list[0]) - assertEquals("Expected Param 2", list[1]) - } - - -} \ No newline at end of file diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/mockk/HierarchicalMockKUnitTest.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/mockk/HierarchicalMockKUnitTest.kt deleted file mode 100644 index e9ef133663..0000000000 --- a/kotlin-libraries-2/src/test/kotlin/com/baeldung/mockk/HierarchicalMockKUnitTest.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.baeldung.mockk - -import io.mockk.* -import org.junit.jupiter.api.Test -import kotlin.test.assertEquals - -class Foo { - lateinit var name: String - lateinit var bar: Bar -} - -class Bar { - lateinit var nickname: String -} - -class HierarchicalMockKUnitTest { - - @Test - fun givenHierarchicalClass_whenMockingIt_thenReturnProperValue() { - // given - val foo = mockk { - every { name } returns "Karol" - every { bar } returns mockk { - every { nickname } returns "Tomato" - } - } - // when - val result = foo.bar.nickname - // then - assertEquals("Tomato", result) - } - -} \ No newline at end of file diff --git a/kotlin-libraries-2/src/test/kotlin/com/baeldung/mockk/TestableService.kt b/kotlin-libraries-2/src/test/kotlin/com/baeldung/mockk/TestableService.kt deleted file mode 100644 index d6f57e5fb0..0000000000 --- a/kotlin-libraries-2/src/test/kotlin/com/baeldung/mockk/TestableService.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.mockk - -class TestableService { - fun getDataFromDb(testParameter: String): String { - // query database and return matching value - return "Value from DB" - } - - fun doSomethingElse(testParameter: String): String { - return "I don't want to!" - } -} \ No newline at end of file diff --git a/kotlin-libraries/.gitignore b/kotlin-libraries/.gitignore deleted file mode 100644 index 0c017e8f8c..0000000000 --- a/kotlin-libraries/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -/bin/ - -#ignore gradle -.gradle/ - - -#ignore build and generated files -build/ -node/ -out/ - -#ignore installed node modules and package lock file -node_modules/ -package-lock.json diff --git a/kotlin-libraries/README.md b/kotlin-libraries/README.md deleted file mode 100644 index 570bf9b1e5..0000000000 --- a/kotlin-libraries/README.md +++ /dev/null @@ -1,16 +0,0 @@ -## Kotlin Libraries - -This module contains articles about Kotlin Libraries. - -### Relevant articles: - -- [Kotlin with Mockito](https://www.baeldung.com/kotlin-mockito) -- [HTTP Requests with Kotlin and khttp](https://www.baeldung.com/kotlin-khttp) -- [Kotlin Dependency Injection with Kodein](https://www.baeldung.com/kotlin-kodein-dependency-injection) -- [Writing Specifications with Kotlin and Spek](https://www.baeldung.com/kotlin-spek) -- [Processing JSON with Kotlin and Klaxson](https://www.baeldung.com/kotlin-json-klaxson) -- [Guide to the Kotlin Exposed Framework](https://www.baeldung.com/kotlin-exposed-persistence) -- [Introduction to Arrow in Kotlin](https://www.baeldung.com/kotlin-arrow) -- [Kotlin with Ktor](https://www.baeldung.com/kotlin-ktor) -- [REST API With Kotlin and Kovert](https://www.baeldung.com/kotlin-kovert) -- More articles: [[next -->]](/kotlin-libraries-2) diff --git a/kotlin-libraries/build.gradle b/kotlin-libraries/build.gradle deleted file mode 100644 index db23a438a0..0000000000 --- a/kotlin-libraries/build.gradle +++ /dev/null @@ -1,62 +0,0 @@ - - -group 'com.baeldung.ktor' -version '1.0-SNAPSHOT' - - -buildscript { - ext.kotlin_version = '1.2.41' - ext.ktor_version = '0.9.2' - ext.khttp_version = '0.1.0' - - repositories { - mavenCentral() - } - dependencies { - - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -apply plugin: 'java' -apply plugin: 'kotlin' -apply plugin: 'application' - -mainClassName = 'APIServer.kt' - -sourceCompatibility = 1.8 -compileKotlin { kotlinOptions.jvmTarget = "1.8" } -compileTestKotlin { kotlinOptions.jvmTarget = "1.8" } - -kotlin { experimental { coroutines "enable" } } - -repositories { - mavenCentral() - jcenter() - maven { url "https://dl.bintray.com/kotlin/ktor" } -} -sourceSets { - main{ - kotlin{ - srcDirs 'com/baeldung/ktor' - } - } - -} - -dependencies { - compile "io.ktor:ktor-server-netty:$ktor_version" - compile "ch.qos.logback:logback-classic:1.2.1" - compile "io.ktor:ktor-gson:$ktor_version" - compile "khttp:khttp:$khttp_version" - testCompile group: 'junit', name: 'junit', version: '4.12' - testCompile group: 'org.jetbrains.spek', name: 'spek-api', version: '1.1.5' - testCompile group: 'org.jetbrains.spek', name: 'spek-subject-extension', version: '1.1.5' - testCompile group: 'org.jetbrains.spek', name: 'spek-junit-platform-engine', version: '1.1.5' - implementation 'com.beust:klaxon:3.0.1' -} - -task runServer(type: JavaExec) { - main = 'APIServer' - classpath = sourceSets.main.runtimeClasspath -} diff --git a/kotlin-libraries/gradle/wrapper/gradle-wrapper.jar b/kotlin-libraries/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 01b8bf6b1f..0000000000 Binary files a/kotlin-libraries/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/kotlin-libraries/gradle/wrapper/gradle-wrapper.properties b/kotlin-libraries/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 933b6473ce..0000000000 --- a/kotlin-libraries/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-bin.zip diff --git a/kotlin-libraries/gradlew b/kotlin-libraries/gradlew deleted file mode 100644 index cccdd3d517..0000000000 --- a/kotlin-libraries/gradlew +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env sh - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn () { - echo "$*" -} - -die () { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - -exec "$JAVACMD" "$@" diff --git a/kotlin-libraries/gradlew.bat b/kotlin-libraries/gradlew.bat deleted file mode 100644 index f9553162f1..0000000000 --- a/kotlin-libraries/gradlew.bat +++ /dev/null @@ -1,84 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/kotlin-libraries/pom.xml b/kotlin-libraries/pom.xml deleted file mode 100644 index 908a545ae3..0000000000 --- a/kotlin-libraries/pom.xml +++ /dev/null @@ -1,171 +0,0 @@ - - - 4.0.0 - kotlin-libraries - kotlin-libraries - jar - - - com.baeldung - parent-kotlin - 1.0.0-SNAPSHOT - ../parent-kotlin - - - - - exposed - exposed - https://dl.bintray.com/kotlin/exposed - - - - false - - kotlinx - bintray - https://dl.bintray.com/kotlin/kotlinx - - - - - - org.jetbrains.spek - spek-api - ${spek.version} - test - - - org.jetbrains.spek - spek-subject-extension - ${spek.version} - test - - - org.jetbrains.spek - spek-junit-platform-engine - ${spek.version} - test - - - org.apache.commons - commons-math3 - ${commons-math3.version} - - - org.junit.platform - junit-platform-runner - test - - - khttp - khttp - ${khttp.version} - - - com.nhaarman - mockito-kotlin - ${mockito-kotlin.version} - test - - - com.github.salomonbrys.kodein - kodein - ${kodein.version} - - - org.assertj - assertj-core - test - - - com.beust - klaxon - ${klaxon.version} - - - org.jetbrains.exposed - exposed - ${exposed.version} - - - com.h2database - h2 - - - - io.arrow-kt - arrow-core - ${arrow-core.version} - - - - uy.kohesive.kovert - kovert-vertx - [1.5.0,1.6.0) - - - nl.komponents.kovenant - kovenant - - - - - nl.komponents.kovenant - kovenant - ${kovenant.version} - pom - - - - - junit - junit - test - - - - - net.bytebuddy - byte-buddy - compile - - - net.bytebuddy - byte-buddy-agent - compile - - - org.objenesis - objenesis - ${objenesis.version} - compile - - - - io.reactivex.rxjava2 - rxkotlin - ${rxkotlin.version} - - - - - 1.5.0 - 4.1.0 - 3.0.4 - 0.1.0 - 3.6.1 - 1.1.1 - 5.2.0 - 3.10.0 - 0.10.4 - 3.3.0 - 1.8.13 - 2.6 - 2.3.0 - 0.7.3 - 1.1.5 - - - diff --git a/kotlin-libraries/resources/logback.xml b/kotlin-libraries/resources/logback.xml deleted file mode 100644 index 9452207268..0000000000 --- a/kotlin-libraries/resources/logback.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - \ No newline at end of file diff --git a/kotlin-libraries/settings.gradle b/kotlin-libraries/settings.gradle deleted file mode 100644 index c91c993971..0000000000 --- a/kotlin-libraries/settings.gradle +++ /dev/null @@ -1,2 +0,0 @@ -rootProject.name = 'KtorWithKotlin' - diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/CustomProduct.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/CustomProduct.kt deleted file mode 100644 index cc46c65f96..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/CustomProduct.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.baeldung.klaxon - -import com.beust.klaxon.Json - -class CustomProduct( - @Json(name = "productName") - val name: String, - @Json(ignored = true) - val id: Int) \ No newline at end of file diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/Product.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/Product.kt deleted file mode 100644 index 09bcbc8722..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/Product.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.klaxon - -class Product(val name: String) \ No newline at end of file diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/ProductData.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/ProductData.kt deleted file mode 100644 index 1f30f26ce9..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/klaxon/ProductData.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.klaxon - -data class ProductData(val name: String, val capacityInGb: Int) \ No newline at end of file diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEither.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEither.kt deleted file mode 100644 index 75dfb9a2a4..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEither.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.baeldung.kotlin.arrow - -import arrow.core.Either -import arrow.core.filterOrElse -import kotlin.math.sqrt - -class FunctionalErrorHandlingWithEither { - - sealed class ComputeProblem { - object OddNumber : ComputeProblem() - object NotANumber : ComputeProblem() - } - - fun parseInput(s : String) : Either = Either.cond(s.toIntOrNull() != null, {-> s.toInt()}, {->ComputeProblem.NotANumber} ) - - fun isEven(x : Int) : Boolean = x % 2 == 0 - - fun biggestDivisor(x: Int) : Int = biggestDivisor(x, 2) - - fun biggestDivisor(x : Int, y : Int) : Int { - if(x == y){ - return 1; - } - if(x % y == 0){ - return x / y; - } - return biggestDivisor(x, y+1) - } - - fun isSquareNumber(x : Int) : Boolean { - val sqrt: Double = sqrt(x.toDouble()) - return sqrt % 1.0 == 0.0 - } - - fun computeWithEither(input : String) : Either { - return parseInput(input) - .filterOrElse(::isEven) {->ComputeProblem.OddNumber} - .map (::biggestDivisor) - .map (::isSquareNumber) - } - - fun computeWithEitherClient(input : String) { - val computeWithEither = computeWithEither(input) - - when(computeWithEither){ - is Either.Right -> "The greatest divisor is square number: ${computeWithEither.b}" - is Either.Left -> when(computeWithEither.a){ - is ComputeProblem.NotANumber -> "Wrong input! Not a number!" - is ComputeProblem.OddNumber -> "It is an odd number!" - } - } - } - -} \ No newline at end of file diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOption.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOption.kt deleted file mode 100644 index 5fddd1d88e..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOption.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.baeldung.kotlin.arrow - -import arrow.core.None -import arrow.core.Option -import arrow.core.Some -import kotlin.math.sqrt - -class FunctionalErrorHandlingWithOption { - - fun parseInput(s : String) : Option = Option.fromNullable(s.toIntOrNull()) - - fun isEven(x : Int) : Boolean = x % 2 == 0 - - fun biggestDivisor(x: Int) : Int = biggestDivisor(x, 2) - - fun biggestDivisor(x : Int, y : Int) : Int { - if(x == y){ - return 1; - } - if(x % y == 0){ - return x / y; - } - return biggestDivisor(x, y+1) - } - - fun isSquareNumber(x : Int) : Boolean { - val sqrt: Double = sqrt(x.toDouble()) - return sqrt % 1.0 == 0.0 - } - - fun computeWithOption(input : String) : Option { - return parseInput(input) - .filter(::isEven) - .map(::biggestDivisor) - .map(::isSquareNumber) - } - - fun computeWithOptionClient(input : String) : String{ - val computeOption = computeWithOption(input) - - return when(computeOption){ - is None -> "Not an even number!" - is Some -> "The greatest divisor is square number: ${computeOption.t}" - } - } -} \ No newline at end of file diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Controller.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Controller.kt deleted file mode 100644 index 721bdb04bc..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Controller.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.kotlin.kodein - -class Controller(private val service : Service) \ No newline at end of file diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Dao.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Dao.kt deleted file mode 100644 index a0be7ef0e0..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Dao.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.kotlin.kodein - -interface Dao \ No newline at end of file diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/JdbcDao.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/JdbcDao.kt deleted file mode 100644 index 0a09b95dbf..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/JdbcDao.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.kotlin.kodein - -class JdbcDao : Dao \ No newline at end of file diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/MongoDao.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/MongoDao.kt deleted file mode 100644 index 06436fcd21..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/MongoDao.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.kotlin.kodein - -class MongoDao : Dao \ No newline at end of file diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Service.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Service.kt deleted file mode 100644 index bb24a5cc21..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/kodein/Service.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.kotlin.kodein - -class Service(private val dao: Dao, private val tag: String) \ No newline at end of file diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/mockito/BookService.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/mockito/BookService.kt deleted file mode 100644 index 993ee555af..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/mockito/BookService.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.baeldung.kotlin - -interface BookService { - fun inStock(bookId: Int): Boolean - fun lend(bookId: Int, memberId: Int) -} \ No newline at end of file diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/mockito/LendBookManager.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/mockito/LendBookManager.kt deleted file mode 100644 index 5a4718162a..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kotlin/mockito/LendBookManager.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.kotlin - -class LendBookManager(val bookService:BookService) { - fun checkout(bookId: Int, memberId: Int) { - if(bookService.inStock(bookId)) { - bookService.lend(bookId, memberId) - } else { - throw IllegalStateException("Book is not available") - } - } -} diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt deleted file mode 100644 index da2bbe4208..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/AnnotatedServer.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.baeldung.kovert - -import io.vertx.ext.web.Router -import io.vertx.ext.web.RoutingContext -import nl.komponents.kovenant.functional.bind -import org.kodein.di.Kodein -import org.kodein.di.conf.global -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import uy.klutter.config.typesafe.ClassResourceConfig -import uy.klutter.config.typesafe.ReferenceConfig -import uy.klutter.config.typesafe.kodein.importConfig -import uy.klutter.config.typesafe.loadConfig -import uy.klutter.vertx.kodein.KodeinVertx -import uy.kohesive.kovert.core.HttpVerb -import uy.kohesive.kovert.core.Location -import uy.kohesive.kovert.core.Verb -import uy.kohesive.kovert.core.VerbAlias -import uy.kohesive.kovert.vertx.bindController -import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx -import uy.kohesive.kovert.vertx.boot.KovertVerticle -import uy.kohesive.kovert.vertx.boot.KovertVerticleModule -import uy.kohesive.kovert.vertx.boot.KovertVertx - - -class AnnotatedServer { - companion object { - private val LOG: Logger = LoggerFactory.getLogger(AnnotatedServer::class.java) - - @JvmStatic - fun main(args: Array) { - AnnotatedServer().start() - } - } - - @VerbAlias("show", HttpVerb.GET) - class AnnotatedController { - fun RoutingContext.showStringById(id: String) = id - - @Verb(HttpVerb.GET) - @Location("/ping/:id") - fun RoutingContext.ping(id: String) = id - } - - fun start() { - Kodein.global.addImport(Kodein.Module { - importConfig(loadConfig(ClassResourceConfig("/kovert.conf", AnnotatedServer::class.java), ReferenceConfig())) { - import("kovert.vertx", KodeinKovertVertx.configModule) - import("kovert.server", KovertVerticleModule.configModule) - } - - // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j - import(KodeinVertx.moduleWithLoggingToSlf4j) - // Kovert boot - import(KodeinKovertVertx.module) - import(KovertVerticleModule.module) - }) - - val initControllers = fun Router.() { - bindController(AnnotatedController(), "api") - } - - // startup asynchronously... - KovertVertx.start() bind { vertx -> - KovertVerticle.deploy(vertx, routerInit = initControllers) - } success { deploymentId -> - LOG.warn("Deployment complete.") - } fail { error -> - LOG.error("Deployment failed!", error) - } - - } -} diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt deleted file mode 100644 index a596391ed8..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/ErrorServer.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.baeldung.kovert - -import io.vertx.ext.web.Router -import io.vertx.ext.web.RoutingContext -import nl.komponents.kovenant.functional.bind -import org.kodein.di.Kodein -import org.kodein.di.conf.global -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import uy.klutter.config.typesafe.ClassResourceConfig -import uy.klutter.config.typesafe.ReferenceConfig -import uy.klutter.config.typesafe.kodein.importConfig -import uy.klutter.config.typesafe.loadConfig -import uy.klutter.vertx.kodein.KodeinVertx -import uy.kohesive.kovert.core.HttpErrorCode -import uy.kohesive.kovert.core.HttpErrorCodeWithBody -import uy.kohesive.kovert.core.HttpErrorForbidden -import uy.kohesive.kovert.vertx.bindController -import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx -import uy.kohesive.kovert.vertx.boot.KovertVerticle -import uy.kohesive.kovert.vertx.boot.KovertVerticleModule -import uy.kohesive.kovert.vertx.boot.KovertVertx - - -class ErrorServer { - companion object { - private val LOG: Logger = LoggerFactory.getLogger(ErrorServer::class.java) - - @JvmStatic - fun main(args: Array) { - ErrorServer().start() - } - } - - class ErrorController { - fun RoutingContext.getForbidden() { - throw HttpErrorForbidden() - } - fun RoutingContext.getError() { - throw HttpErrorCode("Something went wrong", 590) - } - fun RoutingContext.getErrorbody() { - throw HttpErrorCodeWithBody("Something went wrong", 591, "Body here") - } - } - - fun start() { - Kodein.global.addImport(Kodein.Module { - importConfig(loadConfig(ClassResourceConfig("/kovert.conf", ErrorServer::class.java), ReferenceConfig())) { - import("kovert.vertx", KodeinKovertVertx.configModule) - import("kovert.server", KovertVerticleModule.configModule) - } - - // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j - import(KodeinVertx.moduleWithLoggingToSlf4j) - // Kovert boot - import(KodeinKovertVertx.module) - import(KovertVerticleModule.module) - }) - - val initControllers = fun Router.() { - bindController(ErrorController(), "api") - } - - // startup asynchronously... - KovertVertx.start() bind { vertx -> - KovertVerticle.deploy(vertx, routerInit = initControllers) - } success { deploymentId -> - LOG.warn("Deployment complete.") - } fail { error -> - LOG.error("Deployment failed!", error) - } - - } -} diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/JsonServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/JsonServer.kt deleted file mode 100644 index 310fe2a7a0..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/JsonServer.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.baeldung.kovert - -import com.fasterxml.jackson.annotation.JsonProperty -import io.vertx.ext.web.Router -import io.vertx.ext.web.RoutingContext -import nl.komponents.kovenant.functional.bind -import org.kodein.di.Kodein -import org.kodein.di.conf.global -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import uy.klutter.config.typesafe.ClassResourceConfig -import uy.klutter.config.typesafe.ReferenceConfig -import uy.klutter.config.typesafe.kodein.importConfig -import uy.klutter.config.typesafe.loadConfig -import uy.klutter.vertx.kodein.KodeinVertx -import uy.kohesive.kovert.vertx.bindController -import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx -import uy.kohesive.kovert.vertx.boot.KovertVerticle -import uy.kohesive.kovert.vertx.boot.KovertVerticleModule -import uy.kohesive.kovert.vertx.boot.KovertVertx - -class JsonServer { - companion object { - private val LOG: Logger = LoggerFactory.getLogger(JsonServer::class.java) - - @JvmStatic - fun main(args: Array) { - JsonServer().start() - } - } - - data class Person( - @JsonProperty("_id") - val id: String, - val name: String, - val job: String - ) - - class JsonController { - fun RoutingContext.getPersonById(id: String) = Person( - id = id, - name = "Tony Stark", - job = "Iron Man" - ) - fun RoutingContext.putPersonById(id: String, person: Person) = person - } - - fun start() { - Kodein.global.addImport(Kodein.Module { - importConfig(loadConfig(ClassResourceConfig("/kovert.conf", JsonServer::class.java), ReferenceConfig())) { - import("kovert.vertx", KodeinKovertVertx.configModule) - import("kovert.server", KovertVerticleModule.configModule) - } - - // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j - import(KodeinVertx.moduleWithLoggingToSlf4j) - // Kovert boot - import(KodeinKovertVertx.module) - import(KovertVerticleModule.module) - }) - - val initControllers = fun Router.() { - bindController(JsonController(), "api") - } - - // startup asynchronously... - KovertVertx.start() bind { vertx -> - KovertVerticle.deploy(vertx, routerInit = initControllers) - } success { deploymentId -> - LOG.warn("Deployment complete.") - } fail { error -> - LOG.error("Deployment failed!", error) - } - - } -} diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/NoopServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/NoopServer.kt deleted file mode 100644 index 98ce775e66..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/NoopServer.kt +++ /dev/null @@ -1,57 +0,0 @@ -package com.baeldung.kovert - -import io.vertx.ext.web.Router -import nl.komponents.kovenant.functional.bind -import org.kodein.di.Kodein -import org.kodein.di.conf.global -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import uy.klutter.config.typesafe.ClassResourceConfig -import uy.klutter.config.typesafe.ReferenceConfig -import uy.klutter.config.typesafe.kodein.importConfig -import uy.klutter.config.typesafe.loadConfig -import uy.klutter.vertx.kodein.KodeinVertx -import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx -import uy.kohesive.kovert.vertx.boot.KovertVerticle -import uy.kohesive.kovert.vertx.boot.KovertVerticleModule -import uy.kohesive.kovert.vertx.boot.KovertVertx - -class NoopServer { - companion object { - private val LOG: Logger = LoggerFactory.getLogger(NoopServer::class.java) - - @JvmStatic - fun main(args: Array) { - NoopServer().start() - } - } - - - fun start() { - Kodein.global.addImport(Kodein.Module { - importConfig(loadConfig(ClassResourceConfig("/kovert.conf", NoopServer::class.java), ReferenceConfig())) { - import("kovert.vertx", KodeinKovertVertx.configModule) - import("kovert.server", KovertVerticleModule.configModule) - } - - // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j - import(KodeinVertx.moduleWithLoggingToSlf4j) - // Kovert boot - import(KodeinKovertVertx.module) - import(KovertVerticleModule.module) - }) - - val initControllers = fun Router.() { - } - - // startup asynchronously... - KovertVertx.start() bind { vertx -> - KovertVerticle.deploy(vertx, routerInit = initControllers) - } success { deploymentId -> - LOG.warn("Deployment complete.") - } fail { error -> - LOG.error("Deployment failed!", error) - } - - } -} diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt deleted file mode 100644 index 86ca482808..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SecuredServer.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.baeldung.kovert - -import io.vertx.ext.web.Router -import io.vertx.ext.web.RoutingContext -import nl.komponents.kovenant.functional.bind -import org.kodein.di.Kodein -import org.kodein.di.conf.global -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import uy.klutter.config.typesafe.ClassResourceConfig -import uy.klutter.config.typesafe.ReferenceConfig -import uy.klutter.config.typesafe.kodein.importConfig -import uy.klutter.config.typesafe.loadConfig -import uy.klutter.vertx.kodein.KodeinVertx -import uy.kohesive.kovert.vertx.bindController -import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx -import uy.kohesive.kovert.vertx.boot.KovertVerticle -import uy.kohesive.kovert.vertx.boot.KovertVerticleModule -import uy.kohesive.kovert.vertx.boot.KovertVertx - - -class SecuredServer { - companion object { - private val LOG: Logger = LoggerFactory.getLogger(SecuredServer::class.java) - - @JvmStatic - fun main(args: Array) { - SecuredServer().start() - } - } - - class SecuredContext(private val routingContext: RoutingContext) { - val authenticated = routingContext.request().getHeader("Authorization") == "Secure" - } - - class SecuredController { - fun SecuredContext.getSecured() = this.authenticated - } - - fun start() { - Kodein.global.addImport(Kodein.Module { - importConfig(loadConfig(ClassResourceConfig("/kovert.conf", SecuredServer::class.java), ReferenceConfig())) { - import("kovert.vertx", KodeinKovertVertx.configModule) - import("kovert.server", KovertVerticleModule.configModule) - } - - // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j - import(KodeinVertx.moduleWithLoggingToSlf4j) - // Kovert boot - import(KodeinKovertVertx.module) - import(KovertVerticleModule.module) - }) - - val initControllers = fun Router.() { - bindController(SecuredController(), "api") - } - - // startup asynchronously... - KovertVertx.start() bind { vertx -> - KovertVerticle.deploy(vertx, routerInit = initControllers) - } success { deploymentId -> - LOG.warn("Deployment complete.") - } fail { error -> - LOG.error("Deployment failed!", error) - } - - } -} diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt deleted file mode 100644 index 172469ab46..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/kovert/SimpleServer.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.baeldung.kovert - -import io.vertx.ext.web.Router -import io.vertx.ext.web.RoutingContext -import nl.komponents.kovenant.functional.bind -import org.kodein.di.Kodein -import org.kodein.di.conf.global -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import uy.klutter.config.typesafe.ClassResourceConfig -import uy.klutter.config.typesafe.ReferenceConfig -import uy.klutter.config.typesafe.kodein.importConfig -import uy.klutter.config.typesafe.loadConfig -import uy.klutter.vertx.kodein.KodeinVertx -import uy.kohesive.kovert.vertx.bindController -import uy.kohesive.kovert.vertx.boot.KodeinKovertVertx -import uy.kohesive.kovert.vertx.boot.KovertVerticle -import uy.kohesive.kovert.vertx.boot.KovertVerticleModule -import uy.kohesive.kovert.vertx.boot.KovertVertx - - -class SimpleServer { - companion object { - private val LOG: Logger = LoggerFactory.getLogger(SimpleServer::class.java) - - @JvmStatic - fun main(args: Array) { - SimpleServer().start() - } - } - - class SimpleController { - fun RoutingContext.getStringById(id: String) = id - fun RoutingContext.get_truncatedString_by_id(id: String, length: Int = 1) = id.subSequence(0, length) - } - - fun start() { - Kodein.global.addImport(Kodein.Module { - importConfig(loadConfig(ClassResourceConfig("/kovert.conf", SimpleServer::class.java), ReferenceConfig())) { - import("kovert.vertx", KodeinKovertVertx.configModule) - import("kovert.server", KovertVerticleModule.configModule) - } - - // includes jackson ObjectMapper to match compatibility with Vertx, app logging via Vertx facade to Slf4j - import(KodeinVertx.moduleWithLoggingToSlf4j) - // Kovert boot - import(KodeinKovertVertx.module) - import(KovertVerticleModule.module) - }) - - val initControllers = fun Router.() { - bindController(SimpleController(), "api") - } - - // startup asynchronously... - KovertVertx.start() bind { vertx -> - KovertVerticle.deploy(vertx, routerInit = initControllers) - } success { deploymentId -> - LOG.warn("Deployment complete.") - } fail { error -> - LOG.error("Deployment failed!", error) - } - - } -} diff --git a/kotlin-libraries/src/main/kotlin/com/baeldung/ktor/APIServer.kt b/kotlin-libraries/src/main/kotlin/com/baeldung/ktor/APIServer.kt deleted file mode 100755 index a12182ccc8..0000000000 --- a/kotlin-libraries/src/main/kotlin/com/baeldung/ktor/APIServer.kt +++ /dev/null @@ -1,73 +0,0 @@ -@file:JvmName("APIServer") - - -import io.ktor.application.call -import io.ktor.application.install -import io.ktor.features.CallLogging -import io.ktor.features.ContentNegotiation -import io.ktor.features.DefaultHeaders -import io.ktor.gson.gson -import io.ktor.request.path -import io.ktor.request.receive -import io.ktor.response.respond -import io.ktor.routing.* -import io.ktor.server.engine.embeddedServer -import io.ktor.server.netty.Netty -import org.slf4j.event.Level - -data class Author(val name: String, val website: String) -data class ToDo(var id: Int, val name: String, val description: String, val completed: Boolean) - -fun main(args: Array) { - - val toDoList = ArrayList(); - val jsonResponse = """{ - "id": 1, - "task": "Pay waterbill", - "description": "Pay water bill today", - }""" - - - embeddedServer(Netty, 8080) { - install(DefaultHeaders) { - header("X-Developer", "Baeldung") - } - install(CallLogging) { - level = Level.DEBUG - filter { call -> call.request.path().startsWith("/todo") } - filter { call -> call.request.path().startsWith("/author") } - } - install(ContentNegotiation) { - gson { - setPrettyPrinting() - } - } - routing() { - route("/todo") { - post { - var toDo = call.receive(); - toDo.id = toDoList.size; - toDoList.add(toDo); - call.respond("Added") - - } - delete("/{id}") { - call.respond(toDoList.removeAt(call.parameters["id"]!!.toInt())); - } - get("/{id}") { - - call.respond(toDoList[call.parameters["id"]!!.toInt()]); - } - get { - call.respond(toDoList); - } - } - get("/author"){ - call.respond(Author("Baeldung","baeldung.com")); - - } - - - } - }.start(wait = true) -} \ No newline at end of file diff --git a/kotlin-libraries/src/main/resources/kovert.conf b/kotlin-libraries/src/main/resources/kovert.conf deleted file mode 100644 index 3b08641693..0000000000 --- a/kotlin-libraries/src/main/resources/kovert.conf +++ /dev/null @@ -1,15 +0,0 @@ -{ - kovert: { - vertx: { - clustered: false - } - server: { - listeners: [ - { - host: "0.0.0.0" - port: "8000" - } - ] - } - } -} diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/klaxon/KlaxonUnitTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/klaxon/KlaxonUnitTest.kt deleted file mode 100644 index 2a7d44a163..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/klaxon/KlaxonUnitTest.kt +++ /dev/null @@ -1,163 +0,0 @@ -package com.baeldung.klaxon - -import com.beust.klaxon.JsonArray -import com.beust.klaxon.JsonObject -import com.beust.klaxon.JsonReader -import com.beust.klaxon.Klaxon -import com.beust.klaxon.Parser -import com.beust.klaxon.PathMatcher -import org.assertj.core.api.Assertions.assertThat -import org.assertj.core.api.SoftAssertions.assertSoftly -import org.junit.Assert -import org.junit.jupiter.api.Test -import java.io.StringReader -import java.util.regex.Pattern - -class KlaxonUnitTest { - - @Test - fun giveProduct_whenSerialize_thenGetJsonString() { - val product = Product("HDD") - val result = Klaxon().toJsonString(product) - - assertThat(result).isEqualTo("""{"name" : "HDD"}""") - } - - @Test - fun giveJsonString_whenDeserialize_thenGetProduct() { - val result = Klaxon().parse(""" - { - "name" : "RAM" - } - """) - - assertThat(result?.name).isEqualTo("RAM") - } - - @Test - fun giveCustomProduct_whenSerialize_thenGetJsonString() { - val product = CustomProduct("HDD", 1) - val result = Klaxon().toJsonString(product) - - assertThat(result).isEqualTo("""{"productName" : "HDD"}""") - } - - @Test - fun giveJsonArray_whenStreaming_thenGetProductArray() { - val jsonArray = """ - [ - { "name" : "HDD", "capacityInGb" : 512 }, - { "name" : "RAM", "capacityInGb" : 16 } - ]""" - val expectedArray = arrayListOf(ProductData("HDD", 512), - ProductData("RAM", 16)) - val klaxon = Klaxon() - val productArray = arrayListOf() - JsonReader(StringReader(jsonArray)).use { reader -> - reader.beginArray { - while (reader.hasNext()) { - val product = klaxon.parse(reader) - productArray.add(product!!) - } - } - } - - assertThat(productArray).hasSize(2).isEqualTo(expectedArray) - } - - @Test - fun giveJsonString_whenParser_thenGetJsonObject() { - val jsonString = StringBuilder(""" - { - "name" : "HDD", - "capacityInGb" : 512, - "sizeInInch" : 2.5 - } - """) - val parser = Parser() - val json = parser.parse(jsonString) as JsonObject - - assertThat(json).hasSize(3).containsEntry("name", "HDD").containsEntry("capacityInGb", 512).containsEntry("sizeInInch", 2.5) - } - - @Suppress("UNCHECKED_CAST") - @Test - fun giveJsonStringArray_whenParser_thenGetJsonArray() { - val jsonString = StringBuilder(""" - [ - { "name" : "SDD" }, - { "madeIn" : "Taiwan" }, - { "warrantyInYears" : 5 } - ]""") - val parser = Parser() - val json = parser.parse(jsonString) as JsonArray - - assertSoftly({ softly -> - softly.assertThat(json).hasSize(3) - softly.assertThat(json[0]["name"]).isEqualTo("SDD") - softly.assertThat(json[1]["madeIn"]).isEqualTo("Taiwan") - softly.assertThat(json[2]["warrantyInYears"]).isEqualTo(5) - }) - } - - @Test - fun givenJsonString_whenStreaming_thenProcess() { - val jsonString = """ - { - "name" : "HDD", - "madeIn" : "Taiwan", - "warrantyInYears" : 5 - "hasStock" : true - "capacitiesInTb" : [ 1, 2 ], - "features" : { "cacheInMb" : 64, "speedInRpm" : 7200 } - }""" - - JsonReader(StringReader(jsonString)).use { reader -> - reader.beginObject { - while (reader.hasNext()) { - val readName = reader.nextName() - when (readName) { - "name" -> assertThat(reader.nextString()).isEqualTo("HDD") - "madeIn" -> assertThat(reader.nextString()).isEqualTo("Taiwan") - "warrantyInYears" -> assertThat(reader.nextInt()).isEqualTo(5) - "hasStock" -> assertThat(reader.nextBoolean()).isEqualTo(true) - "capacitiesInTb" -> assertThat(reader.nextArray()).contains(1, 2) - "features" -> assertThat(reader.nextObject()).containsEntry("cacheInMb", 64).containsEntry("speedInRpm", 7200) - else -> Assert.fail("Unexpected name: $readName") - } - } - } - } - - } - - @Test - fun givenDiskInventory_whenRegexMatches_thenGetTypes() { - val jsonString = """ - { - "inventory" : { - "disks" : [ - { - "type" : "HDD", - "sizeInGb" : 1000 - }, - { - "type" : "SDD", - "sizeInGb" : 512 - } - ] - } - }""" - val pathMatcher = object : PathMatcher { - override fun pathMatches(path: String) = Pattern.matches(".*inventory.*disks.*type.*", path) - - override fun onMatch(path: String, value: Any) { - when (path) { - "$.inventory.disks[0].type" -> assertThat(value).isEqualTo("HDD") - "$.inventory.disks[1].type" -> assertThat(value).isEqualTo("SDD") - } - } - } - Klaxon().pathMatcher(pathMatcher).parseJsonObject(StringReader(jsonString)) - } -} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalDataTypes.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalDataTypes.kt deleted file mode 100644 index 692425ee07..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalDataTypes.kt +++ /dev/null @@ -1,143 +0,0 @@ -package com.baeldung.kotlin.arrow - -import arrow.core.* -import org.junit.Assert -import org.junit.Test - -class FunctionalDataTypes { - - @Test - fun whenIdCreated_thanValueIsPresent(){ - val id = Id("foo") - val justId = Id.just("foo"); - - Assert.assertEquals("foo", id.extract()) - Assert.assertEquals(justId, id) - } - - fun length(s : String) : Int = s.length - - fun isBigEnough(i : Int) : Boolean = i > 10 - - @Test - fun whenIdCreated_thanMapIsAssociative(){ - val foo = Id("foo") - - val map1 = foo.map(::length) - .map(::isBigEnough) - val map2 = foo.map { s -> isBigEnough(length(s)) } - - Assert.assertEquals(map1, map2) - } - - fun lengthId(s : String) : Id = Id.just(length(s)) - - fun isBigEnoughId(i : Int) : Id = Id.just(isBigEnough(i)) - - @Test - fun whenIdCreated_thanFlatMapIsAssociative(){ - val bar = Id("bar") - - val flatMap = bar.flatMap(::lengthId) - .flatMap(::isBigEnoughId) - val flatMap1 = bar.flatMap { s -> lengthId(s).flatMap(::isBigEnoughId) } - - Assert.assertEquals(flatMap, flatMap1) - } - - @Test - fun whenOptionCreated_thanValueIsPresent(){ - val factory = Option.just(42) - val constructor = Option(42) - val emptyOptional = Option.empty() - val fromNullable = Option.fromNullable(null) - - Assert.assertEquals(42, factory.getOrElse { -1 }) - Assert.assertEquals(factory, constructor) - Assert.assertEquals(emptyOptional, fromNullable) - } - - @Test - fun whenOptionCreated_thanConstructorDifferFromFactory(){ - val constructor : Option = Option(null) - val fromNullable : Option = Option.fromNullable(null) - - try{ - constructor.map { s -> s!!.length } - Assert.fail() - } catch (e : KotlinNullPointerException){ - fromNullable.map { s->s!!.length } - } - Assert.assertNotEquals(constructor, fromNullable) - } - - fun wrapper(x : Integer?) : Option = if (x == null) Option.just(-1) else Option.just(x.toInt()) - - @Test - fun whenOptionFromNullableCreated_thanItBreaksLeftIdentity(){ - val optionFromNull = Option.fromNullable(null) - - Assert.assertNotEquals(optionFromNull.flatMap(::wrapper), wrapper(null)) - } - - @Test - fun whenEitherCreated_thanOneValueIsPresent(){ - val rightOnly : Either = Either.right(42) - val leftOnly : Either = Either.left("foo") - - Assert.assertTrue(rightOnly.isRight()) - Assert.assertTrue(leftOnly.isLeft()) - Assert.assertEquals(42, rightOnly.getOrElse { -1 }) - Assert.assertEquals(-1, leftOnly.getOrElse { -1 }) - - Assert.assertEquals(0, rightOnly.map { it % 2 }.getOrElse { -1 }) - Assert.assertEquals(-1, leftOnly.map { it % 2 }.getOrElse { -1 }) - Assert.assertTrue(rightOnly.flatMap { Either.Right(it % 2) }.isRight()) - Assert.assertTrue(leftOnly.flatMap { Either.Right(it % 2) }.isLeft()) - } - - @Test - fun whenEvalNowUsed_thenMapEvaluatedLazily(){ - val now = Eval.now(1) - Assert.assertEquals(1, now.value()) - - var counter : Int = 0 - val map = now.map { x -> counter++; x+1 } - Assert.assertEquals(0, counter) - - val value = map.value() - Assert.assertEquals(2, value) - Assert.assertEquals(1, counter) - } - - @Test - fun whenEvalLaterUsed_theResultIsMemoized(){ - var counter : Int = 0 - val later = Eval.later { counter++; counter } - Assert.assertEquals(0, counter) - - val firstValue = later.value() - Assert.assertEquals(1, firstValue) - Assert.assertEquals(1, counter) - - val secondValue = later.value() - Assert.assertEquals(1, secondValue) - Assert.assertEquals(1, counter) - } - - @Test - fun whenEvalAlwaysUsed_theResultIsNotMemoized(){ - var counter : Int = 0 - val later = Eval.always { counter++; counter } - Assert.assertEquals(0, counter) - - val firstValue = later.value() - Assert.assertEquals(1, firstValue) - Assert.assertEquals(1, counter) - - val secondValue = later.value() - Assert.assertEquals(2, secondValue) - Assert.assertEquals(2, counter) - } - -} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEitherTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEitherTest.kt deleted file mode 100644 index 47fbf825a0..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithEitherTest.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.baeldung.kotlin.arrow - -import arrow.core.Either -import com.baeldung.kotlin.arrow.FunctionalErrorHandlingWithEither.ComputeProblem.NotANumber -import com.baeldung.kotlin.arrow.FunctionalErrorHandlingWithEither.ComputeProblem.OddNumber -import org.junit.Assert -import org.junit.Test - -class FunctionalErrorHandlingWithEitherTest { - - val operator = FunctionalErrorHandlingWithEither() - - @Test - fun givenInvalidInput_whenComputeInvoked_NotANumberIsPresent(){ - val computeWithEither = operator.computeWithEither("bar") - - Assert.assertTrue(computeWithEither.isLeft()) - when(computeWithEither){ - is Either.Left -> when(computeWithEither.a){ - NotANumber -> "Ok." - else -> Assert.fail() - } - else -> Assert.fail() - } - } - - @Test - fun givenOddNumberInput_whenComputeInvoked_OddNumberIsPresent(){ - val computeWithEither = operator.computeWithEither("121") - - Assert.assertTrue(computeWithEither.isLeft()) - when(computeWithEither){ - is Either.Left -> when(computeWithEither.a){ - OddNumber -> "Ok." - else -> Assert.fail() - } - else -> Assert.fail() - } - } - - @Test - fun givenEvenNumberWithoutSquare_whenComputeInvoked_OddNumberIsPresent(){ - val computeWithEither = operator.computeWithEither("100") - - Assert.assertTrue(computeWithEither.isRight()) - when(computeWithEither){ - is Either.Right -> when(computeWithEither.b){ - false -> "Ok." - else -> Assert.fail() - } - else -> Assert.fail() - } - } - - @Test - fun givenEvenNumberWithSquare_whenComputeInvoked_OddNumberIsPresent(){ - val computeWithEither = operator.computeWithEither("98") - - Assert.assertTrue(computeWithEither.isRight()) - when(computeWithEither){ - is Either.Right -> when(computeWithEither.b){ - true -> "Ok." - else -> Assert.fail() - } - else -> Assert.fail() - } - } -} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOptionTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOptionTest.kt deleted file mode 100644 index 3ca4cd033f..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/arrow/FunctionalErrorHandlingWithOptionTest.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.baeldung.kotlin.arrow - -import org.junit.Assert -import org.junit.Test - -class FunctionalErrorHandlingWithOptionTest { - - val operator = FunctionalErrorHandlingWithOption() - - @Test - fun givenInvalidInput_thenErrorMessageIsPresent(){ - val useComputeOption = operator.computeWithOptionClient("foo") - Assert.assertEquals("Not an even number!", useComputeOption) - } - - @Test - fun givenOddNumberInput_thenErrorMessageIsPresent(){ - val useComputeOption = operator.computeWithOptionClient("539") - Assert.assertEquals("Not an even number!",useComputeOption) - } - - @Test - fun givenEvenNumberInputWithNonSquareNum_thenFalseMessageIsPresent(){ - val useComputeOption = operator.computeWithOptionClient("100") - Assert.assertEquals("The greatest divisor is square number: false",useComputeOption) - } - - @Test - fun givenEvenNumberInputWithSquareNum_thenTrueMessageIsPresent(){ - val useComputeOption = operator.computeWithOptionClient("242") - Assert.assertEquals("The greatest divisor is square number: true",useComputeOption) - } - -} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/exposed/ExposedTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/exposed/ExposedTest.kt deleted file mode 100644 index 29fa18ef7a..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/exposed/ExposedTest.kt +++ /dev/null @@ -1,333 +0,0 @@ -package com.baeldung.kotlin.exposed - -import org.jetbrains.exposed.dao.* -import org.jetbrains.exposed.sql.* -import org.jetbrains.exposed.sql.transactions.TransactionManager -import org.jetbrains.exposed.sql.transactions.transaction -import org.junit.Test -import java.sql.DriverManager -import kotlin.test.* - -class ExposedTest { - - @Test - fun whenH2Database_thenConnectionSuccessful() { - val database = Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") - transaction { - assertEquals(1.4.toBigDecimal(), database.version) - assertEquals("h2", database.vendor) - } - } - - @Test - fun whenH2DatabaseWithCredentials_thenConnectionSuccessful() { - Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver", user = "myself", password = "secret") - } - - @Test - fun whenH2DatabaseWithManualConnection_thenConnectionSuccessful() { - var connected = false - Database.connect({ connected = true; DriverManager.getConnection("jdbc:h2:mem:test;MODE=MySQL") }) - assertEquals(false, connected) - transaction { - addLogger(StdOutSqlLogger) - assertEquals(false, connected) - SchemaUtils.create(Cities) - assertEquals(true, connected) - } - } - - @Test - fun whenManualCommit_thenOk() { - Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") - transaction { - assertTrue(this is Transaction) - commit() - commit() - commit() - } - } - - @Test - fun whenInsert_thenGeneratedKeys() { - Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") - transaction { - SchemaUtils.create(StarWarsFilms) - val id = StarWarsFilms.insertAndGetId { - it[name] = "The Last Jedi" - it[sequelId] = 8 - it[director] = "Rian Johnson" - } - assertEquals(1, id.value) - val insert = StarWarsFilms.insert { - it[name] = "The Force Awakens" - it[sequelId] = 7 - it[director] = "J.J. Abrams" - } - assertEquals(2, insert[StarWarsFilms.id]?.value) - val selectAll = StarWarsFilms.selectAll() - selectAll.forEach { - assertTrue { it[StarWarsFilms.sequelId] >= 7 } - } - StarWarsFilms.slice(StarWarsFilms.name, StarWarsFilms.director).selectAll() - .forEach { - assertTrue { it[StarWarsFilms.name].startsWith("The") } - } - val select = StarWarsFilms.select { (StarWarsFilms.director like "J.J.%") and (StarWarsFilms.sequelId eq 7) } - assertEquals(1, select.count()) - StarWarsFilms.update ({ StarWarsFilms.sequelId eq 8 }) { - it[name] = "Episode VIII – The Last Jedi" - with(SqlExpressionBuilder) { - it.update(StarWarsFilms.sequelId, StarWarsFilms.sequelId + 1) - } - } - } - } - - @Test - fun whenForeignKey_thenAutoJoin() { - Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") - transaction { - addLogger(StdOutSqlLogger) - SchemaUtils.create(StarWarsFilms, Players) - StarWarsFilms.insert { - it[name] = "The Last Jedi" - it[sequelId] = 8 - it[director] = "Rian Johnson" - } - StarWarsFilms.insert { - it[name] = "The Force Awakens" - it[sequelId] = 7 - it[director] = "J.J. Abrams" - } - Players.insert { - it[name] = "Mark Hamill" - it[sequelId] = 7 - } - Players.insert { - it[name] = "Mark Hamill" - it[sequelId] = 8 - } - val simpleInnerJoin = (StarWarsFilms innerJoin Players).selectAll() - assertEquals(2, simpleInnerJoin.count()) - simpleInnerJoin.forEach { - assertNotNull(it[StarWarsFilms.name]) - assertEquals(it[StarWarsFilms.sequelId], it[Players.sequelId]) - assertEquals("Mark Hamill", it[Players.name]) - } - val innerJoinWithCondition = (StarWarsFilms innerJoin Players) - .select { StarWarsFilms.sequelId eq Players.sequelId } - assertEquals(2, innerJoinWithCondition.count()) - innerJoinWithCondition.forEach { - assertNotNull(it[StarWarsFilms.name]) - assertEquals(it[StarWarsFilms.sequelId], it[Players.sequelId]) - assertEquals("Mark Hamill", it[Players.name]) - } - val complexInnerJoin = Join(StarWarsFilms, Players, joinType = JoinType.INNER, onColumn = StarWarsFilms.sequelId, otherColumn = Players.sequelId, additionalConstraint = { - StarWarsFilms.sequelId eq 8 - }).selectAll() - assertEquals(1, complexInnerJoin.count()) - complexInnerJoin.forEach { - assertNotNull(it[StarWarsFilms.name]) - assertEquals(it[StarWarsFilms.sequelId], it[Players.sequelId]) - assertEquals("Mark Hamill", it[Players.name]) - } - - } - } - - @Test - fun whenJoinWithAlias_thenFun() { - Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") - transaction { - addLogger(StdOutSqlLogger) - SchemaUtils.create(StarWarsFilms, Players) - StarWarsFilms.insert { - it[name] = "The Last Jedi" - it[sequelId] = 8 - it[director] = "Rian Johnson" - } - StarWarsFilms.insert { - it[name] = "The Force Awakens" - it[sequelId] = 7 - it[director] = "J.J. Abrams" - } - val sequel = StarWarsFilms.alias("sequel") - Join(StarWarsFilms, sequel, - additionalConstraint = { sequel[StarWarsFilms.sequelId] eq StarWarsFilms.sequelId + 1 }) - .selectAll().forEach { - assertEquals(it[sequel[StarWarsFilms.sequelId]], it[StarWarsFilms.sequelId] + 1) - } - } - } - - @Test - fun whenEntity_thenDAO() { - val database = Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") - val connection = database.connector.invoke() //Keep a connection open so the DB is not destroyed after the first transaction - val inserted = transaction { - addLogger(StdOutSqlLogger) - SchemaUtils.create(StarWarsFilms, Players) - val theLastJedi = StarWarsFilm.new { - name = "The Last Jedi" - sequelId = 8 - director = "Rian Johnson" - } - assertFalse(TransactionManager.current().entityCache.inserts.isEmpty()) - assertEquals(1, theLastJedi.id.value) //Reading this causes a flush - assertTrue(TransactionManager.current().entityCache.inserts.isEmpty()) - theLastJedi - } - transaction { - val theLastJedi = StarWarsFilm.findById(1) - assertNotNull(theLastJedi) - assertEquals(inserted.id, theLastJedi?.id) - } - connection.close() - } - - @Test - fun whenManyToOne_thenNavigation() { - val database = Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") - val connection = database.connector.invoke() - transaction { - addLogger(StdOutSqlLogger) - SchemaUtils.create(StarWarsFilms, Players, Users, UserRatings) - val theLastJedi = StarWarsFilm.new { - name = "The Last Jedi" - sequelId = 8 - director = "Rian Johnson" - } - val someUser = User.new { - name = "Some User" - } - val rating = UserRating.new { - value = 9 - user = someUser - film = theLastJedi - } - assertEquals(theLastJedi, rating.film) - assertEquals(someUser, rating.user) - assertEquals(rating, theLastJedi.ratings.first()) - } - transaction { - val theLastJedi = StarWarsFilm.find { StarWarsFilms.sequelId eq 8 }.first() - val ratings = UserRating.find { UserRatings.film eq theLastJedi.id } - assertEquals(1, ratings.count()) - val rating = ratings.first() - assertEquals("Some User", rating.user.name) - assertEquals(rating, theLastJedi.ratings.first()) - UserRating.new { - value = 8 - user = rating.user - film = theLastJedi - } - assertEquals(2, theLastJedi.ratings.count()) - } - connection.close() - } - - @Test - fun whenManyToMany_thenAssociation() { - val database = Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") - val connection = database.connector.invoke() - val film = transaction { - SchemaUtils.create(StarWarsFilms) - StarWarsFilm.new { - name = "The Last Jedi" - sequelId = 8 - director = "Rian Johnson" - } - } - - val actor = transaction { - SchemaUtils.create(Actors) - Actor.new { - firstname = "Daisy" - lastname = "Ridley" - } - } - - transaction { - SchemaUtils.create(StarWarsFilmActors) - film.actors = SizedCollection(listOf(actor)) - } - connection.close() - } - -} - -object Cities: IntIdTable() { - val name = varchar("name", 50) -} - -object StarWarsFilms_Simple : Table() { - val id = integer("id").autoIncrement().primaryKey() - val sequelId = integer("sequel_id").uniqueIndex() - val name = varchar("name", 50) - val director = varchar("director", 50) -} - -object StarWarsFilms : IntIdTable() { - val sequelId = integer("sequel_id").uniqueIndex() - val name = varchar("name", 50) - val director = varchar("director", 50) -} - -object Players : Table() { - //val sequelId = integer("sequel_id").uniqueIndex().references(StarWarsFilms.sequelId) - val sequelId = reference("sequel_id", StarWarsFilms.sequelId).uniqueIndex() - //val filmId = reference("film_id", StarWarsFilms).nullable() - val name = varchar("name", 50) -} - -class StarWarsFilm(id: EntityID) : Entity(id) { - companion object : EntityClass(StarWarsFilms) - - var sequelId by StarWarsFilms.sequelId - var name by StarWarsFilms.name - var director by StarWarsFilms.director - var actors by Actor via StarWarsFilmActors - val ratings by UserRating referrersOn UserRatings.film -} - -object Users: IntIdTable() { - val name = varchar("name", 50) -} - -object UserRatings: IntIdTable() { - val value = long("value") - val film = reference("film", StarWarsFilms) - val user = reference("user", Users) -} - -class User(id: EntityID): IntEntity(id) { - companion object : IntEntityClass(Users) - - var name by Users.name -} - -class UserRating(id: EntityID): IntEntity(id) { - companion object : IntEntityClass(UserRatings) - - var value by UserRatings.value - var film by StarWarsFilm referencedOn UserRatings.film - var user by User referencedOn UserRatings.user -} - -object Actors: IntIdTable() { - val firstname = varchar("firstname", 50) - val lastname = varchar("lastname", 50) -} - -class Actor(id: EntityID): IntEntity(id) { - companion object : IntEntityClass(Actors) - - var firstname by Actors.firstname - var lastname by Actors.lastname -} - -object StarWarsFilmActors : Table() { - val starWarsFilm = reference("starWarsFilm", StarWarsFilms).primaryKey(0) - val actor = reference("actor", Actors).primaryKey(1) -} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/Calculator.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/Calculator.kt deleted file mode 100644 index 1b61c05887..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/Calculator.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.baeldung.kotlin.junit5 - -class Calculator { - fun add(a: Int, b: Int) = a + b - - fun divide(a: Int, b: Int) = if (b == 0) { - throw DivideByZeroException(a) - } else { - a / b - } - - fun square(a: Int) = a * a - - fun squareRoot(a: Int) = Math.sqrt(a.toDouble()) - - fun log(base: Int, value: Int) = Math.log(value.toDouble()) / Math.log(base.toDouble()) -} diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/DivideByZeroException.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/DivideByZeroException.kt deleted file mode 100644 index 60bc4e2944..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/junit5/DivideByZeroException.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.kotlin.junit5 - -class DivideByZeroException(val numerator: Int) : Exception() diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/khttp/KhttpLiveTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/khttp/KhttpLiveTest.kt deleted file mode 100644 index 4deb576b9f..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/khttp/KhttpLiveTest.kt +++ /dev/null @@ -1,153 +0,0 @@ -package com.baeldung.kotlin.khttp - -import khttp.structures.files.FileLike -import org.json.JSONObject -import org.junit.Test -import java.beans.ExceptionListener -import java.beans.XMLEncoder -import java.io.* -import java.lang.Exception -import java.net.ConnectException -import kotlin.test.assertEquals -import kotlin.test.assertTrue -import kotlin.test.fail - -class KhttpLiveTest { - - @Test - fun whenHttpGetRequestIsMade_thenArgsAreReturned() { - val response = khttp.get( - url = "http://httpbin.org/get", - params = mapOf("p1" to "1", "p2" to "2")) - val args = response.jsonObject.getJSONObject("args") - - assertEquals("1", args["p1"]) - assertEquals("2", args["p2"]) - } - - @Test - fun whenAlternateHttpGetRequestIsMade_thenArgsAreReturned() { - val response = khttp.request( - method = "GET", - url = "http://httpbin.org/get", - params = mapOf("p1" to "1", "p2" to "2")) - val args = response.jsonObject.getJSONObject("args") - - assertEquals("1", args["p1"]) - assertEquals("2", args["p2"]) - } - - @Test - fun whenHeadersAreSet_thenHeadersAreSent() { - val response = khttp.get( - url = "http://httpbin.org/get", - headers = mapOf("header1" to "1", "header2" to "2")) - val headers = response.jsonObject.getJSONObject("headers") - - assertEquals("1", headers["Header1"]) - assertEquals("2", headers["Header2"]) - } - - @Test - fun whenHttpPostRequestIsMadeWithJson_thenBodyIsReturned() { - val response = khttp.post( - url = "http://httpbin.org/post", - params = mapOf("p1" to "1", "p2" to "2"), - json = mapOf("pr1" to "1", "pr2" to "2")) - - val args = response.jsonObject.getJSONObject("args") - - assertEquals("1", args["p1"]) - assertEquals("2", args["p2"]) - - val json = response.jsonObject.getJSONObject("json") - - assertEquals("1", json["pr1"]) - assertEquals("2", json["pr2"]) - } - - @Test - fun whenHttpPostRequestIsMadeWithMapData_thenBodyIsReturned() { - val response = khttp.post( - url = "http://httpbin.org/post", - params = mapOf("p1" to "1", "p2" to "2"), - data = mapOf("pr1" to "1", "pr2" to "2")) - - val args = response.jsonObject.getJSONObject("args") - - assertEquals("1", args["p1"]) - assertEquals("2", args["p2"]) - - val form = response.jsonObject.getJSONObject("form") - - assertEquals("1", form["pr1"]) - assertEquals("2", form["pr2"]) - } - - @Test - fun whenHttpPostRequestIsMadeWithFiles_thenBodyIsReturned() { - val response = khttp.post( - url = "http://httpbin.org/post", - params = mapOf("p1" to "1", "p2" to "2"), - files = listOf( - FileLike("file1", "content1"), - FileLike("file2", javaClass.getResource("KhttpTest.class").openStream().readBytes()))) - - val args = response.jsonObject.getJSONObject("args") - - assertEquals("1", args["p1"]) - assertEquals("2", args["p2"]) - - val files = response.jsonObject.getJSONObject("files") - - assertEquals("content1", files["file1"]) - } - - @Test - fun whenHttpPostRequestIsMadeWithInputStream_thenBodyIsReturned() { - val response = khttp.post( - url = "http://httpbin.org/post", - params = mapOf("p1" to "1", "p2" to "2"), - data = ByteArrayInputStream("content!".toByteArray())) - - val args = response.jsonObject.getJSONObject("args") - - assertEquals("1", args["p1"]) - assertEquals("2", args["p2"]) - - assertEquals("content!", response.jsonObject["data"]) - } - - @Test - fun whenHttpPostStreamingRequestIsMade_thenBodyIsReturnedInChunks() { - val response = khttp.post( - url = "http://httpbin.org/post", - stream = true, - json = mapOf("pr1" to "1", "pr2" to "2")) - - val baos = ByteArrayOutputStream() - response.contentIterator(chunkSize = 10).forEach { arr : ByteArray -> baos.write(arr) } - val json = JSONObject(String(baos.toByteArray())).getJSONObject("json") - - assertEquals("1", json["pr1"]) - assertEquals("2", json["pr2"]) - } - - @Test - fun whenHttpRequestFails_thenExceptionIsThrown() { - try { - khttp.get(url = "http://localhost/nothing/to/see/here") - - fail("Should have thrown an exception") - } catch (e : ConnectException) { - //Ok - } - } - - @Test - fun whenHttpNotFound_thenExceptionIsThrown() { - val response = khttp.get(url = "http://httpbin.org/nothing/to/see/here") - - assertEquals(404, response.statusCode) - } -} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/kodein/KodeinUnitTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/kodein/KodeinUnitTest.kt deleted file mode 100644 index 7776eebd52..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/kodein/KodeinUnitTest.kt +++ /dev/null @@ -1,191 +0,0 @@ -package com.baeldung.kotlin.kodein - -import com.github.salomonbrys.kodein.* -import org.assertj.core.api.Assertions.assertThat -import org.junit.Test - -class KodeinUnitTest { - - class InMemoryDao : Dao - - @Test - fun whenSingletonBinding_thenSingleInstanceIsCreated() { - var created = false - val kodein = Kodein { - bind() with singleton { - created = true - MongoDao() - } - } - - assertThat(created).isFalse() - - val dao1: Dao = kodein.instance() - - assertThat(created).isTrue() - - val dao2: Dao = kodein.instance() - - assertThat(dao1).isSameAs(dao2) - } - - @Test - fun whenFactoryBinding_thenNewInstanceIsCreated() { - val kodein = Kodein { - bind() with singleton { MongoDao() } - bind() with factory { tag: String -> Service(instance(), tag) } - } - val service1: Service = kodein.with("myTag").instance() - val service2: Service = kodein.with("myTag").instance() - - assertThat(service1).isNotSameAs(service2) - } - - @Test - fun whenProviderBinding_thenNewInstanceIsCreated() { - val kodein = Kodein { - bind() with provider { MongoDao() } - } - val dao1: Dao = kodein.instance() - val dao2: Dao = kodein.instance() - - assertThat(dao1).isNotSameAs(dao2) - } - - @Test - fun whenTaggedBinding_thenMultipleInstancesOfSameTypeCanBeRegistered() { - val kodein = Kodein { - bind("dao1") with singleton { MongoDao() } - bind("dao2") with singleton { MongoDao() } - } - val dao1: Dao = kodein.instance("dao1") - val dao2: Dao = kodein.instance("dao2") - - assertThat(dao1).isNotSameAs(dao2) - } - - @Test - fun whenEagerSingletonBinding_thenCreationIsEager() { - var created = false - val kodein = Kodein { - bind() with eagerSingleton { - created = true - MongoDao() - } - } - - assertThat(created).isTrue() - val dao1: Dao = kodein.instance() - val dao2: Dao = kodein.instance() - - assertThat(dao1).isSameAs(dao2) - } - - @Test - fun whenMultitonBinding_thenInstancesAreReused() { - val kodein = Kodein { - bind() with singleton { MongoDao() } - bind() with multiton { tag: String -> Service(instance(), tag) } - } - val service1: Service = kodein.with("myTag").instance() - val service2: Service = kodein.with("myTag").instance() - - assertThat(service1).isSameAs(service2) - } - - @Test - fun whenInstanceBinding_thenItIsReused() { - val dao = MongoDao() - val kodein = Kodein { - bind() with instance(dao) - } - val fromContainer: Dao = kodein.instance() - - assertThat(dao).isSameAs(fromContainer) - } - - @Test - fun whenConstantBinding_thenItIsAvailable() { - val kodein = Kodein { - constant("magic") with 42 - } - val fromContainer: Int = kodein.instance("magic") - - assertThat(fromContainer).isEqualTo(42) - } - - @Test - fun whenUsingModules_thenTransitiveDependenciesAreSuccessfullyResolved() { - val jdbcModule = Kodein.Module { - bind() with singleton { JdbcDao() } - } - val kodein = Kodein { - import(jdbcModule) - bind() with singleton { Controller(instance()) } - bind() with singleton { Service(instance(), "myService") } - } - - val dao: Dao = kodein.instance() - assertThat(dao).isInstanceOf(JdbcDao::class.java) - } - - @Test - fun whenComposition_thenBeansAreReUsed() { - val persistenceContainer = Kodein { - bind() with singleton { MongoDao() } - } - val serviceContainer = Kodein { - extend(persistenceContainer) - bind() with singleton { Service(instance(), "myService") } - } - val fromPersistence: Dao = persistenceContainer.instance() - val fromService: Dao = serviceContainer.instance() - - assertThat(fromPersistence).isSameAs(fromService) - } - - @Test - fun whenOverriding_thenRightBeanIsUsed() { - val commonModule = Kodein.Module { - bind() with singleton { MongoDao() } - bind() with singleton { Service(instance(), "myService") } - } - val testContainer = Kodein { - import(commonModule) - bind(overrides = true) with singleton { InMemoryDao() } - } - val dao: Dao = testContainer.instance() - - assertThat(dao).isInstanceOf(InMemoryDao::class.java) - } - - @Test - fun whenMultiBinding_thenWorks() { - val kodein = Kodein { - bind() from setBinding() - bind().inSet() with singleton { MongoDao() } - bind().inSet() with singleton { JdbcDao() } - } - val daos: Set = kodein.instance() - - assertThat(daos.map { it.javaClass as Class<*> }).containsOnly(MongoDao::class.java, JdbcDao::class.java) - } - - @Test - fun whenInjector_thenWorks() { - class Controller2 { - private val injector = KodeinInjector() - val service: Service by injector.instance() - fun injectDependencies(kodein: Kodein) = injector.inject(kodein) - } - - val kodein = Kodein { - bind() with singleton { MongoDao() } - bind() with singleton { Service(instance(), "myService") } - } - val controller = Controller2() - controller.injectDependencies(kodein) - - assertThat(controller.service).isNotNull - } -} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTest.kt deleted file mode 100644 index ab08273686..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTest.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.kotlin; - -import org.junit.Test -import org.mockito.Mockito - -class LibraryManagementTest { - @Test(expected = IllegalStateException::class) - fun whenBookIsNotAvailable_thenAnExceptionIsThrown() { - val mockBookService = Mockito.mock(BookService::class.java) - - Mockito.`when`(mockBookService.inStock(100)).thenReturn(false) - - val manager = LendBookManager(mockBookService) - - manager.checkout(100, 1) - } - - @Test - fun whenBookIsAvailable_thenLendMethodIsCalled() { - val mockBookService = Mockito.mock(BookService::class.java) - - Mockito.`when`(mockBookService.inStock(100)).thenReturn(true) - - val manager = LendBookManager(mockBookService) - - manager.checkout(100, 1) - - Mockito.verify(mockBookService).lend(100, 1) - } -} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTestMockitoKotlin.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTestMockitoKotlin.kt deleted file mode 100644 index 1ff4e20c61..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/mockito/LendBookManagerTestMockitoKotlin.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.kotlin; - -import com.nhaarman.mockito_kotlin.mock -import com.nhaarman.mockito_kotlin.verify -import com.nhaarman.mockito_kotlin.whenever -import org.junit.Test - -class LibraryManagementTestMockitoKotlin { - @Test(expected = IllegalStateException::class) - fun whenBookIsNotAvailable_thenAnExceptionIsThrown() { - val mockBookService = mock() - - whenever(mockBookService.inStock(100)).thenReturn(false) - - val manager = LendBookManager(mockBookService) - - manager.checkout(100, 1) - } - - @Test - fun whenBookIsAvailable_thenLendMethodIsCalled() { - val mockBookService : BookService = mock() - - whenever(mockBookService.inStock(100)).thenReturn(true) - - val manager = LendBookManager(mockBookService) - - manager.checkout(100, 1) - - verify(mockBookService).lend(100, 1) - } -} \ No newline at end of file diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt deleted file mode 100644 index 979ed3f809..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/rxkotlin/RxKotlinTest.kt +++ /dev/null @@ -1,157 +0,0 @@ -package com.baeldung.kotlin.rxkotlin - -import io.reactivex.Maybe -import io.reactivex.Observable -import io.reactivex.functions.BiFunction -import io.reactivex.rxkotlin.* -import io.reactivex.subjects.PublishSubject -import org.junit.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse - -class RxKotlinTest { - - @Test - fun whenBooleanArrayToObserver_thenBooleanObserver() { - val observable = listOf(true, false, false).toObservable() - observable.test().assertValues(true, false, false) - } - - @Test - fun whenBooleanArrayToFlowable_thenBooleanFlowable() { - val flowable = listOf(true, false, false).toFlowable() - flowable.buffer(2).test().assertValues(listOf(true, false), listOf(false)) - } - - @Test - fun whenIntArrayToObserver_thenIntObserver() { - val observable = listOf(1, 1, 2, 3).toObservable() - observable.test().assertValues(1, 1, 2, 3) - } - - @Test - fun whenIntArrayToFlowable_thenIntFlowable() { - val flowable = listOf(1, 1, 2, 3).toFlowable() - flowable.buffer(2).test().assertValues(listOf(1, 1), listOf(2, 3)) - } - - @Test - fun whenObservablePairToMap_thenSingleNoDuplicates() { - val list = listOf(Pair("a", 1), Pair("b", 2), Pair("c", 3), Pair("a", 4)) - val observable = list.toObservable() - val map = observable.toMap() - assertEquals(mapOf(Pair("a", 4), Pair("b", 2), Pair("c", 3)), map.blockingGet()) - } - - @Test - fun whenObservablePairToMap_thenSingleWithDuplicates() { - val list = listOf(Pair("a", 1), Pair("b", 2), Pair("c", 3), Pair("a", 4)) - val observable = list.toObservable() - val map = observable.toMultimap() - assertEquals( - mapOf(Pair("a", listOf(1, 4)), Pair("b", listOf(2)), Pair("c", listOf(3))), - map.blockingGet()) - } - - @Test - fun whenMergeAll_thenStream() { - val subject = PublishSubject.create>() - val observable = subject.mergeAll() - val testObserver = observable.test() - subject.onNext(Observable.just("first", "second")) - testObserver.assertValues("first", "second") - subject.onNext(Observable.just("third", "fourth")) - subject.onNext(Observable.just("fifth")) - testObserver.assertValues("first", "second", "third", "fourth", "fifth") - } - - @Test - fun whenConcatAll_thenStream() { - val subject = PublishSubject.create>() - val observable = subject.concatAll() - val testObserver = observable.test() - subject.onNext(Observable.just("first", "second")) - testObserver.assertValues("first", "second") - subject.onNext(Observable.just("third", "fourth")) - subject.onNext(Observable.just("fifth")) - testObserver.assertValues("first", "second", "third", "fourth", "fifth") - } - - @Test - fun whenSwitchLatest_thenStream() { - val subject = PublishSubject.create>() - val observable = subject.switchLatest() - val testObserver = observable.test() - subject.onNext(Observable.just("first", "second")) - testObserver.assertValues("first", "second") - subject.onNext(Observable.just("third", "fourth")) - subject.onNext(Observable.just("fifth")) - testObserver.assertValues("first", "second", "third", "fourth", "fifth") - } - - @Test - fun whenMergeAllMaybes_thenObservable() { - val subject = PublishSubject.create>() - val observable = subject.mergeAllMaybes() - val testObserver = observable.test() - subject.onNext(Maybe.just(1)) - subject.onNext(Maybe.just(2)) - subject.onNext(Maybe.empty()) - testObserver.assertValues(1, 2) - subject.onNext(Maybe.error(Exception(""))) - subject.onNext(Maybe.just(3)) - testObserver.assertValues(1, 2).assertError(Exception::class.java) - } - - @Test - fun whenMerge_thenStream() { - val observables = mutableListOf(Observable.just("first", "second")) - val observable = observables.merge() - observables.add(Observable.just("third", "fourth")) - observables.add(Observable.error(Exception("e"))) - observables.add(Observable.just("fifth")) - - observable.test().assertValues("first", "second", "third", "fourth").assertError(Exception::class.java) - } - - @Test - fun whenMergeDelayError_thenStream() { - val observables = mutableListOf>(Observable.error(Exception("e1"))) - val observable = observables.mergeDelayError() - observables.add(Observable.just("1", "2")) - observables.add(Observable.error(Exception("e2"))) - observables.add(Observable.just("3")) - - observable.test().assertValues("1", "2", "3").assertError(Exception::class.java) - } - - @Test - fun whenCast_thenUniformType() { - val observable = Observable.just(1, 1, 2, 3) - observable.cast().test().assertValues(1, 1, 2, 3) - } - - @Test - fun whenOfType_thenFilter() { - val observable = Observable.just(1, "and", 2, "and") - observable.ofType().test().assertValues(1, 2) - } - - @Test - fun whenFunction_thenCompletable() { - var value = 0 - val completable = { value = 3 }.toCompletable() - assertFalse(completable.test().isCancelled) - assertEquals(3, value) - } - - @Test - fun whenHelper_thenMoreIdiomaticKotlin() { - val zipWith = Observable.just(1).zipWith(Observable.just(2)) { a, b -> a + b } - zipWith.subscribeBy(onNext = { println(it) }) - val zip = Observables.zip(Observable.just(1), Observable.just(2)) { a, b -> a + b } - zip.subscribeBy(onNext = { println(it) }) - val zipOrig = Observable.zip(Observable.just(1), Observable.just(2), BiFunction { a, b -> a + b }) - zipOrig.subscribeBy(onNext = { println(it) }) - } -} diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorSubjectTest5.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorSubjectTest5.kt deleted file mode 100644 index f595d65bf2..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorSubjectTest5.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.kotlin.spek - -import com.baeldung.kotlin.junit5.Calculator -import org.jetbrains.spek.api.dsl.describe -import org.jetbrains.spek.api.dsl.it -import org.jetbrains.spek.subject.SubjectSpek -import org.junit.jupiter.api.Assertions.assertEquals - -class CalculatorSubjectTest5 : SubjectSpek({ - subject { Calculator() } - describe("A calculator") { - describe("Addition") { - val result = subject.add(3, 5) - it("Produces the correct answer") { - assertEquals(8, result) - } - } - } -}) diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorTest5.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorTest5.kt deleted file mode 100644 index 3c49d916e4..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/CalculatorTest5.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.kotlin.spek - -import com.baeldung.kotlin.junit5.Calculator -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.describe -import org.jetbrains.spek.api.dsl.given -import org.jetbrains.spek.api.dsl.it -import org.jetbrains.spek.api.dsl.on -import org.junit.jupiter.api.Assertions.assertEquals - -class CalculatorTest5 : Spek({ - given("A calculator") { - val calculator = Calculator() - on("Adding 3 and 5") { - val result = calculator.add(3, 5) - it("Produces 8") { - assertEquals(8, result) - } - } - } - - describe("A calculator") { - val calculator = Calculator() - describe("Addition") { - val result = calculator.add(3, 5) - it("Produces the correct answer") { - assertEquals(8, result) - } - } - } - -}) diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/DataDrivenTest5.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/DataDrivenTest5.kt deleted file mode 100644 index bbcb36e8bb..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/DataDrivenTest5.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.kotlin.spek - -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.describe -import org.jetbrains.spek.api.dsl.it -import org.junit.jupiter.api.Assertions - -class DataDrivenTest5 : Spek({ - describe("A data driven test") { - mapOf( - "hello" to "HELLO", - "world" to "WORLD" - ).forEach { input, expected -> - describe("Capitalising $input") { - it("Correctly returns $expected") { - Assertions.assertEquals(expected, input.toUpperCase()) - } - } - } - } -}) diff --git a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/GroupTest5.kt b/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/GroupTest5.kt deleted file mode 100644 index 5aeee622e4..0000000000 --- a/kotlin-libraries/src/test/kotlin/com/baeldung/kotlin/spek/GroupTest5.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.baeldung.kotlin.spek - -import org.jetbrains.spek.api.Spek -import org.jetbrains.spek.api.dsl.describe -import org.jetbrains.spek.api.dsl.it - -class GroupTest5 : Spek({ - describe("Outer group") { - beforeEachTest { - System.out.println("BeforeEachTest 0") - } - beforeGroup { - System.out.println("BeforeGroup 0") - } - afterEachTest { - System.out.println("AfterEachTest 0") - } - afterGroup { - System.out.println("AfterGroup 0") - } - describe("Inner group 1") { - beforeEachTest { - System.out.println("BeforeEachTest 1") - } - beforeGroup { - System.out.println("BeforeGroup 1") - } - afterEachTest { - System.out.println("AfterEachTest 1") - } - afterGroup { - System.out.println("AfterGroup 1") - } - it("Test 1") { - System.out.println("Test 1") - } - it("Test 2") { - System.out.println("Test 2") - } - } - describe("Inner group 2") { - beforeEachTest { - System.out.println("BeforeEachTest 2") - } - beforeGroup { - System.out.println("BeforeGroup 2") - } - afterEachTest { - System.out.println("AfterEachTest 2") - } - afterGroup { - System.out.println("AfterGroup 2") - } - it("Test 3") { - System.out.println("Test 3") - } - it("Test 4") { - System.out.println("Test 4") - } - } - } -}) diff --git a/kotlin-quasar/README.md b/kotlin-quasar/README.md deleted file mode 100644 index b3693284f9..0000000000 --- a/kotlin-quasar/README.md +++ /dev/null @@ -1,4 +0,0 @@ -### Relevant Articles - -- [Introduction to Quasar in Kotlin](https://www.baeldung.com/kotlin-quasar) -- [Advanced Quasar Usage for Kotlin](https://www.baeldung.com/kotlin-quasar-advanced) diff --git a/kotlin-quasar/pom.xml b/kotlin-quasar/pom.xml deleted file mode 100644 index 59553f422e..0000000000 --- a/kotlin-quasar/pom.xml +++ /dev/null @@ -1,153 +0,0 @@ - - - 4.0.0 - kotlin-quasar - 1.0.0-SNAPSHOT - kotlin-quasar - jar - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - - - org.jetbrains.kotlin - kotlin-test - ${kotlin.version} - test - - - co.paralleluniverse - quasar-core - ${quasar.version} - - - co.paralleluniverse - quasar-actors - ${quasar.version} - - - co.paralleluniverse - quasar-reactive-streams - ${quasar.version} - - - co.paralleluniverse - quasar-kotlin - ${quasar.version} - - - junit - junit - ${junit.version} - - - - org.slf4j - slf4j-api - ${org.slf4j.version} - - - ch.qos.logback - logback-classic - ${logback.version} - - - ch.qos.logback - logback-core - ${logback.version} - - - org.slf4j - jcl-over-slf4j - ${org.slf4j.version} - - - - - src/main/kotlin - src/test/kotlin - - - org.jetbrains.kotlin - kotlin-maven-plugin - ${kotlin.version} - - - compile - compile - - compile - - - - test-compile - test-compile - - test-compile - - - - - 1.8 - - - - maven-dependency-plugin - ${dependency.plugin.version} - - - getClasspathFilenames - - properties - - - - - - org.apache.maven.plugins - maven-surefire-plugin - ${surefire.plugin.version} - - -Dco.paralleluniverse.fibers.verifyInstrumentation=true - -javaagent:${co.paralleluniverse:quasar-core:jar} - - - - org.codehaus.mojo - exec-maven-plugin - ${exec.plugin.version} - - target/classes - echo - - -javaagent:${co.paralleluniverse:quasar-core:jar} - -classpath - - com.baeldung.quasar.QuasarHelloWorldKt - - - - - - - - 0.8.0 - 1.3.31 - 1.7.21 - 1.1.7 - 3.1.1 - 2.22.1 - 1.3.2 - - - diff --git a/kotlin-quasar/src/main/kotlin/com/baeldung/quasar/QuasarHelloWorld.kt b/kotlin-quasar/src/main/kotlin/com/baeldung/quasar/QuasarHelloWorld.kt deleted file mode 100644 index 9bf01ecb09..0000000000 --- a/kotlin-quasar/src/main/kotlin/com/baeldung/quasar/QuasarHelloWorld.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.quasar - -import co.paralleluniverse.fibers.Fiber -import co.paralleluniverse.strands.SuspendableRunnable - - -/** - * Entrypoint into the application - */ -fun main(args: Array) { - class Runnable : SuspendableRunnable { - override fun run() { - println("Hello") - } - } - val result = Fiber(Runnable()).start() - result.join() - println("World") -} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ActorsBehaviorTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ActorsBehaviorTest.kt deleted file mode 100644 index b4d0288a64..0000000000 --- a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ActorsBehaviorTest.kt +++ /dev/null @@ -1,157 +0,0 @@ -package com.baeldung.quasar - -import co.paralleluniverse.actors.Actor -import co.paralleluniverse.actors.ActorRef -import co.paralleluniverse.actors.behaviors.* -import co.paralleluniverse.fibers.Suspendable -import co.paralleluniverse.strands.SuspendableCallable -import org.junit.Test -import org.slf4j.LoggerFactory -import java.lang.Exception - -class ActorsBehaviorTest { - companion object { - private val LOG = LoggerFactory.getLogger(ActorsBehaviorTest::class.java) - } - - @Test - fun requestReplyHelper() { - data class TestMessage(val input: Int) : RequestMessage() - - val actor = object : Actor("requestReplyActor", null) { - @Suspendable - override fun doRun(): Void? { - while (true) { - val msg = receive() - LOG.info("Processing message: {}", msg) - - RequestReplyHelper.reply(msg, msg.input * 100) - } - } - } - - val actorRef = actor.spawn() - - val result = RequestReplyHelper.call(actorRef, TestMessage(50)) - LOG.info("Received reply: {}", result) - } - - @Test - fun server() { - val actor = ServerActor(object : AbstractServerHandler() { - @Suspendable - override fun handleCall(from: ActorRef<*>?, id: Any?, m: Int?): String { - LOG.info("Called with message: {} from {} with ID {}", m, from, id) - return m.toString() ?: "None" - } - - @Suspendable - override fun handleCast(from: ActorRef<*>?, id: Any?, m: Float?) { - LOG.info("Cast message: {} from {} with ID {}", m, from, id) - } - }) - - val server = actor.spawn() - - LOG.info("Call result: {}", server.call(5)) - server.cast(2.5f) - - server.shutdown() - } - - interface Summer { - fun sum(a: Int, b: Int) : Int - } - - @Test - fun proxyServer() { - val actor = ProxyServerActor(false, object : Summer { - @Synchronized - override fun sum(a: Int, b: Int): Int { - Exception().printStackTrace() - LOG.info("Adding together {} and {}", a, b) - return a + b - } - }) - - val summerActor = actor.spawn() - - val result = (summerActor as Summer).sum(1, 2) - LOG.info("Result: {}", result) - - summerActor.shutdown() - } - - @Test - fun eventSource() { - val actor = EventSourceActor() - val eventSource = actor.spawn() - - eventSource.addHandler { msg -> - LOG.info("Sent message: {}", msg) - } - - val name = "Outside Value" - eventSource.addHandler { msg -> - LOG.info("Also Sent message: {} {}", msg, name) - } - - eventSource.send("Hello") - - eventSource.shutdown() - } - - @Test - fun finiteStateMachine() { - val actor = object : FiniteStateMachineActor() { - @Suspendable - override fun initialState(): SuspendableCallable> { - LOG.info("Starting") - return SuspendableCallable { lockedState() } - } - - @Suspendable - fun lockedState() : SuspendableCallable> { - return receive {msg -> - when (msg) { - "PUSH" -> { - LOG.info("Still locked") - lockedState() - } - "COIN" -> { - LOG.info("Unlocking...") - unlockedState() - } - else -> TERMINATE - } - } - } - - @Suspendable - fun unlockedState() : SuspendableCallable> { - return receive {msg -> - when (msg) { - "PUSH" -> { - LOG.info("Locking") - lockedState() - } - "COIN" -> { - LOG.info("Unlocked") - unlockedState() - } - else -> TERMINATE - } - } - } - } - - val actorRef = actor.spawn() - - listOf("PUSH", "COIN", "COIN", "PUSH", "PUSH").forEach { - LOG.info(it) - actorRef.sendSync(it) - } - - actorRef.shutdown() - } -} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ActorsTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ActorsTest.kt deleted file mode 100644 index 819a149af3..0000000000 --- a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ActorsTest.kt +++ /dev/null @@ -1,298 +0,0 @@ -package com.baeldung.quasar - -import co.paralleluniverse.actors.* -import co.paralleluniverse.fibers.Suspendable -import co.paralleluniverse.strands.channels.Channels -import org.junit.Assert -import org.junit.Test -import org.slf4j.LoggerFactory -import java.util.concurrent.TimeUnit - -class ActorsTest { - companion object { - private val LOG = LoggerFactory.getLogger(ActorsTest::class.java) - } - - @Test - fun createNoopActor() { - val actor = object : Actor("noopActor", MailboxConfig(5, Channels.OverflowPolicy.THROW)) { - @Suspendable - override fun doRun(): String { - return "Hello" - } - } - - actor.spawn() - - println("Noop Actor: ${actor.get()}") - } - - @Test - fun registerActor() { - val actor = object : Actor("registerActor", null) { - @Suspendable - override fun doRun(): String { - return "Hello" - } - } - - val actorRef = actor.spawn() - actor.register() - - val retrievedRef = ActorRegistry.getActor>("registerActor") - - Assert.assertEquals(actorRef, retrievedRef) - actor.join() - } - - @Test - fun registerActorNewName() { - val actor = object : Actor(null, null) { - @Suspendable - override fun doRun(): String { - return "Hello" - } - } - - val actorRef = actor.spawn() - actor.register("renamedActor") - - val retrievedRef = ActorRegistry.getActor>("renamedActor") - - Assert.assertEquals(actorRef, retrievedRef) - actor.join() - } - - @Test - fun retrieveUnknownActor() { - val retrievedRef = ActorRegistry.getActor>("unknownActor", 1, TimeUnit.SECONDS) - - Assert.assertNull(retrievedRef) - } - - @Test - fun createSimpleActor() { - val actor = object : Actor("simpleActor", null) { - @Suspendable - override fun doRun(): Void? { - val msg = receive() - LOG.info("SimpleActor Received Message: {}", msg) - - return null - } - } - - val actorRef = actor.spawn() - - actorRef.send(1) - - actor.join() - } - - @Test - fun createLoopingActor() { - val actor = object : Actor("loopingActor", null) { - @Suspendable - override fun doRun(): Void? { - while (true) { - val msg = receive() - - if (msg > 0) { - LOG.info("LoopingActor Received Message: {}", msg) - } else { - break - } - } - - return null - } - } - - val actorRef = actor.spawn() - - actorRef.send(3) - actorRef.send(2) - actorRef.send(1) - actorRef.send(0) - - actor.join() - } - - @Test - fun actorBacklog() { - val actor = object : Actor("backlogActor", MailboxConfig(1, Channels.OverflowPolicy.THROW)) { - @Suspendable - override fun doRun(): String { - TimeUnit.MILLISECONDS.sleep(500); - LOG.info("Backlog Actor Received: {}", receive()) - - try { - receive() - } catch (e: Throwable) { - LOG.info("==== Exception throws by receive() ====") - e.printStackTrace() - } - - return "No Exception" - } - } - - val actorRef = actor.spawn() - - actorRef.send(1) - actorRef.send(2) - - try { - LOG.info("Backlog Actor: {}", actor.get()) - } catch (e: Exception) { - // Expected - LOG.info("==== Exception throws by get() ====") - e.printStackTrace() - } - } - - @Test - fun actorBacklogTrySend() { - val actor = object : Actor("backlogTrySendActor", MailboxConfig(1, Channels.OverflowPolicy.THROW)) { - @Suspendable - override fun doRun(): String { - TimeUnit.MILLISECONDS.sleep(500); - LOG.info("Backlog TrySend Actor Received: {}", receive()) - - return "No Exception" - } - } - - val actorRef = actor.spawn() - - LOG.info("Backlog TrySend 1: {}", actorRef.trySend(1)) - LOG.info("Backlog TrySend 1: {}", actorRef.trySend(2)) - - actor.join() - } - - @Test - fun actorTimeoutReceive() { - val actor = object : Actor("TimeoutReceiveActor", MailboxConfig(1, Channels.OverflowPolicy.THROW)) { - @Suspendable - override fun doRun(): String { - LOG.info("Timeout Actor Received: {}", receive(500, TimeUnit.MILLISECONDS)) - - return "Finished" - } - } - - val actorRef = actor.spawn() - - TimeUnit.MILLISECONDS.sleep(300) - actorRef.trySend(1) - - actor.join() - } - - - @Test - fun actorNonBlockingReceive() { - val actor = object : Actor("NonBlockingReceiveActor", MailboxConfig(1, Channels.OverflowPolicy.THROW)) { - @Suspendable - override fun doRun(): String { - LOG.info("NonBlocking Actor Received #1: {}", tryReceive()) - TimeUnit.MILLISECONDS.sleep(500) - LOG.info("NonBlocking Actor Received #2: {}", tryReceive()) - - return "Finished" - } - } - - val actorRef = actor.spawn() - - TimeUnit.MILLISECONDS.sleep(300) - actorRef.trySend(1) - - actor.join() - } - - @Test - fun evenActor() { - val actor = object : Actor("EvenActor", null) { - @Suspendable - override fun filterMessage(m: Any?): Int? { - return when (m) { - is Int -> { - if (m % 2 == 0) { - m * 10 - } else { - null - } - } - else -> super.filterMessage(m) - } - } - - @Suspendable - override fun doRun(): Void? { - while (true) { - val msg = receive() - - if (msg > 0) { - LOG.info("EvenActor Received Message: {}", msg) - } else { - break - } - } - - return null - } - } - - val actorRef = actor.spawn() - - actorRef.send(3) - actorRef.send(2) - actorRef.send(1) - actorRef.send(0) - - actor.join() - } - - @Test - fun watchingActors() { - val watched = object : Actor("WatchedActor", null) { - @Suspendable - override fun doRun(): Void? { - LOG.info("WatchedActor Starting") - receive(500, TimeUnit.MILLISECONDS) - LOG.info("WatchedActor Finishing") - return null - } - } - - val watcher = object : Actor("WatcherActor", null) { - @Suspendable - override fun doRun(): Void? { - LOG.info("WatcherActor Listening") - try { - LOG.info("WatcherActor received Message: {}", receive(2, TimeUnit.SECONDS)) - } catch (e: Exception) { - LOG.info("WatcherActor Received Exception", e) - } - return null - } - - @Suspendable - override fun handleLifecycleMessage(m: LifecycleMessage?): Int? { - LOG.info("WatcherActor Received Lifecycle Message: {}", m) - return super.handleLifecycleMessage(m) - } - } - - val watcherRef = watcher.spawn() - TimeUnit.MILLISECONDS.sleep(200) - - val watchedRef = watched.spawn() - watcher.link(watchedRef) - - watched.join() - watcher.join() - } -} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ChannelsTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ChannelsTest.kt deleted file mode 100644 index b51943446e..0000000000 --- a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ChannelsTest.kt +++ /dev/null @@ -1,155 +0,0 @@ -package com.baeldung.quasar - -import co.paralleluniverse.fibers.Suspendable -import co.paralleluniverse.kotlin.fiber -import co.paralleluniverse.strands.channels.Channels -import co.paralleluniverse.strands.channels.Selector -import com.google.common.base.Function -import org.junit.Test - -class ChannelsTest { - @Test - fun createChannel() { - Channels.newChannel(0, // The size of the channel buffer - Channels.OverflowPolicy.BLOCK, // The policy for when the buffer is full - true, // Whether we should optimize for a single message producer - true) // Whether we should optimize for a single message consumer - } - - @Test - fun blockOnMessage() { - val channel = Channels.newChannel(0, Channels.OverflowPolicy.BLOCK, true, true) - - fiber @Suspendable { - while (!channel.isClosed) { - val message = channel.receive() - println("Received: $message") - } - println("Stopped receiving messages") - } - - channel.send("Hello") - channel.send("World") - - channel.close() - } - - @Test - fun selectReceiveChannels() { - val channel1 = Channels.newChannel(0, Channels.OverflowPolicy.BLOCK, true, true) - val channel2 = Channels.newChannel(0, Channels.OverflowPolicy.BLOCK, true, true) - - fiber @Suspendable { - while (!channel1.isClosed && !channel2.isClosed) { - val received = Selector.select(Selector.receive(channel1), Selector.receive(channel2)) - - println("Received: $received") - } - } - - fiber @Suspendable { - for (i in 0..10) { - channel1.send("Channel 1: $i") - } - } - - fiber @Suspendable { - for (i in 0..10) { - channel2.send("Channel 2: $i") - } - } - } - - @Test - fun selectSendChannels() { - val channel1 = Channels.newChannel(0, Channels.OverflowPolicy.BLOCK, true, true) - val channel2 = Channels.newChannel(0, Channels.OverflowPolicy.BLOCK, true, true) - - fiber @Suspendable { - for (i in 0..10) { - Selector.select( - Selector.send(channel1, "Channel 1: $i"), - Selector.send(channel2, "Channel 2: $i") - ) - } - } - - fiber @Suspendable { - while (!channel1.isClosed) { - val msg = channel1.receive() - println("Read: $msg") - } - } - - fiber @Suspendable { - while (!channel2.isClosed) { - val msg = channel2.receive() - println("Read: $msg") - } - } - } - - @Test - fun tickerChannel() { - val channel = Channels.newChannel(3, Channels.OverflowPolicy.DISPLACE) - - for (i in 0..10) { - val tickerConsumer = Channels.newTickerConsumerFor(channel) - fiber @Suspendable { - while (!tickerConsumer.isClosed) { - val message = tickerConsumer.receive() - println("Received on $i: $message") - } - println("Stopped receiving messages on $i") - } - } - - for (i in 0..50) { - channel.send("Message $i") - } - - channel.close() - } - - - @Test - fun transformOnSend() { - val channel = Channels.newChannel(0, Channels.OverflowPolicy.BLOCK, true, true) - - fiber @Suspendable { - while (!channel.isClosed) { - val message = channel.receive() - println("Received: $message") - } - println("Stopped receiving messages") - } - - val transformOnSend = Channels.mapSend(channel, Function { msg: String? -> msg?.toUpperCase() }) - - transformOnSend.send("Hello") - transformOnSend.send("World") - - channel.close() - } - - @Test - fun transformOnReceive() { - val channel = Channels.newChannel(0, Channels.OverflowPolicy.BLOCK, true, true) - - val transformOnReceive = Channels.map(channel, Function { msg: String? -> msg?.reversed() }) - - fiber @Suspendable { - while (!transformOnReceive.isClosed) { - val message = transformOnReceive.receive() - println("Received: $message") - } - println("Stopped receiving messages") - } - - - channel.send("Hello") - channel.send("World") - - channel.close() - } -} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/DataflowTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/DataflowTest.kt deleted file mode 100644 index 3f73af3917..0000000000 --- a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/DataflowTest.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.baeldung.quasar - -import co.paralleluniverse.strands.dataflow.Val -import co.paralleluniverse.strands.dataflow.Var -import org.junit.Assert -import org.junit.Test -import java.util.concurrent.TimeUnit - -class DataflowTest { - @Test - fun testValVar() { - val a = Var() - val b = Val() - - val c = Var { a.get() + b.get() } - val d = Var { a.get() * b.get() } - - // (a*b) - (a+b) - val initialResult = Val { d.get() - c.get() } - val currentResult = Var { d.get() - c.get() } - - a.set(2) - b.set(4) - - Assert.assertEquals(2, initialResult.get()) - Assert.assertEquals(2, currentResult.get()) - - a.set(3) - - TimeUnit.SECONDS.sleep(1) - - Assert.assertEquals(2, initialResult.get()) - Assert.assertEquals(5, currentResult.get()) - } -} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/PiAsyncTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/PiAsyncTest.kt deleted file mode 100644 index d4ea04820d..0000000000 --- a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/PiAsyncTest.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.baeldung.quasar - -import co.paralleluniverse.fibers.Fiber -import co.paralleluniverse.fibers.FiberAsync -import co.paralleluniverse.fibers.Suspendable -import co.paralleluniverse.kotlin.fiber -import co.paralleluniverse.strands.Strand -import org.junit.Assert -import org.junit.Test -import java.math.BigDecimal -import java.util.concurrent.TimeUnit - -interface PiCallback { - fun success(result: BigDecimal) - fun failure(error: Exception) -} - -fun computePi(callback: PiCallback) { - println("Starting calculations") - TimeUnit.SECONDS.sleep(2) - println("Finished calculations") - callback.success(BigDecimal("3.14")) -} - -class PiAsync : PiCallback, FiberAsync() { - override fun success(result: BigDecimal) { - asyncCompleted(result) - } - - override fun failure(error: Exception) { - asyncFailed(error) - } - - override fun requestAsync() { - computePi(this) - } -} - -class PiAsyncTest { - @Test - fun testPi() { - val result = fiber @Suspendable { - val pi = PiAsync() - println("Waiting to get PI on: " + Fiber.currentFiber().name) - val result = pi.run() - println("Got PI") - - result - }.get() - - Assert.assertEquals(BigDecimal("3.14"), result) - } -} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ReactiveStreamsTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ReactiveStreamsTest.kt deleted file mode 100644 index 83e06bf7d6..0000000000 --- a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/ReactiveStreamsTest.kt +++ /dev/null @@ -1,135 +0,0 @@ -package com.baeldung.quasar - -import co.paralleluniverse.fibers.Suspendable -import co.paralleluniverse.kotlin.fiber -import co.paralleluniverse.strands.channels.Channels -import co.paralleluniverse.strands.channels.Topic -import co.paralleluniverse.strands.channels.reactivestreams.ReactiveStreams -import org.junit.Test -import org.reactivestreams.Subscriber -import org.reactivestreams.Subscription -import org.slf4j.LoggerFactory -import java.util.concurrent.TimeUnit - -class ReactiveStreamsTest { - companion object { - private val LOG = LoggerFactory.getLogger(ReactiveStreamsTest::class.java) - } - - @Test - fun publisher() { - val inputChannel = Channels.newChannel(1); - - val publisher = ReactiveStreams.toPublisher(inputChannel) - publisher.subscribe(object : Subscriber { - @Suspendable - override fun onComplete() { - LOG.info("onComplete") - } - - @Suspendable - override fun onSubscribe(s: Subscription) { - LOG.info("onSubscribe: {}", s) - s.request(2) - } - - @Suspendable - override fun onNext(t: String?) { - LOG.info("onNext: {}", t) - } - - @Suspendable - override fun onError(t: Throwable?) { - LOG.info("onError: {}", t) - } - }) - - inputChannel.send("Hello") - inputChannel.send("World") - - TimeUnit.SECONDS.sleep(1) - - inputChannel.close() - } - - @Test - fun publisherTopic() { - val inputTopic = Topic() - - val publisher = ReactiveStreams.toPublisher(inputTopic) - publisher.subscribe(object : Subscriber { - @Suspendable - override fun onComplete() { - LOG.info("onComplete 1") - } - - @Suspendable - override fun onSubscribe(s: Subscription) { - LOG.info("onSubscribe 1: {}", s) - s.request(2) - } - - @Suspendable - override fun onNext(t: String?) { - LOG.info("onNext 1: {}", t) - } - - @Suspendable - override fun onError(t: Throwable?) { - LOG.info("onError 1: {}", t) - } - }) - publisher.subscribe(object : Subscriber { - @Suspendable - override fun onComplete() { - LOG.info("onComplete 2") - } - - @Suspendable - override fun onSubscribe(s: Subscription) { - LOG.info("onSubscribe 2: {}", s) - s.request(2) - } - - @Suspendable - override fun onNext(t: String?) { - LOG.info("onNext 2: {}", t) - } - - @Suspendable - override fun onError(t: Throwable?) { - LOG.info("onError 2: {}", t) - } - }) - - inputTopic.send("Hello") - inputTopic.send("World") - - TimeUnit.SECONDS.sleep(1) - - inputTopic.close() - } - - @Test - fun subscribe() { - val inputChannel = Channels.newChannel(10); - val publisher = ReactiveStreams.toPublisher(inputChannel) - - val channel = ReactiveStreams.subscribe(10, Channels.OverflowPolicy.THROW, publisher) - - fiber @Suspendable { - while (!channel.isClosed) { - val message = channel.receive() - LOG.info("Received: {}", message) - } - LOG.info("Stopped receiving messages") - } - - inputChannel.send("Hello") - inputChannel.send("World") - - TimeUnit.SECONDS.sleep(1) - - inputChannel.close() - } -} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/SuspendableCallableTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/SuspendableCallableTest.kt deleted file mode 100644 index 9b139dd686..0000000000 --- a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/SuspendableCallableTest.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.baeldung.quasar - -import co.paralleluniverse.fibers.Fiber -import co.paralleluniverse.fibers.Suspendable -import co.paralleluniverse.kotlin.fiber -import co.paralleluniverse.strands.SuspendableCallable -import org.junit.Assert -import org.junit.Test -import java.util.concurrent.TimeUnit - - -class SuspendableCallableTest { - @Test - fun createFiber() { - class Callable : SuspendableCallable { - override fun run(): String { - println("Inside Fiber") - return "Hello" - } - } - val result = Fiber(Callable()).start() - - Assert.assertEquals("Hello", result.get()) - } - - @Test - fun createFiberLambda() { - val lambda: (() -> String) = { - println("Inside Fiber Lambda") - "Hello" - } - val result = Fiber(lambda) - result.start() - - Assert.assertEquals("Hello", result.get()) - } - - @Test - fun createFiberDsl() { - val result = fiber @Suspendable { - TimeUnit.SECONDS.sleep(5) - println("Inside Fiber DSL") - "Hello" - } - - Assert.assertEquals("Hello", result.get()) - } -} diff --git a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/SuspensableRunnableTest.kt b/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/SuspensableRunnableTest.kt deleted file mode 100644 index ba4cef8f4c..0000000000 --- a/kotlin-quasar/src/test/kotlin/com/baeldung/quasar/SuspensableRunnableTest.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.baeldung.quasar - -import co.paralleluniverse.fibers.Fiber -import co.paralleluniverse.fibers.Suspendable -import co.paralleluniverse.kotlin.fiber -import co.paralleluniverse.strands.SuspendableRunnable -import org.junit.Test -import java.util.concurrent.TimeUnit -import java.util.concurrent.TimeoutException - - -class SuspensableRunnableTest { - @Test - fun createFiber() { - class Runnable : SuspendableRunnable { - override fun run() { - println("Inside Fiber") - } - } - val result = Fiber(Runnable()).start() - result.join() - } - - @Test - fun createFiberLambda() { - val result = Fiber { - println("Inside Fiber Lambda") - } - result.start() - result.join() - } - - @Test - fun createFiberDsl() { - fiber @Suspendable { - println("Inside Fiber DSL") - }.join() - } - - @Test(expected = TimeoutException::class) - fun fiberTimeout() { - fiber @Suspendable { - TimeUnit.SECONDS.sleep(5) - println("Inside Fiber DSL") - }.join(2, TimeUnit.SECONDS) - } -} diff --git a/libraries-5/src/test/java/com/baeldung/pact/PactConsumerDrivenContractUnitTest.java b/libraries-5/src/test/java/com/baeldung/pact/PactConsumerDrivenContractUnitTest.java index e4ac8a3a95..8d4918a3e7 100644 --- a/libraries-5/src/test/java/com/baeldung/pact/PactConsumerDrivenContractUnitTest.java +++ b/libraries-5/src/test/java/com/baeldung/pact/PactConsumerDrivenContractUnitTest.java @@ -7,22 +7,38 @@ import au.com.dius.pact.consumer.dsl.PactDslWithProvider; import au.com.dius.pact.model.RequestResponsePact; import org.junit.Rule; import org.junit.Test; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; +import org.springframework.http.*; import org.springframework.web.client.RestTemplate; +import java.io.IOException; +import java.net.ServerSocket; import java.util.HashMap; import java.util.Map; +import java.util.Random; import static org.assertj.core.api.Assertions.assertThat; public class PactConsumerDrivenContractUnitTest { + private static int getAvailablePort() { + return new Random() + .ints(6000, 9000) + .filter(PactConsumerDrivenContractUnitTest::isFree) + .findFirst() + .orElse(8080); + } + + private static boolean isFree(int port) { + try { + new ServerSocket(port).close(); + return true; + } catch (IOException e) { + return false; + } + } + @Rule - public PactProviderRuleMk2 mockProvider = new PactProviderRuleMk2("test_provider", "localhost", 8080, this); + public PactProviderRuleMk2 mockProvider = new PactProviderRuleMk2("test_provider", "localhost", getAvailablePort(), this); @Pact(consumer = "test_consumer") public RequestResponsePact createPact(PactDslWithProvider builder) { diff --git a/libraries-6/README.md b/libraries-6/README.md index 3748522b9d..ecad499e07 100644 --- a/libraries-6/README.md +++ b/libraries-6/README.md @@ -13,7 +13,9 @@ Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-m - [Implementing a FTP-Client in Java](https://www.baeldung.com/java-ftp-client) - [Introduction to Functional Java](https://www.baeldung.com/java-functional-library) - [A Guide to the Reflections Library](https://www.baeldung.com/reflections-library) -- [Exactly Once Processing in Kafka](https://www.baeldung.com/kafka-exactly-once) +- [Exactly Once Processing in Kafka with Java](https://www.baeldung.com/kafka-exactly-once) - [Introduction to Protonpack](https://www.baeldung.com/java-protonpack) - [Java-R Integration](https://www.baeldung.com/java-r-integration) +- [Using libphonenumber to Validate Phone Numbers](https://www.baeldung.com/java-libphonenumber) +- [Apache Commons Collections vs Google Guava](https://www.baeldung.com/apache-commons-collections-vs-guava) - More articles [[<-- prev]](/libraries-5) diff --git a/libraries-6/pom.xml b/libraries-6/pom.xml index 2f8cc385cb..caaebbb922 100644 --- a/libraries-6/pom.xml +++ b/libraries-6/pom.xml @@ -76,6 +76,11 @@ commons-lang3 ${commons-lang3.version} + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + commons-net commons-net @@ -89,7 +94,7 @@ commons-io commons-io - ${commonsio.version} + ${commons-io.version} test @@ -107,6 +112,12 @@ renjin-script-engine ${renjin.version} + + + com.googlecode.libphonenumber + libphonenumber + ${libphonenumber.version} + @@ -146,10 +157,11 @@ 1.15 3.6 3.6.2 - 2.6 RELEASE 3.0 1.8.1 + 4.4 + 8.12.9 diff --git a/libraries-6/src/test/java/com/baeldung/apache/commons/CollectionsUnitTest.java b/libraries-6/src/test/java/com/baeldung/apache/commons/CollectionsUnitTest.java new file mode 100644 index 0000000000..3de0c64fb9 --- /dev/null +++ b/libraries-6/src/test/java/com/baeldung/apache/commons/CollectionsUnitTest.java @@ -0,0 +1,182 @@ +package com.baeldung.apache.commons; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.apache.commons.collections4.BidiMap; +import org.apache.commons.collections4.MultiValuedMap; +import org.apache.commons.collections4.bidimap.DualHashBidiMap; +import org.apache.commons.collections4.bidimap.DualTreeBidiMap; +import org.apache.commons.collections4.bidimap.TreeBidiMap; +import org.apache.commons.collections4.map.MultiKeyMap; +import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; +import org.junit.Test; + +public class CollectionsUnitTest { + private final static BidiMap daysOfWeek = new TreeBidiMap(); + private final static MultiValuedMap groceryCart = new ArrayListValuedHashMap<>(); + private final static MultiKeyMap days = new MultiKeyMap(); + private final static MultiKeyMap cityCoordinates = new MultiKeyMap(); + private long start; + + static { + daysOfWeek.put(1, "Monday"); + daysOfWeek.put(2, "Tuesday"); + daysOfWeek.put(3, "Wednesday"); + daysOfWeek.put(4, "Thursday"); + daysOfWeek.put(5, "Friday"); + daysOfWeek.put(6, "Saturday"); + daysOfWeek.put(7, "Sunday"); + + groceryCart.put("Fruits", "Apple"); + groceryCart.put("Fruits", "Grapes"); + groceryCart.put("Fruits", "Strawberries"); + groceryCart.put("Vegetables", "Spinach"); + groceryCart.put("Vegetables", "Cabbage"); + + days.put("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Weekday"); + days.put("Saturday", "Sunday", "Weekend"); + + cityCoordinates.put("40.7128° N", "74.0060° W", "New York"); + cityCoordinates.put("48.8566° N", "2.3522° E", "Paris"); + cityCoordinates.put("19.0760° N", "72.8777° E", "Mumbai"); + + } + + @Test + public void givenBidiMap_whenValue_thenKeyReturned() { + assertEquals(Integer.valueOf(7), daysOfWeek.inverseBidiMap() + .get("Sunday")); + } + + @Test + public void givenBidiMap_whenKey_thenValueReturned() { + assertEquals("Tuesday", daysOfWeek.get(2)); + } + + @Test + public void givenMultiValuedMap_whenFruitsFetched_thenFruitsReturned() { + + List fruits = Arrays.asList("Apple", "Grapes", "Strawberries"); + assertEquals(fruits, groceryCart.get("Fruits")); + } + + @Test + public void givenMultiValuedMap_whenVeggiesFetched_thenVeggiesReturned() { + List veggies = Arrays.asList("Spinach", "Cabbage"); + assertEquals(veggies, groceryCart.get("Vegetables")); + } + + @Test + public void givenMultiValuedMap_whenFuitsRemoved_thenVeggiesPreserved() { + + assertEquals(5, groceryCart.size()); + + groceryCart.remove("Fruits"); + assertEquals(2, groceryCart.size()); + } + + @Test + public void givenDaysMultiKeyMap_whenFetched_thenOK() { + assertFalse(days.get("Saturday", "Sunday") + .equals("Weekday")); + } + + @Test + public void givenCoordinatesMultiKeyMap_whenQueried_thenOK() { + List expectedLongitudes = Arrays.asList("72.8777° E", "2.3522° E", "74.0060° W"); + List longitudes = new ArrayList<>(); + + cityCoordinates.forEach((key, value) -> { + longitudes.add(key.getKey(1)); + }); + + assertArrayEquals(expectedLongitudes.toArray(), longitudes.toArray()); + + List expectedCities = Arrays.asList("Mumbai", "Paris", "New York"); + List cities = new ArrayList<>(); + + cityCoordinates.forEach((key, value) -> { + cities.add(value); + }); + + assertArrayEquals(expectedCities.toArray(), cities.toArray()); + + } + + @Test + public void givenTreeBidiMap_whenHundredThousandKeys_thenPerformanceNoted() { + System.out.println("**TreeBidiMap**"); + BidiMap map = new TreeBidiMap<>(); + start = System.nanoTime(); + for (int i = 0; i < 100000; i++) { + Integer key = new Integer(i); + Integer value = new Integer(i + 1); + map.put(key, value); + } + System.out.println("Insertion time:" + TimeUnit.MILLISECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS)); + + start = System.nanoTime(); + Integer value = (Integer) map.get(new Integer(500)); + System.out.println("Value:" + value); + System.out.println("Fetch time key:" + TimeUnit.MICROSECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS)); + + start = System.nanoTime(); + Integer key = (Integer) map.getKey(new Integer(501)); + System.out.println("Key:" + key); + System.out.println("Fetch time value:" + TimeUnit.MICROSECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS)); + } + + @Test + public void givenDualTreeBidiMap_whenHundredThousandKeys_thenPerformanceNoted() { + System.out.println("**DualTreeBidiMap**"); + BidiMap map = new DualTreeBidiMap<>(); + start = System.nanoTime(); + for (int i = 0; i < 100000; i++) { + Integer key = new Integer(i); + Integer value = new Integer(i + 1); + map.put(key, value); + } + System.out.println("Insertion time:" + TimeUnit.MILLISECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS)); + + start = System.nanoTime(); + Integer value = (Integer) map.get(new Integer(500)); + System.out.println("Value:" + value); + System.out.println("Fetch time key:" + TimeUnit.MICROSECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS)); + + start = System.nanoTime(); + Integer key = (Integer) map.getKey(new Integer(501)); + System.out.println("Key:" + key); + System.out.println("Fetch time value:" + TimeUnit.MICROSECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS)); + } + + @Test + public void givenDualHashBidiMap_whenHundredThousandKeys_thenPerformanceNoted() { + System.out.println("**DualHashBidiMap**"); + BidiMap map = new DualHashBidiMap<>(); + start = System.nanoTime(); + for (int i = 0; i < 100000; i++) { + Integer key = new Integer(i); + Integer value = new Integer(i + 1); + map.put(key, value); + } + System.out.println("Insertion time:" + TimeUnit.MILLISECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS)); + + start = System.nanoTime(); + Integer value = (Integer) map.get(new Integer(500)); + System.out.println("Value:" + value); + System.out.println("Fetch time key:" + TimeUnit.MICROSECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS)); + + start = System.nanoTime(); + Integer key = (Integer) map.getKey(new Integer(501)); + System.out.println("Key:" + key); + System.out.println("Fetch time value:" + TimeUnit.MICROSECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS)); + } + +} \ No newline at end of file diff --git a/libraries-6/src/test/java/com/baeldung/guava/GuavaUnitTest.java b/libraries-6/src/test/java/com/baeldung/guava/GuavaUnitTest.java new file mode 100644 index 0000000000..c0501f761e --- /dev/null +++ b/libraries-6/src/test/java/com/baeldung/guava/GuavaUnitTest.java @@ -0,0 +1,143 @@ +package com.baeldung.guava; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.junit.Test; + +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Multimap; +import com.google.common.collect.Table; + +public class GuavaUnitTest { + private final static BiMap daysOfWeek = HashBiMap.create(); + private final static Multimap groceryCart = ArrayListMultimap.create(); + private final static Table cityCoordinates = HashBasedTable.create(); + private final static Table movies = HashBasedTable.create(); + private long start; + + static { + daysOfWeek.put(1, "Monday"); + daysOfWeek.put(2, "Tuesday"); + daysOfWeek.put(3, "Wednesday"); + daysOfWeek.put(4, "Thursday"); + daysOfWeek.put(5, "Friday"); + daysOfWeek.put(6, "Saturday"); + daysOfWeek.put(7, "Sunday"); + + groceryCart.put("Fruits", "Apple"); + groceryCart.put("Fruits", "Grapes"); + groceryCart.put("Fruits", "Strawberries"); + groceryCart.put("Vegetables", "Spinach"); + groceryCart.put("Vegetables", "Cabbage"); + + cityCoordinates.put("40.7128° N", "74.0060° W", "New York"); + cityCoordinates.put("48.8566° N", "2.3522° E", "Paris"); + cityCoordinates.put("19.0760° N", "72.8777° E", "Mumbai"); + + movies.put("Tom Hanks", "Meg Ryan", "You've Got Mail"); + movies.put("Tom Hanks", "Catherine Zeta-Jones", "The Terminal"); + movies.put("Bradley Cooper", "Lady Gaga", "A Star is Born"); + movies.put("Keenu Reaves", "Sandra Bullock", "Speed"); + movies.put("Tom Hanks", "Sandra Bullock", "Extremely Loud & Incredibly Close"); + } + + @Test + public void givenBiMap_whenValue_thenKeyReturned() { + assertEquals(Integer.valueOf(7), daysOfWeek.inverse() + .get("Sunday")); + } + + @Test + public void givenBiMap_whenKey_thenValueReturned() { + assertEquals("Tuesday", daysOfWeek.get(2)); + } + + @Test + public void givenMultiValuedMap_whenFruitsFetched_thenFruitsReturned() { + + List fruits = Arrays.asList("Apple", "Grapes", "Strawberries"); + assertEquals(fruits, groceryCart.get("Fruits")); + } + + @Test + public void givenMultiValuedMap_whenVeggiesFetched_thenVeggiesReturned() { + List veggies = Arrays.asList("Spinach", "Cabbage"); + assertEquals(veggies, groceryCart.get("Vegetables")); + } + + @Test + public void givenMultiValuedMap_whenFuitsRemoved_thenVeggiesPreserved() { + + assertEquals(5, groceryCart.size()); + + groceryCart.remove("Fruits", "Apple"); + assertEquals(4, groceryCart.size()); + + groceryCart.removeAll("Fruits"); + assertEquals(2, groceryCart.size()); + } + + @Test + public void givenCoordinatesTable_whenFetched_thenOK() { + + List expectedLongitudes = Arrays.asList("74.0060° W", "2.3522° E", "72.8777° E"); + + assertArrayEquals(expectedLongitudes.toArray(), cityCoordinates.columnKeySet() + .toArray()); + + List expectedCities = Arrays.asList("New York", "Paris", "Mumbai"); + + assertArrayEquals(expectedCities.toArray(), cityCoordinates.values() + .toArray()); + + assertTrue(cityCoordinates.rowKeySet() + .contains("48.8566° N")); + + } + + @Test + public void givenMoviesTable_whenFetched_thenOK() { + assertEquals(3, movies.row("Tom Hanks") + .size()); + + assertEquals(2, movies.column("Sandra Bullock") + .size()); + + assertEquals("A Star is Born", movies.get("Bradley Cooper", "Lady Gaga")); + + assertTrue(movies.containsValue("Speed")); + + } + + @Test + public void givenHashBiMap_whenHundredThousandKeys_thenPerformanceNoted() { + BiMap map = HashBiMap.create(); + start = System.nanoTime(); + for (int i = 0; i < 100000; i++) { + Integer key = new Integer(i); + Integer value = new Integer(i + 1); + map.put(key, value); + } + System.out.println("Insertion time:" + TimeUnit.MILLISECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS)); + + start = System.nanoTime(); + Integer value = map.get(new Integer(500)); + System.out.println("Value:" + value); + System.out.println("Fetch time key:" + TimeUnit.MICROSECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS)); + + start = System.nanoTime(); + Integer key = map.inverse() + .get(new Integer(501)); + System.out.println("Key:" + key); + System.out.println("Fetch time value:" + TimeUnit.MICROSECONDS.convert(System.nanoTime() - start, TimeUnit.NANOSECONDS)); + } +} \ No newline at end of file diff --git a/libraries-6/src/test/java/com/baeldung/libphonenumber/LibPhoneNumberUnitTest.java b/libraries-6/src/test/java/com/baeldung/libphonenumber/LibPhoneNumberUnitTest.java new file mode 100644 index 0000000000..39b96b3e38 --- /dev/null +++ b/libraries-6/src/test/java/com/baeldung/libphonenumber/LibPhoneNumberUnitTest.java @@ -0,0 +1,79 @@ +package com.baeldung.libphonenumber; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.google.i18n.phonenumbers.NumberParseException; +import com.google.i18n.phonenumbers.PhoneNumberUtil; +import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberType; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; +import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber.CountryCodeSource; + +public class LibPhoneNumberUnitTest { + + private static final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance(); + + @Test + public void givenPhoneNumber_whenValid_thenOK() throws Exception { + + PhoneNumber phone = phoneNumberUtil.parse("+911234567890", CountryCodeSource.UNSPECIFIED.name()); + + assertTrue(phoneNumberUtil.isValidNumber(phone)); + assertTrue(phoneNumberUtil.isValidNumberForRegion(phone, "IN")); + assertFalse(phoneNumberUtil.isValidNumberForRegion(phone, "US")); + assertTrue(phoneNumberUtil.isValidNumber(phoneNumberUtil.getExampleNumber("IN"))); + } + + @Test + public void givenPhoneNumber_whenAlphaNumber_thenValid() { + assertTrue(phoneNumberUtil.isAlphaNumber("325-CARS")); + assertTrue(phoneNumberUtil.isAlphaNumber("0800 REPAIR")); + assertTrue(phoneNumberUtil.isAlphaNumber("1-800-MY-APPLE")); + assertTrue(phoneNumberUtil.isAlphaNumber("1-800-MY-APPLE..")); + assertFalse(phoneNumberUtil.isAlphaNumber("+876 1234-1234")); + } + + @Test + public void givenPhoneNumber_whenPossibleForType_thenValid() { + PhoneNumber number = new PhoneNumber(); + number.setCountryCode(54); + + number.setNationalNumber(123456); + assertTrue(phoneNumberUtil.isPossibleNumberForType(number, PhoneNumberType.FIXED_LINE)); + assertFalse(phoneNumberUtil.isPossibleNumberForType(number, PhoneNumberType.TOLL_FREE)); + + number.setNationalNumber(12345678901L); + assertFalse(phoneNumberUtil.isPossibleNumberForType(number, PhoneNumberType.FIXED_LINE)); + assertTrue(phoneNumberUtil.isPossibleNumberForType(number, PhoneNumberType.MOBILE)); + assertFalse(phoneNumberUtil.isPossibleNumberForType(number, PhoneNumberType.TOLL_FREE)); + } + + @Test + public void givenPhoneNumber_whenPossible_thenValid() { + PhoneNumber number = new PhoneNumber(); + number.setCountryCode(1) + .setNationalNumber(123000L); + assertFalse(phoneNumberUtil.isPossibleNumber(number)); + assertFalse(phoneNumberUtil.isPossibleNumber("+1 343 253 00000", "US")); + assertFalse(phoneNumberUtil.isPossibleNumber("(343) 253-00000", "US")); + assertFalse(phoneNumberUtil.isPossibleNumber("dial p for pizza", "US")); + assertFalse(phoneNumberUtil.isPossibleNumber("123-000", "US")); + } + + @Test + public void givenPhoneNumber_whenNumberGeographical_thenValid() throws NumberParseException { + + PhoneNumber phone = phoneNumberUtil.parse("+911234567890", "IN"); + assertTrue(phoneNumberUtil.isNumberGeographical(phone)); + + phone = new PhoneNumber().setCountryCode(1) + .setNationalNumber(2530000L); + assertFalse(phoneNumberUtil.isNumberGeographical(phone)); + + phone = new PhoneNumber().setCountryCode(800) + .setNationalNumber(12345678L); + assertFalse(phoneNumberUtil.isNumberGeographical(phone)); + } +} diff --git a/libraries-apache-commons/pom.xml b/libraries-apache-commons/pom.xml index 74adddabcf..08dddac880 100644 --- a/libraries-apache-commons/pom.xml +++ b/libraries-apache-commons/pom.xml @@ -65,7 +65,6 @@ - 3.6 1.1 1.9.3 1.2 diff --git a/libraries-data-2/README.md b/libraries-data-2/README.md index a8f2a0cb37..893d3e64e8 100644 --- a/libraries-data-2/README.md +++ b/libraries-data-2/README.md @@ -4,7 +4,7 @@ This module contains articles about libraries for data processing in Java. ### Relevant articles - [Introduction to Apache Flink with Java](https://www.baeldung.com/apache-flink) -- [Guide to the HyperLogLog Algorithm](https://www.baeldung.com/java-hyperloglog) +- [Guide to the HyperLogLog Algorithm in Java](https://www.baeldung.com/java-hyperloglog) - [Introduction to Conflict-Free Replicated Data Types](https://www.baeldung.com/java-conflict-free-replicated-data-types) - [Introduction to javax.measure](https://www.baeldung.com/javax-measure) - [A Guide to Infinispan in Java](https://www.baeldung.com/infinispan) diff --git a/libraries-data-2/pom.xml b/libraries-data-2/pom.xml index 26d8651cdd..0154823cca 100644 --- a/libraries-data-2/pom.xml +++ b/libraries-data-2/pom.xml @@ -168,7 +168,7 @@ 0.1.0 1.0.3 9.1.5.Final - 2.9.8 + 4.3.8.RELEASE 4.0.0 1.1.0 diff --git a/libraries-data/pom.xml b/libraries-data/pom.xml index 95d771ce4e..5adb490e96 100644 --- a/libraries-data/pom.xml +++ b/libraries-data/pom.xml @@ -80,7 +80,7 @@ commons-io commons-io - ${commons.io.version} + ${commons-io.version} provided @@ -165,7 +165,6 @@ 2.3 1.2 - 2.1 3.0.1 1.2.2 1.0.0 diff --git a/libraries-http-2/README.md b/libraries-http-2/README.md index 5ba45eb4a9..c0d6e76f1b 100644 --- a/libraries-http-2/README.md +++ b/libraries-http-2/README.md @@ -6,5 +6,6 @@ This module contains articles about HTTP libraries. - [Jetty ReactiveStreams HTTP Client](https://www.baeldung.com/jetty-reactivestreams-http-client) - [Decode an OkHttp JSON Response](https://www.baeldung.com/okhttp-json-response) +- [Retrofit 2 – Dynamic URL](https://www.baeldung.com/retrofit-dynamic-url) - More articles [[<-- prev]](/libraries-http) diff --git a/libraries-http-2/pom.xml b/libraries-http-2/pom.xml index 73fe6c66bd..d0bdb26bd4 100644 --- a/libraries-http-2/pom.xml +++ b/libraries-http-2/pom.xml @@ -66,16 +66,28 @@ reactive-streams ${reactive.stream.version} + + + + com.squareup.retrofit2 + retrofit + ${retrofit.version} + + + com.squareup.retrofit2 + converter-gson + ${retrofit.version} + 3.14.2 2.8.5 3.14.2 - 2.9.8 1.0.3 9.4.19.v20190610 2.2.11 + 2.3.0 5.1.9.RELEASE 1.0.3 3.2.12.RELEASE diff --git a/libraries-http-2/src/main/java/com/baeldung/retrofit/dynamic/GitHubDynamicApi.java b/libraries-http-2/src/main/java/com/baeldung/retrofit/dynamic/GitHubDynamicApi.java new file mode 100644 index 0000000000..5356c12b26 --- /dev/null +++ b/libraries-http-2/src/main/java/com/baeldung/retrofit/dynamic/GitHubDynamicApi.java @@ -0,0 +1,19 @@ +package com.baeldung.retrofit.dynamic; + +import com.baeldung.retrofit.models.Contributor; +import com.baeldung.retrofit.models.Repository; +import retrofit2.Call; +import retrofit2.http.GET; +import retrofit2.http.Path; +import retrofit2.http.Url; + +import java.util.List; + +public interface GitHubDynamicApi { + + @GET + Call> reposList(@Url String url); + + @GET("{fullUrl}") + Call> contributorsList(@Path(value = "fullUrl", encoded = true) String fullUrl); +} diff --git a/libraries-http-2/src/main/java/com/baeldung/retrofit/dynamic/GitHubDynamicApiApp.java b/libraries-http-2/src/main/java/com/baeldung/retrofit/dynamic/GitHubDynamicApiApp.java new file mode 100644 index 0000000000..06f6b3cef7 --- /dev/null +++ b/libraries-http-2/src/main/java/com/baeldung/retrofit/dynamic/GitHubDynamicApiApp.java @@ -0,0 +1,13 @@ +package com.baeldung.retrofit.dynamic; + +import java.io.IOException; +import java.util.List; + +public class GitHubDynamicApiApp { + + public static void main(String[] args) throws IOException { + String url = "https://api.github.com/users/eugenp/repos"; + List topContributors = new GitHubDynamicApiService().getTopContributors(url); + topContributors.forEach(System.out::println); + } +} diff --git a/libraries-http-2/src/main/java/com/baeldung/retrofit/dynamic/GitHubDynamicApiService.java b/libraries-http-2/src/main/java/com/baeldung/retrofit/dynamic/GitHubDynamicApiService.java new file mode 100644 index 0000000000..cb8e95f2d5 --- /dev/null +++ b/libraries-http-2/src/main/java/com/baeldung/retrofit/dynamic/GitHubDynamicApiService.java @@ -0,0 +1,44 @@ +package com.baeldung.retrofit.dynamic; + +import com.baeldung.retrofit.models.Contributor; +import com.baeldung.retrofit.models.Repository; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class GitHubDynamicApiService { + + private GitHubDynamicApi gitHubDynamicApi; + + GitHubDynamicApiService() { + Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.github.com/").addConverterFactory(GsonConverterFactory.create()).build(); + + gitHubDynamicApi = retrofit.create(GitHubDynamicApi.class); + } + + List getTopContributors(String url) throws IOException { + List repos = gitHubDynamicApi.reposList(url).execute().body(); + + repos = repos != null ? repos : Collections.emptyList(); + + return repos.stream().flatMap(repo -> getContributors("repos/eugenp/"+repo+"/contributors")).sorted((a, b) -> b.getContributions() - a.getContributions()).map(com.baeldung.retrofit.models.Contributor::getName).distinct().sorted().collect(Collectors.toList()); + } + + private Stream getContributors(String fullUrl) { + List contributors = null; + try { + contributors = gitHubDynamicApi.contributorsList(fullUrl).execute().body(); + } catch (IOException e) { + e.printStackTrace(); + } + + contributors = contributors != null ? contributors : Collections.emptyList(); + + return contributors.stream().filter(c -> c.getContributions() > 100); + } +} diff --git a/libraries-http-2/src/main/java/com/baeldung/retrofit/models/Contributor.java b/libraries-http-2/src/main/java/com/baeldung/retrofit/models/Contributor.java new file mode 100644 index 0000000000..f98b19de96 --- /dev/null +++ b/libraries-http-2/src/main/java/com/baeldung/retrofit/models/Contributor.java @@ -0,0 +1,33 @@ +package com.baeldung.retrofit.models; + +import com.google.gson.annotations.SerializedName; + +public class Contributor { + + @SerializedName("login") + private String name; + + private Integer contributions; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getContributions() { + return contributions; + } + + public void setContributions(Integer contributions) { + this.contributions = contributions; + } + + @Override + public String toString() { + return "Contributer [name=" + name + ", contributions=" + contributions + "]"; + } + +} diff --git a/libraries-http-2/src/main/java/com/baeldung/retrofit/models/Repository.java b/libraries-http-2/src/main/java/com/baeldung/retrofit/models/Repository.java new file mode 100644 index 0000000000..6bc91eb772 --- /dev/null +++ b/libraries-http-2/src/main/java/com/baeldung/retrofit/models/Repository.java @@ -0,0 +1,30 @@ +package com.baeldung.retrofit.models; + +public class Repository { + + private String name; + + private String description; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + @Override + public String toString() { + return "Repository [name=" + name + ", description=" + description + "]"; + } + +} diff --git a/kotlin-js/src/main/resources/logback.xml b/libraries-http-2/src/main/resources/logback.xml similarity index 100% rename from kotlin-js/src/main/resources/logback.xml rename to libraries-http-2/src/main/resources/logback.xml diff --git a/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/AbstractUnitTest.java b/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/AbstractUnitTest.java index 4a3e67a7c5..876586032a 100644 --- a/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/AbstractUnitTest.java +++ b/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/AbstractUnitTest.java @@ -3,23 +3,16 @@ package com.baeldung.jetty.httpclient; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; -import org.junit.After; -import org.junit.Before; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; public abstract class AbstractUnitTest { - protected HttpClient httpClient; - protected Server server; + protected static HttpClient httpClient; + protected static Server server; protected static final String CONTENT = "Hello World!"; - protected final int port = 9080; - - @Before - public void init() { - startServer(new RequestHandler()); - startClient(); - } - private void startClient() { + protected static void startClient() { httpClient = new HttpClient(); try { httpClient.start(); @@ -28,7 +21,7 @@ public abstract class AbstractUnitTest { } } - private void startServer(Handler handler) { + protected static void startServer(Handler handler, int port) { server = new Server(port); server.setHandler(handler); try { @@ -37,18 +30,9 @@ public abstract class AbstractUnitTest { e.printStackTrace(); } } - - @After - public void dispose() throws Exception { - if (httpClient != null) { - httpClient.stop(); - } - if (server != null) { - server.stop(); - } - } - - protected String uri() { + + protected String uri(int port) { return "http://localhost:" + port; } + } \ No newline at end of file diff --git a/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/ProjectReactorUnitTest.java b/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/ProjectReactorUnitTest.java index 6d79773609..db27ea1c89 100644 --- a/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/ProjectReactorUnitTest.java +++ b/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/ProjectReactorUnitTest.java @@ -4,18 +4,29 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.reactive.client.ReactiveRequest; import org.eclipse.jetty.reactive.client.ReactiveResponse; -import org.junit.Assert; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.reactivestreams.Publisher; import reactor.core.publisher.Mono; public class ProjectReactorUnitTest extends AbstractUnitTest { + protected static int port = 9080; + + @BeforeAll + public static void init() { + startServer(new RequestHandler(), port); + startClient(); + } + @Test public void givenReactiveClient_whenRequested_shouldReturn200() throws Exception { - Request request = httpClient.newRequest(uri()); + Request request = httpClient.newRequest(uri(port)); ReactiveRequest reactiveRequest = ReactiveRequest.newBuilder(request) .build(); Publisher publisher = reactiveRequest.response(); @@ -23,8 +34,19 @@ public class ProjectReactorUnitTest extends AbstractUnitTest { ReactiveResponse response = Mono.from(publisher) .block(); - Assert.assertNotNull(response); - Assert.assertEquals(response.getStatus(), HttpStatus.OK_200); + assertNotNull(response); + assertEquals(response.getStatus(), HttpStatus.OK_200); } + + @AfterAll + public static void dispose() throws Exception { + if (httpClient != null) { + httpClient.stop(); + } + if (server != null) { + server.stop(); + } + } + } diff --git a/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/ReactiveStreamsUnitTest.java b/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/ReactiveStreamsUnitTest.java index 3db4553c86..494d65e9e1 100644 --- a/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/ReactiveStreamsUnitTest.java +++ b/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/ReactiveStreamsUnitTest.java @@ -4,16 +4,27 @@ import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.reactive.client.ReactiveRequest; import org.eclipse.jetty.reactive.client.ReactiveResponse; -import org.junit.Assert; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.reactivestreams.Publisher; public class ReactiveStreamsUnitTest extends AbstractUnitTest { + + protected static int port = 9081; + + @BeforeAll + public static void init() { + startServer(new RequestHandler(), port); + startClient(); + } @Test public void givenReactiveClient_whenRequested_shouldReturn200() throws Exception { - Request request = httpClient.newRequest(uri()); + Request request = httpClient.newRequest(uri(port)); ReactiveRequest reactiveRequest = ReactiveRequest.newBuilder(request) .build(); Publisher publisher = reactiveRequest.response(); @@ -21,8 +32,18 @@ public class ReactiveStreamsUnitTest extends AbstractUnitTest { BlockingSubscriber subscriber = new BlockingSubscriber(); publisher.subscribe(subscriber); ReactiveResponse response = subscriber.block(); - Assert.assertNotNull(response); - Assert.assertEquals(response.getStatus(), HttpStatus.OK_200); + assertNotNull(response); + assertEquals(response.getStatus(), HttpStatus.OK_200); + } + + @AfterAll + public static void dispose() throws Exception { + if (httpClient != null) { + httpClient.stop(); + } + if (server != null) { + server.stop(); + } } } diff --git a/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/RxJava2UnitTest.java b/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/RxJava2UnitTest.java index dabd768702..a819eec475 100644 --- a/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/RxJava2UnitTest.java +++ b/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/RxJava2UnitTest.java @@ -10,8 +10,11 @@ import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.reactive.client.ReactiveRequest; import org.eclipse.jetty.reactive.client.ReactiveRequest.Event.Type; import org.eclipse.jetty.reactive.client.ReactiveResponse; -import org.junit.Assert; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.reactivestreams.Publisher; import org.springframework.http.MediaType; @@ -19,11 +22,19 @@ import io.reactivex.Flowable; import io.reactivex.Single; public class RxJava2UnitTest extends AbstractUnitTest { + + protected static int port = 9082; + + @BeforeAll + public static void init() { + startServer(new RequestHandler(), port); + startClient(); + } @Test public void givenReactiveClient_whenRequestedWithBody_ShouldReturnBody() throws Exception { - Request request = httpClient.newRequest(uri()); + Request request = httpClient.newRequest(uri(port)); ReactiveRequest reactiveRequest = ReactiveRequest.newBuilder(request) .content(ReactiveRequest.Content.fromString(CONTENT, MediaType.TEXT_PLAIN_VALUE, UTF_8)) .build(); @@ -32,12 +43,12 @@ public class RxJava2UnitTest extends AbstractUnitTest { String responseContent = Single.fromPublisher(publisher) .blockingGet(); - Assert.assertEquals(CONTENT, responseContent); + assertEquals(CONTENT, responseContent); } @Test public void givenReactiveClient_whenRequested_ShouldPrintEvents() throws Exception { - ReactiveRequest request = ReactiveRequest.newBuilder(httpClient, uri()) + ReactiveRequest request = ReactiveRequest.newBuilder(httpClient, uri(port)) .content(ReactiveRequest.Content.fromString(CONTENT, MediaType.TEXT_PLAIN_VALUE, UTF_8)) .build(); Publisher requestEvents = request.requestEvents(); @@ -58,10 +69,20 @@ public class RxJava2UnitTest extends AbstractUnitTest { int actualStatus = response.blockingGet() .getStatus(); - Assert.assertEquals(6, requestEventTypes.size()); - Assert.assertEquals(5, responseEventTypes.size()); + assertEquals(6, requestEventTypes.size()); + assertEquals(5, responseEventTypes.size()); - Assert.assertEquals(actualStatus, HttpStatus.OK_200); + assertEquals(actualStatus, HttpStatus.OK_200); + } + + @AfterAll + public static void dispose() throws Exception { + if (httpClient != null) { + httpClient.stop(); + } + if (server != null) { + server.stop(); + } } } \ No newline at end of file diff --git a/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/SpringWebFluxUnitTest.java b/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/SpringWebFluxUnitTest.java index 4a1a9bb2b5..f14fc38e1d 100644 --- a/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/SpringWebFluxUnitTest.java +++ b/libraries-http-2/src/test/java/com/baeldung/jetty/httpclient/SpringWebFluxUnitTest.java @@ -1,8 +1,11 @@ package com.baeldung.jetty.httpclient; import org.eclipse.jetty.client.HttpClient; -import org.junit.Assert; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.*; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.springframework.http.MediaType; import org.springframework.http.client.reactive.ClientHttpConnector; import org.springframework.http.client.reactive.JettyClientHttpConnector; @@ -12,25 +15,40 @@ import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; public class SpringWebFluxUnitTest extends AbstractUnitTest { - + + protected static int port = 9083; + + @BeforeAll + public static void init() { + startServer(new RequestHandler(), port); + startClient(); + } + @Test public void givenReactiveClient_whenRequested_shouldReturnResponse() throws Exception { - - HttpClient httpClient = new HttpClient(); - httpClient.start(); ClientHttpConnector clientConnector = new JettyClientHttpConnector(httpClient); WebClient client = WebClient.builder() .clientConnector(clientConnector) .build(); String responseContent = client.post() - .uri(uri()) + .uri(uri(port)) .contentType(MediaType.TEXT_PLAIN) .body(BodyInserters.fromPublisher(Mono.just(CONTENT), String.class)) .retrieve() .bodyToMono(String.class) .block(); - Assert.assertNotNull(responseContent); - Assert.assertEquals(CONTENT, responseContent); + assertNotNull(responseContent); + assertEquals(CONTENT, responseContent); + } + + @AfterAll + public static void dispose() throws Exception { + if (httpClient != null) { + httpClient.stop(); + } + if (server != null) { + server.stop(); + } } } \ No newline at end of file diff --git a/libraries-http/pom.xml b/libraries-http/pom.xml index cbc74ce132..257cb988d6 100644 --- a/libraries-http/pom.xml +++ b/libraries-http/pom.xml @@ -118,9 +118,9 @@ 2.8.5 4.5.3 - 2.9.8 + 3.6.2 - 3.14.2 + 4.9.1 1.23.0 2.2.0 2.3.0 diff --git a/libraries-security/pom.xml b/libraries-security/pom.xml index 202b3b8763..3b812f0d2c 100644 --- a/libraries-security/pom.xml +++ b/libraries-security/pom.xml @@ -21,7 +21,7 @@ org.springframework.security.oauth spring-security-oauth2 - ${spring-boot.version} + ${spring-security-oauth2.version} org.springframework @@ -88,6 +88,7 @@ 1.58 0.1.55 2.5.1 + 2.4.0.RELEASE diff --git a/machine-learning/README.md b/machine-learning/README.md deleted file mode 100644 index 80f2d2c6cd..0000000000 --- a/machine-learning/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles: - -- [Introduction to Supervised Learning in Kotlin](https://www.baeldung.com/kotlin-supervised-learning) diff --git a/machine-learning/pom.xml b/machine-learning/pom.xml deleted file mode 100644 index 842e488985..0000000000 --- a/machine-learning/pom.xml +++ /dev/null @@ -1,163 +0,0 @@ - - - 4.0.0 - machine-learning - 1.0-SNAPSHOT - machine-learning - jar - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - - - org.nd4j - nd4j-native-platform - ${dl4j.version} - - - org.deeplearning4j - deeplearning4j-core - ${dl4j.version} - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - - - org.jetbrains.kotlin - kotlin-test - ${kotlin.version} - test - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - - - - - src/main/kotlin - src/test - - - - - maven-clean-plugin - ${clean.plugin.version} - - - - maven-resources-plugin - ${resources.plugin.version} - - - maven-compiler-plugin - ${compiler.plugin.version} - - - maven-surefire-plugin - ${surefire.plugin.version} - - - maven-jar-plugin - ${jar.plugin.version} - - - maven-install-plugin - ${install.plugin.version} - - - maven-deploy-plugin - ${deploy.plugin.version} - - - - maven-site-plugin - ${site.plugin.version} - - - maven-project-info-reports-plugin - ${report.plugin.version} - - - - - - org.jetbrains.kotlin - kotlin-maven-plugin - ${kotlin.version} - - - compile - compile - - compile - - - - test-compile - test-compile - - test-compile - - - - - 1.8 - - - - org.apache.maven.plugins - maven-compiler-plugin - - - compile - compile - - compile - - - - testCompile - test-compile - - testCompile - - - - - - - - - UTF-8 - 1.7 - 1.7 - 1.3.50 - 0.9.1 - 3.1.0 - 3.0.2 - 3.0.2 - 3.8.0 - 2.22.1 - 2.5.2 - 2.8.2 - 3.7.1 - 3.0.0 - - - diff --git a/machine-learning/src/main/kotlin/com/baeldung/cnn/ConvolutionalNeuralNetwork.kt b/machine-learning/src/main/kotlin/com/baeldung/cnn/ConvolutionalNeuralNetwork.kt deleted file mode 100644 index b77fe273ae..0000000000 --- a/machine-learning/src/main/kotlin/com/baeldung/cnn/ConvolutionalNeuralNetwork.kt +++ /dev/null @@ -1,117 +0,0 @@ -package com.baeldung.cnn - -import org.datavec.api.records.reader.impl.collection.ListStringRecordReader -import org.datavec.api.split.ListStringSplit -import org.deeplearning4j.datasets.datavec.RecordReaderDataSetIterator -import org.deeplearning4j.eval.Evaluation -import org.deeplearning4j.nn.conf.NeuralNetConfiguration -import org.deeplearning4j.nn.conf.inputs.InputType -import org.deeplearning4j.nn.conf.layers.* -import org.deeplearning4j.nn.multilayer.MultiLayerNetwork -import org.deeplearning4j.nn.weights.WeightInit -import org.nd4j.linalg.activations.Activation -import org.nd4j.linalg.learning.config.Adam -import org.nd4j.linalg.lossfunctions.LossFunctions - -object ConvolutionalNeuralNetwork { - - @JvmStatic - fun main(args: Array) { - val dataset = ZalandoMNISTDataSet().load() - dataset.shuffle() - val trainDatasetIterator = createDatasetIterator(dataset.subList(0, 50_000)) - val testDatasetIterator = createDatasetIterator(dataset.subList(50_000, 60_000)) - - val cnn = buildCNN() - learning(cnn, trainDatasetIterator) - testing(cnn, testDatasetIterator) - } - - private fun createDatasetIterator(dataset: MutableList>): RecordReaderDataSetIterator { - val listStringRecordReader = ListStringRecordReader() - listStringRecordReader.initialize(ListStringSplit(dataset)) - return RecordReaderDataSetIterator(listStringRecordReader, 128, 28 * 28, 10) - } - - private fun buildCNN(): MultiLayerNetwork { - val multiLayerNetwork = MultiLayerNetwork(NeuralNetConfiguration.Builder() - .seed(123) - .l2(0.0005) - .updater(Adam()) - .weightInit(WeightInit.XAVIER) - .list() - .layer(0, buildInitialConvolutionLayer()) - .layer(1, buildBatchNormalizationLayer()) - .layer(2, buildPoolingLayer()) - .layer(3, buildConvolutionLayer()) - .layer(4, buildBatchNormalizationLayer()) - .layer(5, buildPoolingLayer()) - .layer(6, buildDenseLayer()) - .layer(7, buildBatchNormalizationLayer()) - .layer(8, buildDenseLayer()) - .layer(9, buildOutputLayer()) - .setInputType(InputType.convolutionalFlat(28, 28, 1)) - .backprop(true) - .build()) - multiLayerNetwork.init() - return multiLayerNetwork - } - - private fun buildOutputLayer(): OutputLayer? { - return OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD) - .nOut(10) - .activation(Activation.SOFTMAX) - .build() - } - - private fun buildDenseLayer(): DenseLayer? { - return DenseLayer.Builder().activation(Activation.RELU) - .nOut(500) - .dropOut(0.5) - .build() - } - - private fun buildPoolingLayer(): SubsamplingLayer? { - return SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.MAX) - .kernelSize(2, 2) - .stride(2, 2) - .build() - } - - private fun buildBatchNormalizationLayer() = BatchNormalization.Builder().build() - - private fun buildConvolutionLayer(): ConvolutionLayer? { - return ConvolutionLayer.Builder(5, 5) - .stride(1, 1) // nIn need not specified in later layers - .nOut(50) - .activation(Activation.IDENTITY) - .build() - } - - private fun buildInitialConvolutionLayer(): ConvolutionLayer? { - return ConvolutionLayer.Builder(5, 5) - .nIn(1) - .stride(1, 1) - .nOut(20) - .activation(Activation.IDENTITY) - .build() - } - - private fun learning(cnn: MultiLayerNetwork, trainSet: RecordReaderDataSetIterator) { - for (i in 0 until 10) { - cnn.fit(trainSet) - } - } - - private fun testing(cnn: MultiLayerNetwork, testSet: RecordReaderDataSetIterator) { - val evaluation = Evaluation(10) - while (testSet.hasNext()) { - val next = testSet.next() - val output = cnn.output(next.features) - evaluation.eval(next.labels, output) - } - - println(evaluation.stats()) - println(evaluation.confusionToString()) - } -} \ No newline at end of file diff --git a/machine-learning/src/main/kotlin/com/baeldung/cnn/ZalandoMNISTDataSet.kt b/machine-learning/src/main/kotlin/com/baeldung/cnn/ZalandoMNISTDataSet.kt deleted file mode 100644 index f29c8f2d0b..0000000000 --- a/machine-learning/src/main/kotlin/com/baeldung/cnn/ZalandoMNISTDataSet.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.baeldung.cnn - -import java.io.File -import java.nio.ByteBuffer -import java.util.* -import java.util.stream.Collectors -import kotlin.streams.asStream - -class ZalandoMNISTDataSet { - private val OFFSET_SIZE = 4 //in bytes - private val NUM_ITEMS_OFFSET = 4 - private val ITEMS_SIZE = 4 - private val ROWS = 28 - private val COLUMNS = 28 - private val IMAGE_OFFSET = 16 - private val IMAGE_SIZE = ROWS * COLUMNS - - fun load(): MutableList> { - val labelsFile = File("machine-learning/src/main/resources/train-labels-idx1-ubyte") - val imagesFile = File("machine-learning/src/main/resources/train-images-idx3-ubyte") - - val labelBytes = labelsFile.readBytes() - val imageBytes = imagesFile.readBytes() - - val byteLabelCount = Arrays.copyOfRange(labelBytes, NUM_ITEMS_OFFSET, NUM_ITEMS_OFFSET + ITEMS_SIZE) - val numberOfLabels = ByteBuffer.wrap(byteLabelCount).int - - val list = mutableListOf>() - - for (i in 0 until numberOfLabels) { - val label = labelBytes[OFFSET_SIZE + ITEMS_SIZE + i] - val startBoundary = i * IMAGE_SIZE + IMAGE_OFFSET - val endBoundary = i * IMAGE_SIZE + IMAGE_OFFSET + IMAGE_SIZE - val imageData = Arrays.copyOfRange(imageBytes, startBoundary, endBoundary) - - val imageDataList = imageData.iterator() - .asSequence() - .asStream().map { b -> b.toString() } - .collect(Collectors.toList()) - imageDataList.add(label.toString()) - list.add(imageDataList) - } - return list - } -} \ No newline at end of file diff --git a/machine-learning/src/main/kotlin/com/baeldung/simplelinearregression/SimpleLinearRegression.kt b/machine-learning/src/main/kotlin/com/baeldung/simplelinearregression/SimpleLinearRegression.kt deleted file mode 100644 index 5ab520924e..0000000000 --- a/machine-learning/src/main/kotlin/com/baeldung/simplelinearregression/SimpleLinearRegression.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.baeldung.simplelinearregression - -import kotlin.math.pow - -class SimpleLinearRegression(private val xs: List, private val ys: List) { - var slope: Double = 0.0 - var yIntercept: Double = 0.0 - - init { - val covariance = calculateCovariance(xs, ys) - val variance = calculateVariance(xs) - slope = calculateSlope(covariance, variance) - yIntercept = calculateYIntercept(ys, slope, xs) - } - - fun predict(independentVariable: Double) = slope * independentVariable + yIntercept - - fun calculateRSquared(): Double { - val sst = ys.sumByDouble { y -> (y - ys.average()).pow(2) } - val ssr = xs.zip(ys) { x, y -> (y - predict(x.toDouble())).pow(2) }.sum() - return (sst - ssr) / sst - } - - private fun calculateYIntercept(ys: List, slope: Double, xs: List) = ys.average() - slope * xs.average() - - private fun calculateSlope(covariance: Double, variance: Double) = covariance / variance - - private fun calculateCovariance(xs: List, ys: List) = xs.zip(ys) { x, y -> (x - xs.average()) * (y - ys.average()) }.sum() - - private fun calculateVariance(xs: List) = xs.sumByDouble { x -> (x - xs.average()).pow(2) } -} \ No newline at end of file diff --git a/machine-learning/src/main/resources/train-labels-idx1-ubyte b/machine-learning/src/main/resources/train-labels-idx1-ubyte deleted file mode 100644 index 30424ca2ea..0000000000 Binary files a/machine-learning/src/main/resources/train-labels-idx1-ubyte and /dev/null differ diff --git a/machine-learning/src/test/com/baeldung/simplelinearregression/SimpleLinearRegressionUnitTest.kt b/machine-learning/src/test/com/baeldung/simplelinearregression/SimpleLinearRegressionUnitTest.kt deleted file mode 100644 index a741639d50..0000000000 --- a/machine-learning/src/test/com/baeldung/simplelinearregression/SimpleLinearRegressionUnitTest.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.baeldung.simplelinearregression - -import org.junit.Assert.assertEquals -import org.junit.jupiter.api.Test - -class SimpleLinearRegressionUnitTest { - @Test - fun givenAProperDataSetWhenFedToASimpleLinearRegressionModelThenItPredictsCorrectly() { - val xs = arrayListOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - val ys = arrayListOf(25, 35, 49, 60, 75, 90, 115, 130, 150, 200) - - val model = SimpleLinearRegression(xs, ys) - - val predictionOne = model.predict(2.5) - assertEquals(38.99, predictionOne, 0.01) - - val predictionTwo = model.predict(7.5) - assertEquals(128.84, predictionTwo, 0.01) - } - - @Test - fun givenAPredictableDataSetWhenCalculatingTheLossFunctionThenTheModelIsConsideredReliable() { - val xs = arrayListOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - val ys = arrayListOf(25, 35, 49, 60, 75, 90, 115, 130, 150, 200) - - val model = SimpleLinearRegression(xs, ys) - - assertEquals(0.95, model.calculateRSquared(), 0.01) - } - - @Test - fun givenAnUnpredictableDataSetWhenCalculatingTheLossFunctionThenTheModelIsConsideredUnreliable() { - val xs = arrayListOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) - val ys = arrayListOf(200, 0, 200, 0, 0, 0, -115, 1000, 0, 1) - - val model = SimpleLinearRegression(xs, ys) - - assertEquals(0.01, model.calculateRSquared(), 0.01) - } -} \ No newline at end of file diff --git a/maven-modules/README.md b/maven-modules/README.md index 1ef664f879..19f0473a58 100644 --- a/maven-modules/README.md +++ b/maven-modules/README.md @@ -7,3 +7,4 @@ This module contains articles about Apache Maven. Please refer to its submodules - [Apache Maven Tutorial](https://www.baeldung.com/maven) - [Apache Maven Standard Directory Layout](https://www.baeldung.com/maven-directory-structure) - [Multi-Module Project with Maven](https://www.baeldung.com/maven-multi-module) +- [Maven Packaging Types](https://www.baeldung.com/maven-packaging-types) diff --git a/maven-modules/maven-plugins/custom-rule/pom.xml b/maven-modules/maven-plugins/custom-rule/pom.xml index 0fb551e71b..075a5c7943 100644 --- a/maven-modules/maven-plugins/custom-rule/pom.xml +++ b/maven-modules/maven-plugins/custom-rule/pom.xml @@ -51,4 +51,17 @@ 1.0-alpha-9 + + + + maven-verifier-plugin + ${maven.verifier.version} + + ../input-resources/verifications.xml + false + + + + + diff --git a/maven-modules/maven-plugins/pom.xml b/maven-modules/maven-plugins/pom.xml index 4877f00a92..9f28871ec0 100644 --- a/maven-modules/maven-plugins/pom.xml +++ b/maven-modules/maven-plugins/pom.xml @@ -15,7 +15,7 @@ - + custom-rule maven-enforcer diff --git a/maven-modules/versions-maven-plugin/original/pom.xml b/maven-modules/versions-maven-plugin/original/pom.xml index f705dae5c5..c36a5913c2 100644 --- a/maven-modules/versions-maven-plugin/original/pom.xml +++ b/maven-modules/versions-maven-plugin/original/pom.xml @@ -74,7 +74,6 @@ 1.15 2.3 4.0 - 3.0 1.9.1 2.7 diff --git a/maven-modules/versions-maven-plugin/pom.xml b/maven-modules/versions-maven-plugin/pom.xml index 3a9134ff40..ff49811430 100644 --- a/maven-modules/versions-maven-plugin/pom.xml +++ b/maven-modules/versions-maven-plugin/pom.xml @@ -74,8 +74,8 @@ 2.3 2.7 1.9.1 - 3.0 4.0 + 3.11 \ No newline at end of file diff --git a/metrics/pom.xml b/metrics/pom.xml index 92699c3fb8..07adf15936 100644 --- a/metrics/pom.xml +++ b/metrics/pom.xml @@ -66,12 +66,12 @@ com.fasterxml.jackson.core jackson-databind - ${fasterxml.jackson.version} + ${jackson.version} com.fasterxml.jackson.dataformat jackson-dataformat-smile - ${fasterxml.jackson.version} + ${jackson.version} @@ -93,7 +93,7 @@ 3.1.0 0.12.17 0.12.0.RELEASE - 2.9.1 + 2.0.7.RELEASE 3.11.1 1.1.0 diff --git a/netflix-modules/README.md b/netflix-modules/README.md index c126bbdf5b..21d6958dab 100644 --- a/netflix-modules/README.md +++ b/netflix-modules/README.md @@ -2,3 +2,6 @@ This module contains articles about Netflix. +### Relevant Articles: + +- [Introduction to Netflix Mantis](https://www.baeldung.com/java-netflix-mantis) diff --git a/netflix-modules/mantis/pom.xml b/netflix-modules/mantis/pom.xml new file mode 100644 index 0000000000..5d9611ccdf --- /dev/null +++ b/netflix-modules/mantis/pom.xml @@ -0,0 +1,78 @@ + + + 4.0.0 + mantis + Mantis + jar + Sample project for Netflix Mantis + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + + org.springframework.boot + spring-boot-starter + 2.1.3.RELEASE + + + + io.mantisrx + mantis-runtime + 1.2.63 + + + org.slf4j + slf4j-log4j12 + + + + + + com.fasterxml.jackson.core + jackson-databind + 2.10.2 + + + + net.andreinc.mockneat + mockneat + 0.3.8 + + + + org.projectlombok + lombok + 1.18.12 + + + + org.springframework + spring-webflux + 5.0.9.RELEASE + test + + + + io.projectreactor.netty + reactor-netty + 0.9.12.RELEASE + test + + + + + + + SpringLibReleaseRepo + https://repo.spring.io/libs-release/ + + + + diff --git a/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/MantisApplication.java b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/MantisApplication.java new file mode 100644 index 0000000000..d5ffe977c3 --- /dev/null +++ b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/MantisApplication.java @@ -0,0 +1,23 @@ +package com.baeldung.netflix.mantis; + +import com.baeldung.netflix.mantis.job.LogAggregationJob; +import io.mantisrx.runtime.executor.LocalJobExecutorNetworked; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@Slf4j +@SpringBootApplication +public class MantisApplication implements CommandLineRunner { + + public static void main(String[] args) { + SpringApplication.run(MantisApplication.class, args); + } + + @Override + public void run(String... args) { + LocalJobExecutorNetworked.execute(new LogAggregationJob().getJobInstance()); + } + +} diff --git a/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/job/LogAggregationJob.java b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/job/LogAggregationJob.java new file mode 100644 index 0000000000..7fc514deef --- /dev/null +++ b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/job/LogAggregationJob.java @@ -0,0 +1,37 @@ +package com.baeldung.netflix.mantis.job; + +import com.baeldung.netflix.mantis.model.LogAggregate; +import com.baeldung.netflix.mantis.source.RandomLogSource; +import com.baeldung.netflix.mantis.stage.CountLogStage; +import com.baeldung.netflix.mantis.stage.GroupLogStage; +import com.baeldung.netflix.mantis.stage.TransformLogStage; +import io.mantisrx.runtime.Job; +import io.mantisrx.runtime.MantisJob; +import io.mantisrx.runtime.MantisJobProvider; +import io.mantisrx.runtime.Metadata; +import io.mantisrx.runtime.sink.Sink; +import io.mantisrx.runtime.sink.Sinks; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +public class LogAggregationJob extends MantisJobProvider { + + private Sink sink = Sinks.eagerSubscribe(Sinks.sse(LogAggregate::toJsonString)); + + @Override + public Job getJobInstance() { + + return MantisJob + .source(new RandomLogSource()) + .stage(new TransformLogStage(), TransformLogStage.stageConfig()) + .stage(new GroupLogStage(), GroupLogStage.config()) + .stage(new CountLogStage(), CountLogStage.config()) + .sink(sink) + .metadata(new Metadata.Builder().build()) + .create(); + + } + +} diff --git a/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/job/LogCollectingJob.java b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/job/LogCollectingJob.java new file mode 100644 index 0000000000..34ccf8355a --- /dev/null +++ b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/job/LogCollectingJob.java @@ -0,0 +1,34 @@ +package com.baeldung.netflix.mantis.job; + +import com.baeldung.netflix.mantis.model.LogEvent; +import com.baeldung.netflix.mantis.sink.LogSink; +import com.baeldung.netflix.mantis.source.RandomLogSource; +import com.baeldung.netflix.mantis.stage.TransformLogStage; +import io.mantisrx.runtime.Job; +import io.mantisrx.runtime.MantisJob; +import io.mantisrx.runtime.MantisJobProvider; +import io.mantisrx.runtime.Metadata; +import io.mantisrx.runtime.ScalarToScalar; +import io.mantisrx.runtime.sink.Sink; +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; + +@NoArgsConstructor +@AllArgsConstructor +public class LogCollectingJob extends MantisJobProvider { + + private Sink sink = new LogSink(); + + @Override + public Job getJobInstance() { + + return MantisJob + .source(new RandomLogSource()) + .stage(new TransformLogStage(), new ScalarToScalar.Config<>()) + .sink(sink) + .metadata(new Metadata.Builder().build()) + .create(); + + } + +} diff --git a/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/model/LogAggregate.java b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/model/LogAggregate.java new file mode 100644 index 0000000000..e0e3c4f9fa --- /dev/null +++ b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/model/LogAggregate.java @@ -0,0 +1,28 @@ +package com.baeldung.netflix.mantis.model; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mantisrx.runtime.codec.JsonType; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class LogAggregate implements JsonType { + + private static final ObjectMapper mapper = new ObjectMapper(); + + private Integer count; + private String level; + + public String toJsonString() { + try { + return mapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + return null; + } + } + +} diff --git a/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/model/LogEvent.java b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/model/LogEvent.java new file mode 100644 index 0000000000..a48dfcd5dd --- /dev/null +++ b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/model/LogEvent.java @@ -0,0 +1,35 @@ +package com.baeldung.netflix.mantis.model; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mantisrx.runtime.codec.JsonType; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +public class LogEvent implements JsonType { + + private static final ObjectMapper mapper = new ObjectMapper(); + + private Long index; + private String level; + private String message; + + public LogEvent(String[] parts) { + this.index = Long.valueOf(parts[0]); + this.level = parts[1]; + this.message = parts[2]; + } + + public String toJsonString() { + try { + return mapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + return null; + } + } + +} diff --git a/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/sink/LogSink.java b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/sink/LogSink.java new file mode 100644 index 0000000000..ae2177bf87 --- /dev/null +++ b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/sink/LogSink.java @@ -0,0 +1,37 @@ +package com.baeldung.netflix.mantis.sink; + +import com.baeldung.netflix.mantis.model.LogEvent; +import io.mantisrx.runtime.Context; +import io.mantisrx.runtime.PortRequest; +import io.mantisrx.runtime.sink.SelfDocumentingSink; +import io.mantisrx.runtime.sink.ServerSentEventsSink; +import io.mantisrx.runtime.sink.Sink; +import io.mantisrx.runtime.sink.predicate.Predicate; +import rx.Observable; + +public class LogSink implements Sink { + + @Override + public void call(Context context, PortRequest portRequest, Observable logEventObservable) { + + SelfDocumentingSink sink = new ServerSentEventsSink.Builder() + .withEncoder(LogEvent::toJsonString) + .withPredicate(filterByLogMessage()) + .build(); + + logEventObservable.subscribe(); + + sink.call(context, portRequest, logEventObservable); + } + + private Predicate filterByLogMessage() { + return new Predicate<>("filter by message", + parameters -> { + if (parameters != null && parameters.containsKey("filter")) { + return logEvent -> logEvent.getMessage().contains(parameters.get("filter").get(0)); + } + return logEvent -> true; + }); + } + +} diff --git a/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/source/RandomLogSource.java b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/source/RandomLogSource.java new file mode 100644 index 0000000000..fe607d9866 --- /dev/null +++ b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/source/RandomLogSource.java @@ -0,0 +1,46 @@ +package com.baeldung.netflix.mantis.source; + +import io.mantisrx.runtime.Context; +import io.mantisrx.runtime.source.Index; +import io.mantisrx.runtime.source.Source; +import lombok.extern.slf4j.Slf4j; +import net.andreinc.mockneat.MockNeat; +import rx.Observable; + +import java.util.Date; +import java.util.concurrent.TimeUnit; + +@Slf4j +public class RandomLogSource implements Source { + + private MockNeat mockDataGenerator; + + @Override + public void init(Context context, Index index) { + mockDataGenerator = MockNeat.threadLocal(); + } + + @Override + public Observable> call(Context context, Index index) { + return Observable.just( + Observable + .interval(250, TimeUnit.MILLISECONDS) + .map(this::createRandomLogEvent)); + } + + private String createRandomLogEvent(Long tick) { + String level = mockDataGenerator.probabilites(String.class) + .add(0.5, "INFO") + .add(0.3, "WARN") + .add(0.2, "ERROR") + .get(); + + String message = mockDataGenerator.probabilites(String.class) + .add(0.5, "login attempt") + .add(0.5, "user created") + .get(); + + return tick + "#" + level + "#" + message; + } + +} diff --git a/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/stage/CountLogStage.java b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/stage/CountLogStage.java new file mode 100644 index 0000000000..5f02d783d0 --- /dev/null +++ b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/stage/CountLogStage.java @@ -0,0 +1,58 @@ +package com.baeldung.netflix.mantis.stage; + +import com.baeldung.netflix.mantis.model.LogAggregate; +import com.baeldung.netflix.mantis.model.LogEvent; +import io.mantisrx.common.MantisGroup; +import io.mantisrx.runtime.Context; +import io.mantisrx.runtime.GroupToScalar; +import io.mantisrx.runtime.codec.JacksonCodecs; +import io.mantisrx.runtime.computation.GroupToScalarComputation; +import io.mantisrx.runtime.parameter.ParameterDefinition; +import io.mantisrx.runtime.parameter.type.IntParameter; +import io.mantisrx.runtime.parameter.validator.Validators; +import rx.Observable; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class CountLogStage implements GroupToScalarComputation { + + private int duration; + + @Override + public void init(Context context) { + duration = (int)context.getParameters().get("LogAggregationDuration", 1000); + } + + @Override + public Observable call(Context context, Observable> mantisGroup) { + return mantisGroup + .window(duration, TimeUnit.MILLISECONDS) + .flatMap(o -> o.groupBy(MantisGroup::getKeyValue) + .flatMap(group -> group.reduce(0, (count, value) -> count = count + 1) + .map((count) -> new LogAggregate(count, group.getKey())) + )); + } + + public static GroupToScalar.Config config(){ + return new GroupToScalar.Config() + .description("sum events for a log level") + .codec(JacksonCodecs.pojo(LogAggregate.class)) + .withParameters(getParameters()); + } + + public static List> getParameters() { + List> params = new ArrayList<>(); + + params.add(new IntParameter() + .name("LogAggregationDuration") + .description("window size for aggregation in milliseconds") + .validator(Validators.range(100, 10000)) + .defaultValue(5000) + .build()) ; + + return params; + } + +} diff --git a/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/stage/GroupLogStage.java b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/stage/GroupLogStage.java new file mode 100644 index 0000000000..f21c4aba7d --- /dev/null +++ b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/stage/GroupLogStage.java @@ -0,0 +1,25 @@ +package com.baeldung.netflix.mantis.stage; + +import com.baeldung.netflix.mantis.model.LogEvent; +import io.mantisrx.common.MantisGroup; +import io.mantisrx.runtime.Context; +import io.mantisrx.runtime.ScalarToGroup; +import io.mantisrx.runtime.codec.JacksonCodecs; +import io.mantisrx.runtime.computation.ToGroupComputation; +import rx.Observable; + +public class GroupLogStage implements ToGroupComputation { + + @Override + public Observable> call(Context context, Observable logEvent) { + return logEvent.map(log -> new MantisGroup<>(log.getLevel(), log)); + } + + public static ScalarToGroup.Config config(){ + return new ScalarToGroup.Config() + .description("Group event data by level") + .codec(JacksonCodecs.pojo(LogEvent.class)) + .concurrentInput(); + } + +} diff --git a/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/stage/TransformLogStage.java b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/stage/TransformLogStage.java new file mode 100644 index 0000000000..33e6567d13 --- /dev/null +++ b/netflix-modules/mantis/src/main/java/com/baeldung/netflix/mantis/stage/TransformLogStage.java @@ -0,0 +1,24 @@ +package com.baeldung.netflix.mantis.stage; + +import com.baeldung.netflix.mantis.model.LogEvent; +import io.mantisrx.runtime.Context; +import io.mantisrx.runtime.ScalarToScalar; +import io.mantisrx.runtime.codec.JacksonCodecs; +import io.mantisrx.runtime.computation.ScalarComputation; +import rx.Observable; + +public class TransformLogStage implements ScalarComputation { + + @Override + public Observable call(Context context, Observable logEntry) { + return logEntry + .map(log -> log.split("#")) + .filter(parts -> parts.length == 3) + .map(LogEvent::new); + } + + public static ScalarToScalar.Config stageConfig() { + return new ScalarToScalar.Config() + .codec(JacksonCodecs.pojo(LogEvent.class)); + } +} diff --git a/netflix-modules/mantis/src/test/java/com/baeldung/netflix/mantis/job/LogAggregationJobIntegrationTest.java b/netflix-modules/mantis/src/test/java/com/baeldung/netflix/mantis/job/LogAggregationJobIntegrationTest.java new file mode 100644 index 0000000000..b9b16e2146 --- /dev/null +++ b/netflix-modules/mantis/src/test/java/com/baeldung/netflix/mantis/job/LogAggregationJobIntegrationTest.java @@ -0,0 +1,56 @@ +package com.baeldung.netflix.mantis.job; + +import com.baeldung.netflix.mantis.model.LogAggregate; +import io.mantisrx.runtime.PortRequest; +import io.mantisrx.runtime.sink.Sinks; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import static java.util.Arrays.asList; +import static java.util.Optional.of; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class LogAggregationJobIntegrationTest extends MantisJobTestBase { + + private final static int PORT = 7382; + private final static String SINK_URL = "http://localhost:" + PORT; + + @BeforeAll + static void beforeAll() { + start(new LogAggregationJob((context, portRequest, logAggregateObservable) -> { + logAggregateObservable.subscribe(); + Sinks.sse(LogAggregate::toJsonString).call(context, new PortRequest(PORT), logAggregateObservable); + })); + } + + @Override + public String getSinkUrl() { + return SINK_URL; + } + + @Override + public Class getEventType() { + return LogAggregate.class; + } + + @Test + void whenReadingFromSink_thenShouldRetrieveCorrectNumberOfLogAggregates() { + assertEquals(of(5L), sinkStream.take(5).count().blockOptional()); + } + + @Test + void whenReadingFromSink_thenShouldRetrieveLogAggregate() { + assertNotNull(sinkStream.take(1).blockFirst()); + } + + @Test + void whenReadingFromSink_thenShouldRetrieveValidLogAggregate() { + LogAggregate logAggregate = sinkStream.take(1).blockFirst(); + + assertTrue(asList("ERROR", "WARN", "INFO").contains(logAggregate.getLevel())); + assertTrue(logAggregate.getCount() > 0); + } + +} \ No newline at end of file diff --git a/netflix-modules/mantis/src/test/java/com/baeldung/netflix/mantis/job/LogCollectingJobIntegrationTest.java b/netflix-modules/mantis/src/test/java/com/baeldung/netflix/mantis/job/LogCollectingJobIntegrationTest.java new file mode 100644 index 0000000000..87e0c194b5 --- /dev/null +++ b/netflix-modules/mantis/src/test/java/com/baeldung/netflix/mantis/job/LogCollectingJobIntegrationTest.java @@ -0,0 +1,73 @@ +package com.baeldung.netflix.mantis.job; + +import com.baeldung.netflix.mantis.model.LogEvent; +import com.baeldung.netflix.mantis.sink.LogSink; +import io.mantisrx.runtime.Context; +import io.mantisrx.runtime.PortRequest; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import rx.Observable; + +import static java.util.Arrays.asList; +import static java.util.Optional.of; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class LogCollectingJobIntegrationTest extends MantisJobTestBase { + + private final static int PORT = 7381; + private final static String SINK_URL = "http://localhost:" + PORT; + + @BeforeAll + static void beforeAll() { + + start(new LogCollectingJob(new LogSink() { + + @Override + public void call(Context context, PortRequest portRequest, Observable observable) { + super.call(context, new PortRequest(PORT), observable); + } + + })); + + } + + @Override + public String getSinkUrl() { + return SINK_URL; + } + + @Override + public Class getEventType() { + return LogEvent.class; + } + + @Test + void whenReadingFromSink_thenShouldRetrieveCorrectNumberOfLogEvents() { + assertEquals(of(5L), sinkStream.take(5).count().blockOptional()); + } + + @Test + void whenReadingFromSink_thenShouldRetrieveLogEvent() { + assertNotNull(sinkStream.take(1).blockFirst()); + } + + @Test + void whenReadingFromSink_thenShouldRetrieveValidLogEvent() { + LogEvent logEvent = sinkStream.take(1).blockFirst(); + + assertTrue(asList("ERROR", "WARN", "INFO").contains(logEvent.getLevel())); + assertTrue(asList("login attempt", "user created").contains(logEvent.getMessage())); + } + + @Test + void whenReadingFromSink_thenShouldRetrieveFilteredLogEvents() { + getSinkStream(SINK_URL + "?filter=login") + .take(7) + .toStream().forEach( + logEvent -> assertEquals("login attempt", logEvent.getMessage()) + ); + } + +} \ No newline at end of file diff --git a/netflix-modules/mantis/src/test/java/com/baeldung/netflix/mantis/job/MantisJobTestBase.java b/netflix-modules/mantis/src/test/java/com/baeldung/netflix/mantis/job/MantisJobTestBase.java new file mode 100644 index 0000000000..89425299a4 --- /dev/null +++ b/netflix-modules/mantis/src/test/java/com/baeldung/netflix/mantis/job/MantisJobTestBase.java @@ -0,0 +1,49 @@ +package com.baeldung.netflix.mantis.job; + +import io.mantisrx.runtime.Job; +import io.mantisrx.runtime.MantisJobProvider; +import io.mantisrx.runtime.executor.LocalJobExecutorNetworked; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Flux; +import reactor.util.retry.Retry; + +import java.time.Duration; + +public abstract class MantisJobTestBase { + + private static Job jobInstance; + Flux sinkStream; + + public abstract String getSinkUrl(); + public abstract Class getEventType(); + + @BeforeEach + void setUp() { + sinkStream = getSinkStream(getSinkUrl()); + } + + @AfterAll + static void afterAll() { + stopJob(); + } + + protected Flux getSinkStream(String sinkUrl) { + return WebClient.builder().build().get() + .uri(sinkUrl) + .retrieve() + .bodyToFlux(getEventType()) + .retryWhen(Retry.fixedDelay(10, Duration.ofMillis(2000))); + } + + static void start(MantisJobProvider job) { + jobInstance = job.getJobInstance(); + new Thread(() -> LocalJobExecutorNetworked.execute(jobInstance)).start(); + } + + static void stopJob() { + jobInstance.getLifecycle().shutdown(); + } + +} diff --git a/netflix-modules/pom.xml b/netflix-modules/pom.xml index 9ed22498d8..538126fb34 100644 --- a/netflix-modules/pom.xml +++ b/netflix-modules/pom.xml @@ -15,6 +15,7 @@ genie + mantis \ No newline at end of file diff --git a/parent-boot-2/pom.xml b/parent-boot-2/pom.xml index dab9f015b3..ace3e538c9 100644 --- a/parent-boot-2/pom.xml +++ b/parent-boot-2/pom.xml @@ -82,8 +82,10 @@ 3.3.0 1.0.22.RELEASE - 2.3.3.RELEASE + 2.4.0 1.9.1 + + 3.4.0 diff --git a/parent-java/pom.xml b/parent-java/pom.xml index d251adcdd3..9170f45bbe 100644 --- a/parent-java/pom.xml +++ b/parent-java/pom.xml @@ -27,7 +27,7 @@ commons-io commons-io - ${commons.io.version} + ${commons-io.version} org.openjdk.jmh @@ -43,7 +43,6 @@ 29.0-jre - 2.6 1.19 2.3.7 2.2 diff --git a/parent-kotlin/README.md b/parent-kotlin/README.md deleted file mode 100644 index c78ecbac42..0000000000 --- a/parent-kotlin/README.md +++ /dev/null @@ -1,3 +0,0 @@ -## Parent Kotlin - -This is a parent module for all projects using Kotlin diff --git a/parent-kotlin/pom.xml b/parent-kotlin/pom.xml deleted file mode 100644 index 947dd20483..0000000000 --- a/parent-kotlin/pom.xml +++ /dev/null @@ -1,223 +0,0 @@ - - - 4.0.0 - parent-kotlin - parent-kotlin - pom - Parent for all kotlin modules - - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - - - - - jcenter - https://jcenter.bintray.com - - - kotlin-ktor - https://dl.bintray.com/kotlin/ktor/ - - - kotlin-eap - https://dl.bintray.com/kotlin/kotlin-eap - - - spring-milestone - Spring Milestone Repository - https://repo.spring.io/milestone - - - - - - kotlin-eap - https://dl.bintray.com/kotlin/kotlin-eap - - - - - - - org.springframework.boot - spring-boot-dependencies - ${boot.dependencies.version} - pom - import - - - - - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - - - org.jetbrains.kotlin - kotlin-stdlib - - - org.jetbrains.kotlin - kotlin-reflect - - - - org.jetbrains.kotlinx - kotlinx-coroutines-core - ${kotlinx.version} - - - - io.ktor - ktor-server-netty - ${ktor.io.version} - - - io.ktor - ktor-gson - ${ktor.io.version} - - - com.fasterxml.jackson.module - jackson-module-kotlin - - - - org.jetbrains.kotlin - kotlin-test-junit - test - - - - - - - - org.jetbrains.kotlin - kotlin-maven-plugin - ${kotlin.version} - - - compile - - compile - - - - ${project.basedir}/src/main/kotlin - ${project.basedir}/src/main/java - - ${java.version} - - -Xjvm-default=enable - - - - - test-compile - - test-compile - - - - ${project.basedir}/src/test/kotlin - ${project.basedir}/src/test/java - - ${java.version} - - - - - - spring - - - - - org.jetbrains.kotlin - kotlin-maven-allopen - ${kotlin.version} - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - ${java.version} - ${java.version} - - - - - default-compile - none - - - - default-testCompile - none - - - java-compile - compile - - compile - - - - java-test-compile - test-compile - - testCompile - - - - - - org.apache.maven.plugins - maven-failsafe-plugin - ${maven-failsafe-plugin.version} - - - org.junit.platform - junit-platform-surefire-provider - ${junit.platform.version} - - - - - junit5 - - integration-test - verify - - - - **/*Test5.java - - - - - - - - - - 1.3.30 - 1.0.0 - 0.9.5 - 3.12.0 - 1.3.2 - 2.2.0.M4 - - - diff --git a/patterns/clean-architecture/README.md b/patterns/clean-architecture/README.md new file mode 100644 index 0000000000..aad8608447 --- /dev/null +++ b/patterns/clean-architecture/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Clean Architecture with Spring Boot](https://www.baeldung.com/spring-boot-clean-architecture) diff --git a/patterns/clean-architecture/pom.xml b/patterns/clean-architecture/pom.xml new file mode 100644 index 0000000000..6e7de78751 --- /dev/null +++ b/patterns/clean-architecture/pom.xml @@ -0,0 +1,87 @@ + + + 4.0.0 + clean-architecture + 1.0 + clean-architecture + Project for clean architecture in java + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + 1.8 + + + + + com.h2database + h2 + runtime + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.junit.jupiter + junit-jupiter-engine + test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + org.mockito + mockito-core + test + + + org.junit.platform + junit-platform-engine + + + org.junit.jupiter + junit-jupiter-engine + + + org.junit.jupiter + junit-jupiter-api + + + org.junit.platform + junit-platform-runner + test + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/CleanArchitectureApplication.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/CleanArchitectureApplication.java new file mode 100644 index 0000000000..ebac2bacf3 --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/CleanArchitectureApplication.java @@ -0,0 +1,40 @@ +package com.baeldung.pattern.cleanarchitecture; + +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.core.type.filter.TypeFilter; + +@SpringBootApplication +public class CleanArchitectureApplication { + + public static void main(String[] args) { + SpringApplication.run(CleanArchitectureApplication.class); + } + + @Bean + BeanFactoryPostProcessor beanFactoryPostProcessor(ApplicationContext beanRegistry) { + return beanFactory -> { + genericApplicationContext((BeanDefinitionRegistry) ((AnnotationConfigServletWebServerApplicationContext) beanRegistry).getBeanFactory()); + }; + } + + void genericApplicationContext(BeanDefinitionRegistry beanRegistry) { + ClassPathBeanDefinitionScanner beanDefinitionScanner = new ClassPathBeanDefinitionScanner(beanRegistry); + beanDefinitionScanner.addIncludeFilter(removeModelAndEntitiesFilter()); + beanDefinitionScanner.scan("com.baeldung.pattern.cleanarchitecture"); + } + + static TypeFilter removeModelAndEntitiesFilter() { + return (MetadataReader mr, MetadataReaderFactory mrf) -> !mr.getClassMetadata() + .getClassName() + .endsWith("Model"); + } +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/CommonUser.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/CommonUser.java new file mode 100644 index 0000000000..c4f105fad5 --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/CommonUser.java @@ -0,0 +1,30 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +class CommonUser implements User { + + String name; + String password; + + CommonUser(String name, String password) { + this.name = name; + this.password = password; + } + + CommonUser() { + } + + @Override + public boolean passwordIsValid() { + return password != null && password.length() > 5; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getPassword() { + return password; + } +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/CommonUserFactory.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/CommonUserFactory.java new file mode 100644 index 0000000000..a2b851da94 --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/CommonUserFactory.java @@ -0,0 +1,8 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +class CommonUserFactory implements UserFactory { + @Override + public User create(String name, String password) { + return new CommonUser(name, password); + } +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/JpaUser.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/JpaUser.java new file mode 100644 index 0000000000..20751f282a --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/JpaUser.java @@ -0,0 +1,21 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +class JpaUser implements UserRegisterDsGateway { + + final JpaUserRepository repository; + + JpaUser(JpaUserRepository repository) { + this.repository = repository; + } + + @Override + public boolean existsByName(String name) { + return repository.existsById(name); + } + + @Override + public void save(UserDsRequestModel requestModel) { + UserDataMapper accountDataMapper = new UserDataMapper(requestModel.getName(), requestModel.getPassword(), requestModel.getCreationTime()); + repository.save(accountDataMapper); + } +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/JpaUserRepository.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/JpaUserRepository.java new file mode 100644 index 0000000000..8565ed7965 --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/JpaUserRepository.java @@ -0,0 +1,8 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +interface JpaUserRepository extends JpaRepository { +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/User.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/User.java new file mode 100644 index 0000000000..aab652f2a1 --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/User.java @@ -0,0 +1,9 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +interface User { + boolean passwordIsValid(); + + String getName(); + + String getPassword(); +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserDataMapper.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserDataMapper.java new file mode 100644 index 0000000000..44112de8a9 --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserDataMapper.java @@ -0,0 +1,53 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +import java.time.LocalDateTime; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "user") +class UserDataMapper { + + @Id + String name; + + String password; + + LocalDateTime creationTime; + + public UserDataMapper() { + } + + public UserDataMapper(String name, String password, LocalDateTime creationTime) { + super(); + this.name = name; + this.password = password; + this.creationTime = creationTime; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public LocalDateTime getCreationTime() { + return creationTime; + } + + public void setCreationTime(LocalDateTime creationTime) { + this.creationTime = creationTime; + } +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserDsRequestModel.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserDsRequestModel.java new file mode 100644 index 0000000000..aa0f0b56d1 --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserDsRequestModel.java @@ -0,0 +1,41 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +import java.time.LocalDateTime; + +class UserDsRequestModel { + + String name; + String password; + LocalDateTime creationTime; + + public UserDsRequestModel(String name, String password, LocalDateTime creationTime) { + this.name = name; + this.password = password; + this.creationTime = creationTime; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public LocalDateTime getCreationTime() { + return creationTime; + } + + public void setCreationTime(LocalDateTime creationTime) { + this.creationTime = creationTime; + } + +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserFactory.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserFactory.java new file mode 100644 index 0000000000..1ff29709be --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserFactory.java @@ -0,0 +1,5 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +interface UserFactory { + User create(String name, String password); +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserInputBoundary.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserInputBoundary.java new file mode 100644 index 0000000000..e72c30f13c --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserInputBoundary.java @@ -0,0 +1,5 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +public interface UserInputBoundary { + UserResponseModel create(UserRequestModel requestModel); +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserPresenter.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserPresenter.java new file mode 100644 index 0000000000..45d202643e --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserPresenter.java @@ -0,0 +1,7 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +interface UserPresenter { + UserResponseModel prepareSuccessView(UserResponseModel user); + + UserResponseModel prepareFailView(String error); +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserRegisterController.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserRegisterController.java new file mode 100644 index 0000000000..039dc12910 --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserRegisterController.java @@ -0,0 +1,20 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +class UserRegisterController { + + final UserInputBoundary userInput; + + UserRegisterController(UserInputBoundary accountGateway) { + this.userInput = accountGateway; + } + + @PostMapping("/user") + UserResponseModel create(@RequestBody UserRequestModel requestModel) { + return userInput.create(requestModel); + } +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserRegisterDsGateway.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserRegisterDsGateway.java new file mode 100644 index 0000000000..89c1b7e774 --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserRegisterDsGateway.java @@ -0,0 +1,7 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +interface UserRegisterDsGateway { + boolean existsByName(String identifier); + + void save(UserDsRequestModel requestModel); +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserRegisterInteractor.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserRegisterInteractor.java new file mode 100644 index 0000000000..5137593dc3 --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserRegisterInteractor.java @@ -0,0 +1,35 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +import java.time.LocalDateTime; + +class UserRegisterInteractor implements UserInputBoundary { + + final UserRegisterDsGateway userDsGateway; + final UserPresenter userPresenter; + final UserFactory userFactory; + + UserRegisterInteractor(UserRegisterDsGateway userRegisterDfGateway, UserPresenter userPresenter, + UserFactory userFactory) { + this.userDsGateway = userRegisterDfGateway; + this.userPresenter = userPresenter; + this.userFactory = userFactory; + } + + @Override + public UserResponseModel create(UserRequestModel requestModel) { + if (userDsGateway.existsByName(requestModel.getName())) { + return userPresenter.prepareFailView("User already exists."); + } + User user = userFactory.create(requestModel.getName(), requestModel.getPassword()); + if (!user.passwordIsValid()) { + return userPresenter.prepareFailView("User password must have more than 5 characters."); + } + LocalDateTime now = LocalDateTime.now(); + UserDsRequestModel userDsModel = new UserDsRequestModel(user.getName(), user.getPassword(), now); + + userDsGateway.save(userDsModel); + + UserResponseModel accountResponseModel = new UserResponseModel(user.getName(), now.toString()); + return userPresenter.prepareSuccessView(accountResponseModel); + } +} \ No newline at end of file diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserRequestModel.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserRequestModel.java new file mode 100644 index 0000000000..8317665c31 --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserRequestModel.java @@ -0,0 +1,33 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +class UserRequestModel { + + String name; + String password; + + public UserRequestModel() { + super(); + } + + UserRequestModel(String name, String password) { + super(); + this.name = name; + this.password = password; + } + + String getName() { + return name; + } + + void setName(String name) { + this.name = name; + } + + String getPassword() { + return password; + } + + void setPassword(String password) { + this.password = password; + } +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserResponseFormatter.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserResponseFormatter.java new file mode 100644 index 0000000000..4842d44e22 --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserResponseFormatter.java @@ -0,0 +1,22 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +import org.springframework.http.HttpStatus; +import org.springframework.web.server.ResponseStatusException; + +class UserResponseFormatter implements UserPresenter { + + @Override + public UserResponseModel prepareSuccessView(UserResponseModel response) { + LocalDateTime responseTime = LocalDateTime.parse(response.getCreationTime()); + response.setCreationTime(responseTime.format(DateTimeFormatter.ofPattern("hh:mm:ss"))); + return response; + } + + @Override + public UserResponseModel prepareFailView(String error) { + throw new ResponseStatusException(HttpStatus.CONFLICT, error); + } +} diff --git a/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserResponseModel.java b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserResponseModel.java new file mode 100644 index 0000000000..73a3d8fb10 --- /dev/null +++ b/patterns/clean-architecture/src/main/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserResponseModel.java @@ -0,0 +1,29 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +public class UserResponseModel { + + String login; + String creationTime; + + public UserResponseModel(String login, String creationTime) { + this.login = login; + this.creationTime = creationTime; + } + + public String getLogin() { + return login; + } + + public void setLogin(String login) { + this.login = login; + } + + public String getCreationTime() { + return creationTime; + } + + public void setCreationTime(String creationTime) { + this.creationTime = creationTime; + } + +} diff --git a/patterns/clean-architecture/src/main/resources/application.properties b/patterns/clean-architecture/src/main/resources/application.properties new file mode 100644 index 0000000000..a5a02bb49d --- /dev/null +++ b/patterns/clean-architecture/src/main/resources/application.properties @@ -0,0 +1,2 @@ +server.port=8080 +server.error.include-message=always \ No newline at end of file diff --git a/patterns/clean-architecture/src/test/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserResponseFormatterUnitTest.java b/patterns/clean-architecture/src/test/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserResponseFormatterUnitTest.java new file mode 100644 index 0000000000..e394cbbf94 --- /dev/null +++ b/patterns/clean-architecture/src/test/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserResponseFormatterUnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import org.junit.jupiter.api.Test; +import org.springframework.web.server.ResponseStatusException; + +import com.baeldung.pattern.cleanarchitecture.usercreation.UserResponseFormatter; +import com.baeldung.pattern.cleanarchitecture.usercreation.UserResponseModel; + +class UserResponseFormatterUnitTest { + + UserResponseFormatter userResponseFormatter = new UserResponseFormatter(); + + @Test + void givenDateAnd3HourTime_whenPrepareSuccessView_thenReturnOnly3HourTime() { + UserResponseModel modelResponse = new UserResponseModel("baeldung", "2020-12-20T03:00:00.000"); + UserResponseModel formattedResponse = userResponseFormatter.prepareSuccessView(modelResponse); + + assertThat(formattedResponse.getCreationTime()).isEqualTo("03:00:00"); + } + + @Test + void whenPrepareFailView_thenThrowHttpConflictException() { + assertThatThrownBy(() -> userResponseFormatter.prepareFailView("Invalid password")) + .isInstanceOf(ResponseStatusException.class); + } +} diff --git a/patterns/clean-architecture/src/test/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserUnitTest.java b/patterns/clean-architecture/src/test/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserUnitTest.java new file mode 100644 index 0000000000..505ea47e3f --- /dev/null +++ b/patterns/clean-architecture/src/test/java/com/baeldung/pattern/cleanarchitecture/usercreation/UserUnitTest.java @@ -0,0 +1,15 @@ +package com.baeldung.pattern.cleanarchitecture.usercreation; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; + +class UserUnitTest { + + @Test + void given123Password_whenPasswordIsNotValid_thenIsFalse() { + User user = new CommonUser("Baeldung", "123"); + + assertThat(user.passwordIsValid()).isFalse(); + } +} diff --git a/patterns/design-patterns-architectural/README.md b/patterns/design-patterns-architectural/README.md index 5b6011c159..ae6781c66c 100644 --- a/patterns/design-patterns-architectural/README.md +++ b/patterns/design-patterns-architectural/README.md @@ -1,4 +1,4 @@ ### Relevant Articles: -- [Service Locator Pattern](https://www.baeldung.com/java-service-locator-pattern) +- [Service Locator Pattern and Java Implementation](https://www.baeldung.com/java-service-locator-pattern) - [The DAO Pattern in Java](https://www.baeldung.com/java-dao-pattern) - [DAO vs Repository Patterns](https://www.baeldung.com/java-dao-vs-repository) diff --git a/patterns/design-patterns-behavioral/src/main/java/com/baeldung/nulls/UsingOptional.java b/patterns/design-patterns-behavioral/src/main/java/com/baeldung/nulls/UsingOptional.java index d5dd56e760..099864589c 100644 --- a/patterns/design-patterns-behavioral/src/main/java/com/baeldung/nulls/UsingOptional.java +++ b/patterns/design-patterns-behavioral/src/main/java/com/baeldung/nulls/UsingOptional.java @@ -1,23 +1,52 @@ package com.baeldung.nulls; +import java.util.List; import java.util.Optional; +import static java.util.Collections.emptyList; + public class UsingOptional { - public Optional process(boolean processed) { + public static final String DEFAULT_VALUE = "Default Value"; + public Optional process(boolean processed) { String response = doSomething(processed); return Optional.ofNullable(response); } - private String doSomething(boolean processed) { + public String findFirst() { + return getList() + .stream() + .findFirst() + .orElse(DEFAULT_VALUE); + } + + public Optional findOptionalFirst() { + return getList() + .stream() + .findFirst(); + } + + private List getList() { + return emptyList(); + } + + public Optional optionalListFirst() { + return getOptionalList() + .flatMap(list -> list.stream().findFirst()); + } + + private Optional getOptionalList() { + return Optional.ofNullable(getList()); + } + + private String doSomething(boolean processed) { if (processed) { return "passed"; } else { return null; } } - } diff --git a/patterns/design-patterns-behavioral/src/test/java/com/baeldung/nulls/UsingOptionalUnitTest.java b/patterns/design-patterns-behavioral/src/test/java/com/baeldung/nulls/UsingOptionalUnitTest.java index 8f896cedfa..73797d48c8 100644 --- a/patterns/design-patterns-behavioral/src/test/java/com/baeldung/nulls/UsingOptionalUnitTest.java +++ b/patterns/design-patterns-behavioral/src/test/java/com/baeldung/nulls/UsingOptionalUnitTest.java @@ -11,32 +11,47 @@ import static org.junit.jupiter.api.Assertions.assertTrue; class UsingOptionalUnitTest { - private UsingOptional classUnderTest; + private UsingOptional dataObject; @BeforeEach public void setup() { - classUnderTest = new UsingOptional(); + dataObject = new UsingOptional(); } @Test public void whenArgIsFalse_thenReturnEmptyResponse() { - - Optional result = classUnderTest.process(false); + Optional result = dataObject.process(false); assertFalse(result.isPresent()); } @Test public void whenArgIsTrue_thenReturnValidResponse() { - - Optional result = classUnderTest.process(true); + Optional result = dataObject.process(true); assertTrue(result.isPresent()); } @Test public void whenArgIsFalse_thenChainResponseAndThrowException() { - - assertThrows(Exception.class, () -> classUnderTest.process(false).orElseThrow(() -> new Exception())); + assertThrows(Exception.class, () -> dataObject.process(false).orElseThrow(() -> new Exception())); } + + @Test() + void givenEmptyList_whenFindFirst_getDefaultValue() { + assertTrue(dataObject.findFirst().equalsIgnoreCase(UsingOptional.DEFAULT_VALUE)); + } + + @Test() + void givenEmptyList_whenFindOptionalFirst_returnsEmptyOptional() { + assertFalse(dataObject.findOptionalFirst().isPresent()); + } + + @Test() + void whenOptionalListFirst_returnsEmptyOptional() { + assertFalse(dataObject.optionalListFirst().isPresent()); + } + + + } \ No newline at end of file diff --git a/patterns/pom.xml b/patterns/pom.xml index a179d75ffe..112eecb606 100644 --- a/patterns/pom.xml +++ b/patterns/pom.xml @@ -24,6 +24,7 @@ hexagonal-architecture intercepting-filter solid + clean-architecture diff --git a/performance-tests/README.md b/performance-tests/README.md index 27c0363010..09bf6dba1f 100644 --- a/performance-tests/README.md +++ b/performance-tests/README.md @@ -6,6 +6,7 @@ This module contains articles about performance testing. - [Performance of Java Mapping Frameworks](https://www.baeldung.com/java-performance-mapping-frameworks) - [Performance Effects of Exceptions in Java](https://www.baeldung.com/java-exceptions-performance) +- [Is Java a Compiled or Interpreted Language?](https://www.baeldung.com/java-compiled-interpreted) ### Running diff --git a/performance-tests/src/main/external/Fibonacci.cpp b/performance-tests/src/main/external/Fibonacci.cpp new file mode 100644 index 0000000000..d23603c2ea --- /dev/null +++ b/performance-tests/src/main/external/Fibonacci.cpp @@ -0,0 +1,19 @@ +#include +#include + +using namespace std; + +int fibonacci(int n) { + if (n <= 1) + return n; + return fibonacci(n - 1) + fibonacci(n - 2); +} + +int main() { + for (int i = 0; i < 100; i++) { + auto startTime = chrono::high_resolution_clock::now().time_since_epoch(); + int result = fibonacci(12); + auto totalTime = chrono::high_resolution_clock::now().time_since_epoch() - startTime; + cout << totalTime << "\n"; + } +} \ No newline at end of file diff --git a/performance-tests/src/main/external/Fibonacci.js b/performance-tests/src/main/external/Fibonacci.js new file mode 100644 index 0000000000..ba41bf3ab9 --- /dev/null +++ b/performance-tests/src/main/external/Fibonacci.js @@ -0,0 +1,14 @@ +function fibonacci(index) { + if (index <= 1) + return index; + return fibonacci(index-1) + fibonacci(index-2); +} + +for (var i=0; i<100; i++) { + var startTime = process.hrtime.bigint(); + var result = fibonacci(12); + var totalTime = process.hrtime.bigint() - startTime; + console.log(totalTime); +} + + \ No newline at end of file diff --git a/performance-tests/src/main/java/com/baeldung/performancetests/jit/Fibonacci.java b/performance-tests/src/main/java/com/baeldung/performancetests/jit/Fibonacci.java new file mode 100644 index 0000000000..c980093128 --- /dev/null +++ b/performance-tests/src/main/java/com/baeldung/performancetests/jit/Fibonacci.java @@ -0,0 +1,20 @@ +package com.baeldung.performancetests.jit; + +public class Fibonacci { + + public static void main(String[] args) { + for (int i=0; i<100; i++) { + long startTime = System.nanoTime(); + int result = fibonacci(12); + long totalTime = System.nanoTime() - startTime; + System.out.println(totalTime); + } + } + + private static int fibonacci(int index) { + if (index <= 1) + return index; + return fibonacci(index-1) + fibonacci(index-2); + } + +} diff --git a/performance-tests/src/main/resources/FibonacciPerformancesResults.csv b/performance-tests/src/main/resources/FibonacciPerformancesResults.csv new file mode 100644 index 0000000000..01a1f3dd90 --- /dev/null +++ b/performance-tests/src/main/resources/FibonacciPerformancesResults.csv @@ -0,0 +1,103 @@ +Runs;Java using JIT;Java without JIT;C++ without O2;C++ with O2;JavaScript +1;21900;10572;8684;2643;35115 +2;60790;10572;8306;2643;20389 +3;1888;24543;7551;2265;20390 +4;4153;25675;8307;2265;19256 +5;1888;26053;8307;2265;19257 +6;5664;25675;8307;1887;35115 +7;1510;25676;29829;2266;20012 +8;1510;26053;7929;2643;35493 +9;1511;23787;7929;1888;40023 +10;3776;26431;26053;3776;20012 +11;1510;25676;7929;2265;35115 +12;1510;10195;7552;3775;19256 +13;17746;10572;7552;1888;40024 +14;26431;10194;7552;2265;19257 +15;1133;10195;8685;2265;18501 +16;1133;10572;7929;2265;18879 +17;1133;10572;7929;1888;53995 +18;756;10195;7929;1888;35115 +19;1133;10195;7930;2266;19634 +20;756;10573;7552;2266;37003 +21;1133;9817;7552;1888;35115 +22;1133;10194;7930;2266;32472 +23;1133;10195;7929;2266;18879 +24;755;10195;8307;3776;19257 +25;755;10195;7551;1888;34738 +26;1510;10194;7551;2265;18501 +27;3776;10194;7929;2266;33227 +28;1888;37758;9440;1888;19634 +29;1133;10573;8306;1888;32472 +30;1133;26430;7929;2265;32849 +31;1133;24165;8306;4153;32850 +32;755;24166;7929;2643;18879 +33;1133;10572;24920;4153;32850 +34;755;23788;10194;2643;19257 +35;756;23788;12837;4154;18501 +36;755;11328;8307;2643;33227 +37;1132;29829;8307;7174;1000211 +38;755;36625;8307;4531;39646 +39;1133;10950;7929;2643;34360 +40;1133;10950;7929;4531;3021 +41;1133;10573;7929;2643;2643 +42;755;29829;15104;2643;2643 +43;755;29829;13971;2643;3398 +44;1133;10950;8685;5664;3021 +45;1133;10950;9817;3020;3398 +46;1133;10950;8684;3776;3020 +47;1888;30962;7930;3020;3021 +48;1132;10950;8307;2643;3399 +49;1133;29451;7929;2265;2266 +50;1133;29452;8307;23033;2265 +51;755;10950;7929;2643;2266 +52;755;10950;7930;2643;2643 +53;755;11327;7929;4908;2265 +54;755;11328;7929;2265;2643 +55;1133;10572;7929;18879;16236 +56;756;36248;7929;2643;2643 +57;755;10572;7929;2265;2643 +58;755;10950;9818;2644;2643 +59;1132;10950;7929;2266;2643 +60;20012;30206;7929;2266;3021 +61;1133;30206;7929;2266;16613 +62;1511;30206;7552;2266;2643 +63;3021;30207;8307;1888;2643 +64;1510;10950;7929;1888;2266 +65;1510;30207;7929;2266;2644 +66;1888;30207;8307;2265;2643 +67;1511;29829;7929;2266;2643 +68;1888;10950;7930;2265;2266 +69;1510;29829;7929;21145;3020 +70;1511;29829;7929;1888;16613 +71;1510;30206;7929;2643;2265 +72;1510;10950;7929;2266;2644 +73;1888;10573;24921;18124;2266 +74;1888;10573;9062;6797;2644 +75;1888;10950;7929;2265;2643 +76;1133;10950;7929;2266;2644 +77;1133;29829;12460;2266;3020 +78;755;11328;8307;2643;2266 +79;755;11327;8684;2266;2643 +80;1133;30206;8307;2266;2643 +81;1133;29829;7929;2266;2266 +82;1888;30206;7929;2266;16236 +83;1510;11327;8307;2266;16613 +84;1888;11327;7929;2265;2643 +85;1133;10573;8307;6042;2266 +86;1133;10950;7929;2643;2266 +87;1133;10950;9817;2265;2265 +88;755;10950;24165;2643;2643 +89;755;11328;7929;3399;2643 +90;755;10950;8307;4909;3020 +91;755;10572;7552;23787;3020 +92;1133;10572;7929;2643;3021 +93;1132;10572;8307;2643;2643 +94;1132;10950;7551;2266;3398 +95;755;10950;23788;2265;2644 +96;755;10573;7551;1888;2265 +97;755;29829;12460;2266;2643 +98;1132;30207;7929;2266;2265 +99;1133;30206;7929;2265;2266 +100;755;10572;7929;2265;2643 +;;;;; +;;;;; diff --git a/persistence-modules/core-java-persistence-2/README.md b/persistence-modules/core-java-persistence-2/README.md new file mode 100644 index 0000000000..36c33cc6e1 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/README.md @@ -0,0 +1,4 @@ +### Relevant Articles: + +- [Getting Database URL From JDBC Connection Object](https://www.baeldung.com/jdbc-get-url-from-connection) +- [JDBC URL Format For Different Databases](https://www.baeldung.com/java-jdbc-url-format) diff --git a/persistence-modules/core-java-persistence-2/pom.xml b/persistence-modules/core-java-persistence-2/pom.xml new file mode 100644 index 0000000000..a1088b0801 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + com.baeldung.core-java-persistence-2 + core-java-persistence-2 + 0.1.0-SNAPSHOT + core-java-persistence-2 + jar + + + com.baeldung + persistence-modules + 1.0.0-SNAPSHOT + + + + + com.h2database + h2 + ${h2.version} + + + org.postgresql + postgresql + ${postgresql.version} + test + + + mysql + mysql-connector-java + ${mysql.driver.version} + + + + com.microsoft.sqlserver + mssql-jdbc + ${mssql.driver.version} + + + + + + 1.4.200 + 42.2.5.jre7 + 8.4.1.jre11 + 10.2.0.4.0 + 8.0.22 + + + diff --git a/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/getdburl/DBConfiguration.java b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/getdburl/DBConfiguration.java new file mode 100644 index 0000000000..51d3a432ac --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/getdburl/DBConfiguration.java @@ -0,0 +1,13 @@ +package com.baeldung.getdburl; + +import java.sql.Connection; +import java.sql.DriverManager; + +public class DBConfiguration { + + public static Connection getConnection() throws Exception { + Class.forName("org.h2.Driver"); + String url = "jdbc:h2:mem:testdb"; + return DriverManager.getConnection(url, "user", "password"); + } +} diff --git a/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/getdburl/DBConfigurationUnitTest.java b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/getdburl/DBConfigurationUnitTest.java new file mode 100644 index 0000000000..845076f070 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/getdburl/DBConfigurationUnitTest.java @@ -0,0 +1,18 @@ +package com.baeldung.getdburl; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.sql.Connection; + +import org.junit.jupiter.api.Test; + +class DBConfigurationUnitTest { + + @Test + void givenConnectionObject_whenExtractMetaData_thenGetDbURL() throws Exception { + Connection connection = DBConfiguration.getConnection(); + String dbUrl = connection.getMetaData().getURL(); + assertEquals("jdbc:h2:mem:testdb", dbUrl); + } + +} diff --git a/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/jdbcurlformat/JdbcUrlFormatLiveTest.java b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/jdbcurlformat/JdbcUrlFormatLiveTest.java new file mode 100644 index 0000000000..fc00119704 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/jdbcurlformat/JdbcUrlFormatLiveTest.java @@ -0,0 +1,86 @@ +package com.baeldung.jdbcurlformat; + +import org.junit.Test; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; + +import static org.junit.Assert.assertNotNull; + +public class JdbcUrlFormatLiveTest { + @Test + public void givenOracleSID_thenCreateConnectionObject() { + String oracleJdbcUrl = "jdbc:oracle:thin:@myoracle.db.server:1521:my_sid"; + String username = "dbUser"; + String password = "1234567"; + try (Connection conn = DriverManager.getConnection(oracleJdbcUrl, username, password)) { + assertNotNull(conn); + } catch (SQLException e) { + System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage()); + } + } + + @Test + public void givenOracleServiceName_thenCreateConnectionObject() { + String oracleJdbcUrl = "jdbc:oracle:thin:@//myoracle.db.server:1521/my_servicename"; + String username = "dbUser"; + String password = "1234567"; + try (Connection conn = DriverManager.getConnection(oracleJdbcUrl, username, password)) { + assertNotNull(conn); + } catch (SQLException e) { + System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage()); + } + } + + @Test + public void givenOracleTnsnames_thenCreateConnectionObject() { + String oracleJdbcUrl = "jdbc:oracle:thin:@" + + "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)" + + "(HOST=myoracle.db.server)(PORT=1521))" + + "(CONNECT_DATA=(SERVICE_NAME=my_servicename)))"; + String username = "dbUser"; + String password = "1234567"; + try (Connection conn = DriverManager.getConnection(oracleJdbcUrl, username, password)) { + assertNotNull(conn); + } catch (SQLException e) { + System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage()); + } + } + + @Test + public void givenMysqlDb_thenCreateConnectionObject() { + String jdbcUrl = "jdbc:mysql://mysql.db.server:3306/my_database?useSSL=false&serverTimezone=UTC"; + String username = "dbUser"; + String password = "1234567"; + try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) { + assertNotNull(conn); + } catch (SQLException e) { + System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage()); + } + } + + @Test + public void givenMssqlDb_thenCreateConnectionObject() { + String jdbcUrl = "jdbc:sqlserver://mssql.db.server\\mssql_instance;databaseName=my_database"; + String username = "dbUser"; + String password = "1234567"; + try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) { + assertNotNull(conn); + } catch (SQLException e) { + System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage()); + } + } + + @Test + public void givenPostgreSqlDb_thenCreateConnectionObject() { + String jdbcUrl = "jdbc:postgresql://postgresql.db.server:5430/my_database?ssl=true&loglevel=2"; + String username = "dbUser"; + String password = "1234567"; + try (Connection conn = DriverManager.getConnection(jdbcUrl, username, password)) { + assertNotNull(conn); + } catch (SQLException e) { + System.err.format("SQL State: %s\n%s", e.getSQLState(), e.getMessage()); + } + } +} diff --git a/persistence-modules/flyway-repair/pom.xml b/persistence-modules/flyway-repair/pom.xml index 82e5d705f9..2c283cfc04 100644 --- a/persistence-modules/flyway-repair/pom.xml +++ b/persistence-modules/flyway-repair/pom.xml @@ -76,10 +76,6 @@ src/main/resources/application-${spring-boot.run.profiles}.properties - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/flyway/pom.xml b/persistence-modules/flyway/pom.xml index 2379f996d7..c4a3363bdc 100644 --- a/persistence-modules/flyway/pom.xml +++ b/persistence-modules/flyway/pom.xml @@ -66,10 +66,6 @@ 5.2.3 5.0.2 - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/hibernate-annotations/pom.xml b/persistence-modules/hibernate-annotations/pom.xml index 5367921f31..d3b786d6c8 100644 --- a/persistence-modules/hibernate-annotations/pom.xml +++ b/persistence-modules/hibernate-annotations/pom.xml @@ -30,7 +30,7 @@ org.apache.commons commons-lang3 - ${commons.lang3.version} + ${commons-lang3.version} @@ -44,31 +44,15 @@ hibernate-spatial ${hibernate-core.version} - - org.opengeo - geodb - ${geodb.version} - - - - geodb-repo - GeoDB repository - http://repo.boundlessgeo.com/main/ - - - 5.4.7.Final 1.4.200 - 3.8.1 true 2.1.7.RELEASE 5.4.7.Final 1.4.200 - 3.8.1 - 0.9 diff --git a/persistence-modules/hibernate-enterprise/README.md b/persistence-modules/hibernate-enterprise/README.md index c5606d0970..1a86c32afa 100644 --- a/persistence-modules/hibernate-enterprise/README.md +++ b/persistence-modules/hibernate-enterprise/README.md @@ -9,4 +9,5 @@ This module contains articles about enterprise concerns such as Multitenancy, Er - [Hibernate Aggregate Functions](https://www.baeldung.com/hibernate-aggregate-functions) - [Common Hibernate Exceptions](https://www.baeldung.com/hibernate-exceptions) - [Hibernate Error “Not all named parameters have been set”](https://www.baeldung.com/hibernate-error-named-parameters-not-set) -- [Various Logging Levels in Hibernate](https://www.baeldung.com/hibernate-logging-levels) \ No newline at end of file +- [Various Logging Levels in Hibernate](https://www.baeldung.com/hibernate-logging-levels) +- [Hibernate: save, persist, update, merge, saveOrUpdate](https://www.baeldung.com/hibernate-save-persist-update-merge-saveorupdate) \ No newline at end of file diff --git a/persistence-modules/hibernate-enterprise/pom.xml b/persistence-modules/hibernate-enterprise/pom.xml index ae58e409c4..c088cc1eca 100644 --- a/persistence-modules/hibernate-enterprise/pom.xml +++ b/persistence-modules/hibernate-enterprise/pom.xml @@ -61,13 +61,25 @@ ${byte-buddy.version} test + + org.hsqldb + hsqldb + ${hsqldb.version} + test + - geodb-repo - GeoDB repository - http://repo.boundlessgeo.com/main/ + osgeo + OSGeo Release Repository + https://repo.osgeo.org/repository/release/ + + false + + + true + @@ -77,6 +89,7 @@ 2.2.3 3.8.0 0.9 + 2.3.4 diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Person.java b/persistence-modules/hibernate-enterprise/src/main/java/com/baeldung/persistence/model/Person.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Person.java rename to persistence-modules/hibernate-enterprise/src/main/java/com/baeldung/persistence/model/Person.java diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsIntegrationTest.java b/persistence-modules/hibernate-enterprise/src/test/java/com/baeldung/persistence/save/SaveMethodsIntegrationTest.java similarity index 79% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsIntegrationTest.java rename to persistence-modules/hibernate-enterprise/src/test/java/com/baeldung/persistence/save/SaveMethodsIntegrationTest.java index ef83af3a0d..8c571428b4 100644 --- a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsIntegrationTest.java +++ b/persistence-modules/hibernate-enterprise/src/test/java/com/baeldung/persistence/save/SaveMethodsIntegrationTest.java @@ -1,6 +1,14 @@ package com.baeldung.persistence.save; -import com.baeldung.persistence.model.Person; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +import javax.persistence.PersistenceException; + import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; @@ -8,9 +16,13 @@ import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.dialect.HSQLDialect; import org.hibernate.service.ServiceRegistry; -import org.junit.*; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; -import static org.junit.Assert.*; +import com.baeldung.persistence.model.Person; /** * Testing specific implementation details for different methods: @@ -21,12 +33,19 @@ public class SaveMethodsIntegrationTest { private static SessionFactory sessionFactory; private Session session; + private boolean doNotCommit = false; @BeforeClass public static void beforeTests() { - Configuration configuration = new Configuration().addAnnotatedClass(Person.class).setProperty("hibernate.dialect", HSQLDialect.class.getName()).setProperty("hibernate.connection.driver_class", org.hsqldb.jdbcDriver.class.getName()) - .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test").setProperty("hibernate.connection.username", "sa").setProperty("hibernate.connection.password", "").setProperty("hibernate.hbm2ddl.auto", "update"); - ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); + Configuration configuration = new Configuration().addAnnotatedClass(Person.class) + .setProperty("hibernate.dialect", HSQLDialect.class.getName()) + .setProperty("hibernate.connection.driver_class", org.hsqldb.jdbcDriver.class.getName()) + .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test") + .setProperty("hibernate.connection.username", "sa") + .setProperty("hibernate.connection.password", "") + .setProperty("hibernate.hbm2ddl.auto", "update"); + ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()) + .build(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); } @@ -34,6 +53,7 @@ public class SaveMethodsIntegrationTest { public void setUp() { session = sessionFactory.openSession(); session.beginTransaction(); + doNotCommit = false; } @Test @@ -43,7 +63,8 @@ public class SaveMethodsIntegrationTest { person.setName("John"); session.persist(person); - session.getTransaction().commit(); + session.getTransaction() + .commit(); session.close(); session = sessionFactory.openSession(); @@ -68,15 +89,33 @@ public class SaveMethodsIntegrationTest { assertEquals(id1, id2); } - @Test(expected = HibernateException.class) + @Test(expected = PersistenceException.class) public void whenPersistDetached_thenThrowsException() { + doNotCommit = true; + Person person = new Person(); person.setName("John"); session.persist(person); session.evict(person); - + session.persist(person); + } + + @Test + public void whenMergeDetached_thenEntityUpdatedFromDatabase() { + + Person person = new Person(); + person.setName("John"); + session.save(person); + session.flush(); + session.evict(person); + + person.setName("Mary"); + Person mergedPerson = (Person) session.merge(person); + + assertNotSame(person, mergedPerson); + assertEquals("Mary", mergedPerson.getName()); } @@ -92,7 +131,8 @@ public class SaveMethodsIntegrationTest { assertNotNull(id); - session.getTransaction().commit(); + session.getTransaction() + .commit(); session.close(); assertEquals(id, person.getId()); @@ -128,22 +168,6 @@ public class SaveMethodsIntegrationTest { } - @Test - public void whenMergeDetached_thenEntityUpdatedFromDatabase() { - - Person person = new Person(); - person.setName("John"); - session.save(person); - session.evict(person); - - person.setName("Mary"); - Person mergedPerson = (Person) session.merge(person); - - assertNotSame(person, mergedPerson); - assertEquals("Mary", mergedPerson.getName()); - - } - @Test public void whenMergeTransient_thenNewEntitySavedToDatabase() { @@ -151,7 +175,8 @@ public class SaveMethodsIntegrationTest { person.setName("John"); Person mergedPerson = (Person) session.merge(person); - session.getTransaction().commit(); + session.getTransaction() + .commit(); session.beginTransaction(); assertNull(person.getId()); @@ -227,7 +252,8 @@ public class SaveMethodsIntegrationTest { person.setName("John"); session.saveOrUpdate(person); - session.getTransaction().commit(); + session.getTransaction() + .commit(); session.close(); session = sessionFactory.openSession(); @@ -250,7 +276,10 @@ public class SaveMethodsIntegrationTest { @After public void tearDown() { - session.getTransaction().commit(); + if (!doNotCommit) { + session.getTransaction() + .commit(); + } session.close(); } diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/jpabootstrap/application/Application.java b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/jpabootstrap/application/Application.java index f7b8e6bf6d..b547a60b06 100644 --- a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/jpabootstrap/application/Application.java +++ b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/jpabootstrap/application/Application.java @@ -8,7 +8,7 @@ public class Application { public static void main(String[] args) { EntityManager entityManager = getJpaEntityManager(); - User user = entityManager.find(User.class, 1); + User user = entityManager.find(User.class, 1l); System.out.println(user); entityManager.getTransaction().begin(); user.setName("John"); diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/onetoone/sharedkeybased/Address.java b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/onetoone/sharedkeybased/Address.java index 927516f6bb..e70c62e77b 100644 --- a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/onetoone/sharedkeybased/Address.java +++ b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/onetoone/sharedkeybased/Address.java @@ -1,9 +1,9 @@ package com.baeldung.hibernate.onetoone.sharedkeybased; - import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; +import javax.persistence.JoinColumn; import javax.persistence.MapsId; import javax.persistence.OneToOne; import javax.persistence.Table; @@ -13,7 +13,7 @@ import javax.persistence.Table; public class Address { @Id - @Column(name = "id") + @Column(name = "user_id") private Long id; @Column(name = "street") @@ -24,6 +24,7 @@ public class Address { @OneToOne @MapsId + @JoinColumn(name = "user_id") private User user; public Long getId() { diff --git a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/onetoone/sharedkeybased/User.java b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/onetoone/sharedkeybased/User.java index fa00db1271..605671a149 100644 --- a/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/onetoone/sharedkeybased/User.java +++ b/persistence-modules/hibernate-jpa/src/main/java/com/baeldung/hibernate/onetoone/sharedkeybased/User.java @@ -8,6 +8,7 @@ import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToOne; +import javax.persistence.PrimaryKeyJoinColumn; import javax.persistence.Table; @Entity @@ -22,6 +23,7 @@ public class User { private String userName; @OneToOne(mappedBy = "user", cascade = CascadeType.ALL) + @PrimaryKeyJoinColumn private Address address; public Long getId() { diff --git a/persistence-modules/hibernate-libraries/pom.xml b/persistence-modules/hibernate-libraries/pom.xml index 808c47133c..f67309cf43 100644 --- a/persistence-modules/hibernate-libraries/pom.xml +++ b/persistence-modules/hibernate-libraries/pom.xml @@ -170,7 +170,6 @@ 29.0-jre 2.9.7 5.4.14.Final - 2.10.3 3.27.0-GA 2.3.1 2.0.0 diff --git a/persistence-modules/hibernate-mapping/pom.xml b/persistence-modules/hibernate-mapping/pom.xml index 4eabc5d298..ebc854a621 100644 --- a/persistence-modules/hibernate-mapping/pom.xml +++ b/persistence-modules/hibernate-mapping/pom.xml @@ -71,8 +71,6 @@ 3.0.1-b11 1.0.3 1.3 - 3.9 - 2.6 diff --git a/persistence-modules/hibernate-queries/pom.xml b/persistence-modules/hibernate-queries/pom.xml index 06f7f42088..4374c833c2 100644 --- a/persistence-modules/hibernate-queries/pom.xml +++ b/persistence-modules/hibernate-queries/pom.xml @@ -35,11 +35,6 @@ hibernate-spatial ${hibernate.version} - - org.opengeo - geodb - ${geodb.version} - mysql mysql-connector-java @@ -62,19 +57,10 @@ - - - geodb-repo - GeoDB repository - http://repo.boundlessgeo.com/main/ - - - 6.0.6 2.2.3 3.8.0 - 0.9 1.21 diff --git a/persistence-modules/hibernate5/pom.xml b/persistence-modules/hibernate5/pom.xml index 7f04abc09f..3feffc98fd 100644 --- a/persistence-modules/hibernate5/pom.xml +++ b/persistence-modules/hibernate5/pom.xml @@ -35,11 +35,6 @@ hibernate-spatial ${hibernate.version} - - org.opengeo - geodb - ${geodb.version} - mysql mysql-connector-java @@ -68,21 +63,12 @@ - - - geodb-repo - GeoDB repository - http://repo.boundlessgeo.com/main/ - - - 5.4.12.Final 6.0.6 2.2.3 3.8.0 1.21 - 0.9 diff --git a/persistence-modules/java-jpa-3/README.md b/persistence-modules/java-jpa-3/README.md index dce9c4e711..9c9e040825 100644 --- a/persistence-modules/java-jpa-3/README.md +++ b/persistence-modules/java-jpa-3/README.md @@ -5,3 +5,8 @@ This module contains articles about the Java Persistence API (JPA) in Java. ### Relevant Articles: - [JPA Entity Equality](https://www.baeldung.com/jpa-entity-equality) +- [Ignoring Fields With the JPA @Transient Annotation](https://www.baeldung.com/jpa-transient-ignore-field) +- [Defining Indexes in JPA](https://www.baeldung.com/jpa-indexes) +- [JPA CascadeType.REMOVE vs orphanRemoval](https://www.baeldung.com/jpa-cascade-remove-vs-orphanremoval) +- [A Guide to MultipleBagFetchException in Hibernate](https://www.baeldung.com/java-hibernate-multiplebagfetchexception) +- [How to Convert a Hibernate Proxy to a Real Entity Object](https://www.baeldung.com/hibernate-proxy-to-real-entity-object) diff --git a/persistence-modules/java-jpa-3/pom.xml b/persistence-modules/java-jpa-3/pom.xml index da18ae3046..7c02cc6c8e 100644 --- a/persistence-modules/java-jpa-3/pom.xml +++ b/persistence-modules/java-jpa-3/pom.xml @@ -27,7 +27,21 @@ h2 ${h2.version} - + + mysql + mysql-connector-java + 8.0.21 + + + com.fasterxml.jackson.core + jackson-databind + 2.11.3 + + + com.fasterxml.jackson.datatype + jackson-datatype-hibernate5 + 2.9.8 + javax.persistence diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/ignorable/fields/HibernateConfig.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/ignorable/fields/HibernateConfig.java new file mode 100644 index 0000000000..9285c23dfa --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/ignorable/fields/HibernateConfig.java @@ -0,0 +1,37 @@ +package com.baeldung.ignorable.fields; + +import java.util.Properties; + +import org.hibernate.SessionFactory; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.Environment; +import org.hibernate.service.ServiceRegistry; + +public class HibernateConfig { + private static SessionFactory sessionFactory; + + public static SessionFactory getSessionFactory() { + if (sessionFactory == null) { + Configuration configuration = new Configuration(); + + Properties settings = new Properties(); + settings.put(Environment.DRIVER, "com.mysql.cj.jdbc.Driver"); + settings.put(Environment.URL, "jdbc:mysql://localhost:3306/app_db?useSSL=false"); + settings.put(Environment.USER, "root"); + settings.put(Environment.PASS, "password"); + settings.put(Environment.DIALECT, "org.hibernate.dialect.MySQL5Dialect"); + settings.put(Environment.CURRENT_SESSION_CONTEXT_CLASS, "thread"); + configuration.setProperties(settings); + + configuration.addAnnotatedClass(User.class); + + ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder() + .applySettings(configuration.getProperties()) + .build(); + + sessionFactory = configuration.buildSessionFactory(serviceRegistry); + } + return sessionFactory; + } +} \ No newline at end of file diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/ignorable/fields/User.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/ignorable/fields/User.java new file mode 100644 index 0000000000..8d1812605d --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/ignorable/fields/User.java @@ -0,0 +1,80 @@ +package com.baeldung.ignorable.fields; + +import java.io.Serializable; +import java.util.StringJoiner; + +import javax.persistence.*; + +@Entity +@Table(name = "Users") +public class User implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + private String email; + private String password; + @Transient + private String currentDevice; + + // Needed for Hibernate mapping + public User() { + } + + public User(String email, String password, String currentDevice) { + this.email = email; + this.password = password; + this.currentDevice = currentDevice; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getCurrentDevice() { + return currentDevice; + } + + public void setCurrentDevice(String currentDevice) { + this.currentDevice = currentDevice; + } + + @Override + public String toString() { + return new StringJoiner(", ", User.class.getSimpleName() + "[", "]").add("id=" + id) + .add("email='" + email + "'") + .add("password='" + password + "'") + .add("currentDevice='" + currentDevice + "'") + .toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (!(o instanceof User)) + return false; + User user = (User) o; + return email.equals(user.email); + } +} \ No newline at end of file diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/ignorable/fields/UserDao.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/ignorable/fields/UserDao.java new file mode 100644 index 0000000000..45e491e42e --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/ignorable/fields/UserDao.java @@ -0,0 +1,28 @@ +package com.baeldung.ignorable.fields; + +import java.util.List; + +import org.hibernate.Session; +import org.hibernate.Transaction; + +public class UserDao { + + public void saveUser(User user) { + Transaction transaction = null; + try (Session session = HibernateConfig.getSessionFactory().openSession()) { + transaction = session.beginTransaction(); + session.save(user); + transaction.commit(); + } catch (Exception e) { + if (transaction != null) { + transaction.rollback(); + } + } + } + + public List getUsers() { + try (Session session = HibernateConfig.getSessionFactory().openSession()) { + return session.createQuery("from User", User.class).list(); + } + } +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/hibernateunproxy/CreditCardPayment.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/hibernateunproxy/CreditCardPayment.java new file mode 100644 index 0000000000..6eb41f7ccc --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/hibernateunproxy/CreditCardPayment.java @@ -0,0 +1,20 @@ +package com.baeldung.jpa.hibernateunproxy; + +import javax.persistence.Entity; +import java.math.BigDecimal; + +@Entity +public class CreditCardPayment extends Payment { + + private String cardNumber; + + CreditCardPayment(BigDecimal amount, WebUser webUser, String cardNumber) { + this.amount = amount; + this.webUser = webUser; + this.cardNumber = cardNumber; + } + + protected CreditCardPayment() { + } + +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/hibernateunproxy/Payment.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/hibernateunproxy/Payment.java new file mode 100644 index 0000000000..9e70da5f65 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/hibernateunproxy/Payment.java @@ -0,0 +1,47 @@ +package com.baeldung.jpa.hibernateunproxy; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Inheritance; +import javax.persistence.InheritanceType; +import javax.persistence.ManyToOne; +import java.math.BigDecimal; +import java.util.Objects; + +@Entity +@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) +public abstract class Payment { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + protected WebUser webUser; + + protected BigDecimal amount; + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Payment payment = (Payment) o; + + return Objects.equals(id, payment.id); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + protected Payment() { + } + +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/hibernateunproxy/PaymentReceipt.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/hibernateunproxy/PaymentReceipt.java new file mode 100644 index 0000000000..530839eef4 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/hibernateunproxy/PaymentReceipt.java @@ -0,0 +1,53 @@ +package com.baeldung.jpa.hibernateunproxy; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToOne; +import java.util.Objects; +import java.util.UUID; + +@Entity +public class PaymentReceipt { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @OneToOne(fetch = FetchType.LAZY) + private Payment payment; + + private String transactionNumber; + + PaymentReceipt(Payment payment) { + this.payment = payment; + this.transactionNumber = UUID.randomUUID().toString(); + } + + public Payment getPayment() { + return payment; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + PaymentReceipt that = (PaymentReceipt) o; + + return Objects.equals(id, that.id); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + protected PaymentReceipt() { + } + +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/hibernateunproxy/WebUser.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/hibernateunproxy/WebUser.java new file mode 100644 index 0000000000..d3f82bacd4 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/hibernateunproxy/WebUser.java @@ -0,0 +1,42 @@ +package com.baeldung.jpa.hibernateunproxy; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import java.util.Objects; + +@Entity +public class WebUser { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + WebUser(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + WebUser webUser = (WebUser) o; + + return Objects.equals(id, webUser.id); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + protected WebUser() { + } + +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/index/Student.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/index/Student.java new file mode 100644 index 0000000000..45de3f3fc4 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/index/Student.java @@ -0,0 +1,70 @@ +package com.baeldung.jpa.index; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Index; +import javax.persistence.Table; +import java.io.Serializable; +import java.util.Objects; + +@Entity +@Table(indexes = { + @Index(columnList = "firstName"), + @Index(name = "fn_index", columnList = "id"), + @Index(name = "multiIndex1", columnList = "firstName, lastName"), + @Index(name = "multiIndex2", columnList = "lastName, firstName"), + @Index(name = "multiSortIndex", columnList = "firstName, lastName DESC"), + @Index(name = "uniqueIndex", columnList = "firstName", unique = true), + @Index(name = "uniqueMultiIndex", columnList = "firstName, lastName", unique = true) +}) +public class Student implements Serializable { + @Id + @GeneratedValue + private Long id; + private String firstName; + private String lastName; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Student student = (Student) o; + return Objects.equals(id, student.id) && + Objects.equals(firstName, student.firstName) && + Objects.equals(lastName, student.lastName); + } + + @Override + public int hashCode() { + return Objects.hash(id, firstName, lastName); + } +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Album.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Album.java new file mode 100644 index 0000000000..96615b4ee2 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Album.java @@ -0,0 +1,52 @@ +package com.baeldung.jpa.multiplebagfetchexception; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToMany; +import javax.persistence.OneToMany; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +@Entity +class Album { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + @OneToMany(mappedBy = "album") + private List songs; + + @ManyToMany(mappedBy = "followingAlbums") + private Set followers; + + Album(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Album album = (Album) o; + + return Objects.equals(id, album.id); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + protected Album() { + } + +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Artist.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Artist.java new file mode 100644 index 0000000000..b87de27629 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Artist.java @@ -0,0 +1,56 @@ +package com.baeldung.jpa.multiplebagfetchexception; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +@Entity +class Artist { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + @OneToMany(mappedBy = "artist") + private List songs; + + @OneToMany(mappedBy = "artist", cascade = CascadeType.PERSIST) + private List offers; + + Artist(String name) { + this.name = name; + this.offers = new ArrayList<>(); + } + + void createOffer(String description) { + this.offers.add(new Offer(description, this)); + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Artist artist = (Artist) o; + + return Objects.equals(id, artist.id); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + protected Artist() { + } +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/FavoriteSong.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/FavoriteSong.java new file mode 100644 index 0000000000..43bd39487e --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/FavoriteSong.java @@ -0,0 +1,52 @@ +package com.baeldung.jpa.multiplebagfetchexception; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import java.util.Objects; + +@Entity +class FavoriteSong { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @ManyToOne + private Song song; + + @ManyToOne + private User user; + + @Column(name = "arrangement_index", nullable = false) + private int arrangementIndex; + + FavoriteSong(Song song, User user) { + this.song = song; + this.user = user; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + FavoriteSong likedSong = (FavoriteSong) o; + + return Objects.equals(id, likedSong.id); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + protected FavoriteSong() { + } + +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Offer.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Offer.java new file mode 100644 index 0000000000..54f355dfff --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Offer.java @@ -0,0 +1,46 @@ +package com.baeldung.jpa.multiplebagfetchexception; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +class Offer { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + @ManyToOne + private Artist artist; + + Offer(String name, Artist artist) { + this.name = name; + this.artist = artist; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Offer offer = (Offer) o; + + return id != null ? id.equals(offer.id) : offer.id == null; + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + protected Offer() { + } + +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Playlist.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Playlist.java new file mode 100644 index 0000000000..7fa96c3355 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Playlist.java @@ -0,0 +1,47 @@ +package com.baeldung.jpa.multiplebagfetchexception; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import java.util.Objects; + +@Entity +class Playlist { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + @ManyToOne + private User createdBy; + + Playlist(String name, User createdBy) { + this.name = name; + this.createdBy = createdBy; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Playlist playlist = (Playlist) o; + + return Objects.equals(id, playlist.id); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + protected Playlist() { + } + +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Song.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Song.java new file mode 100644 index 0000000000..8cb4ca0ae4 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/Song.java @@ -0,0 +1,55 @@ +package com.baeldung.jpa.multiplebagfetchexception; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import java.util.Objects; + +@Entity +class Song { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + @ManyToOne + private Album album; + + @ManyToOne + private Artist artist; + + Song(String name, Artist artist) { + this.name = name; + this.artist = artist; + } + + void assignToAlbum(Album album) { + this.album = album; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Song song = (Song) o; + + return Objects.equals(id, song.id); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + protected Song() { + } + +} + \ No newline at end of file diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/User.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/User.java new file mode 100644 index 0000000000..d475baddab --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/multiplebagfetchexception/User.java @@ -0,0 +1,74 @@ +package com.baeldung.jpa.multiplebagfetchexception; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToMany; +import javax.persistence.OneToMany; +import javax.persistence.OrderColumn; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +@Entity +class User { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + @OneToMany(mappedBy = "createdBy", cascade = CascadeType.PERSIST) + private List playlists; + + @OneToMany(mappedBy = "user", cascade = CascadeType.PERSIST) + @OrderColumn(name = "arrangement_index") + private List favoriteSongs; + + @ManyToMany + private Set followingAlbums; + + User(String name) { + this.name = name; + this.playlists = new ArrayList<>(); + this.favoriteSongs = new ArrayList<>(); + this.followingAlbums = new HashSet<>(); + } + + void followAlbum(Album album) { + this.followingAlbums.add(album); + } + + void createPlaylist(String name) { + this.playlists.add(new Playlist(name, this)); + } + + void addSongToFavorites(Song song) { + this.favoriteSongs.add(new FavoriteSong(song, this)); + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + User user = (User) o; + + return Objects.equals(id, user.id); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + protected User() { + } +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/removal/LineItem.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/removal/LineItem.java new file mode 100644 index 0000000000..9ab2dd4e74 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/removal/LineItem.java @@ -0,0 +1,45 @@ +package com.baeldung.jpa.removal; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import java.util.Objects; + +@Entity +public class LineItem { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + @ManyToOne + private OrderRequest orderRequest; + + public LineItem(String name) { + this.name = name; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + LineItem lineItem = (LineItem) o; + + return Objects.equals(id, lineItem.id); + } + + @Override + public int hashCode() { + return id != null ? id.hashCode() : 0; + } + + protected LineItem() { + } +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/removal/OrderRequest.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/removal/OrderRequest.java new file mode 100644 index 0000000000..739c110d8c --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/removal/OrderRequest.java @@ -0,0 +1,43 @@ +package com.baeldung.jpa.removal; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.OneToOne; +import java.util.List; + +@Entity +public class OrderRequest { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @OneToOne(cascade = { CascadeType.REMOVE, CascadeType.PERSIST }) + private ShipmentInfo shipmentInfo; + + @OneToMany(orphanRemoval = true, cascade = CascadeType.PERSIST, mappedBy = "orderRequest") + private List lineItems; + + public OrderRequest(ShipmentInfo shipmentInfo) { + this.shipmentInfo = shipmentInfo; + } + + public OrderRequest(List lineItems) { + this.lineItems = lineItems; + } + + public void removeLineItem(LineItem lineItem) { + lineItems.remove(lineItem); + } + + public void setLineItems(List lineItems) { + this.lineItems = lineItems; + } + + protected OrderRequest() { + } +} diff --git a/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/removal/ShipmentInfo.java b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/removal/ShipmentInfo.java new file mode 100644 index 0000000000..12274bcadf --- /dev/null +++ b/persistence-modules/java-jpa-3/src/main/java/com/baeldung/jpa/removal/ShipmentInfo.java @@ -0,0 +1,23 @@ +package com.baeldung.jpa.removal; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class ShipmentInfo { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + public ShipmentInfo(String name) { + this.name = name; + } + + protected ShipmentInfo() { + } +} diff --git a/persistence-modules/java-jpa-3/src/main/resources/META-INF/persistence.xml b/persistence-modules/java-jpa-3/src/main/resources/META-INF/persistence.xml index 28a929f912..19ecae8491 100644 --- a/persistence-modules/java-jpa-3/src/main/resources/META-INF/persistence.xml +++ b/persistence-modules/java-jpa-3/src/main/resources/META-INF/persistence.xml @@ -1,25 +1,100 @@ - - org.hibernate.jpa.HibernatePersistenceProvider - com.baeldung.jpa.equality.EqualByJavaDefault - com.baeldung.jpa.equality.EqualById - com.baeldung.jpa.equality.EqualByBusinessKey - true - - - - - - - - - - - - + version="2.2"> + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.equality.EqualByJavaDefault + com.baeldung.jpa.equality.EqualById + com.baeldung.jpa.equality.EqualByBusinessKey + true + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.removal.ShipmentInfo + com.baeldung.jpa.removal.LineItem + com.baeldung.jpa.removal.OrderRequest + true + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.index.Student + true + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.multiplebagfetchexception.Album + com.baeldung.jpa.multiplebagfetchexception.Song + com.baeldung.jpa.multiplebagfetchexception.User + com.baeldung.jpa.multiplebagfetchexception.Artist + com.baeldung.jpa.multiplebagfetchexception.Offer + com.baeldung.jpa.multiplebagfetchexception.Playlist + com.baeldung.jpa.multiplebagfetchexception.FavoriteSong + true + + + + + + + + + + + + + + org.hibernate.jpa.HibernatePersistenceProvider + com.baeldung.jpa.hibernateunproxy.Payment + com.baeldung.jpa.hibernateunproxy.CreditCardPayment + com.baeldung.jpa.hibernateunproxy.PaymentReceipt + com.baeldung.jpa.hibernateunproxy.WebUser + true + + + + + + + + + + + + + diff --git a/persistence-modules/java-jpa-3/src/main/resources/logback.xml b/persistence-modules/java-jpa-3/src/main/resources/logback.xml index 2527fea245..8000740dd1 100644 --- a/persistence-modules/java-jpa-3/src/main/resources/logback.xml +++ b/persistence-modules/java-jpa-3/src/main/resources/logback.xml @@ -8,7 +8,7 @@ - + diff --git a/persistence-modules/java-jpa-3/src/test/java/com/baeldung/ignorable/fields/TransientFieldUnitTest.java b/persistence-modules/java-jpa-3/src/test/java/com/baeldung/ignorable/fields/TransientFieldUnitTest.java new file mode 100644 index 0000000000..114a4cca4c --- /dev/null +++ b/persistence-modules/java-jpa-3/src/test/java/com/baeldung/ignorable/fields/TransientFieldUnitTest.java @@ -0,0 +1,79 @@ +package com.baeldung.ignorable.fields; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.io.*; +import java.util.List; +import java.util.Random; + +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module; + +public class TransientFieldUnitTest { + + private final UserDao userDao = new UserDao(); + + private final int randInt = new Random().nextInt(); + + private final User user = new User("user" + randInt + "@bar.com", "hunter2", "MacOSX"); + + @Test + public void givenFieldWithTransientAnnotation_whenSavingViaJPA_thenFieldIgnored() { + userDao.saveUser(user); + List allUsers = userDao.getUsers(); + User savedUser = allUsers.get(allUsers.indexOf(user)); + + assertNull(savedUser.getCurrentDevice()); + } + + @Test + public void givenFieldWithTransientAnnotation_whenSerializingObject_thenFieldSerialized() throws IOException, ClassNotFoundException { + + FileOutputStream fout = new FileOutputStream("test.obj"); + ObjectOutputStream out = new ObjectOutputStream(fout); + out.writeObject(user); + out.flush(); + out.close(); + + FileInputStream fin = new FileInputStream("test.obj"); + ObjectInputStream in = new ObjectInputStream(fin); + User savedUser = (User) in.readObject(); + in.close(); + + assertEquals(user.getCurrentDevice(), savedUser.getCurrentDevice()); + } + + @Test + public void givenFieldWithTransientAnnotation_whenSerializingToJSON_thenFieldSerialized() throws JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + String json = objectMapper.writeValueAsString(user); + User savedUser = objectMapper.readValue(json, User.class); + + assertEquals(user.getCurrentDevice(), savedUser.getCurrentDevice()); + } + + @Test + public void givenJacksonHibernate5Module_whenSerializingTransientAnnotation_thenFieldIgnored() throws JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.registerModule(new Hibernate5Module()); + String json = objectMapper.writeValueAsString(user); + User savedUser = objectMapper.readValue(json, User.class); + + assertNull(savedUser.getCurrentDevice()); + } + + @Test + public void givenPropagateTransientFieldFlag_whenSerializingTransientAnnotation_thenFieldSerialized() throws JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true); + String json = objectMapper.writeValueAsString(user); + User savedUser = objectMapper.readValue(json, User.class); + + assertEquals(user.getCurrentDevice(), savedUser.getCurrentDevice()); + } +} diff --git a/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/hibernateunproxy/HibernateProxyIntegrationTest.java b/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/hibernateunproxy/HibernateProxyIntegrationTest.java new file mode 100644 index 0000000000..717745bb13 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/hibernateunproxy/HibernateProxyIntegrationTest.java @@ -0,0 +1,75 @@ +package com.baeldung.jpa.hibernateunproxy; + +import org.hibernate.Hibernate; +import org.hibernate.proxy.HibernateProxy; +import org.junit.Assert; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import java.math.BigDecimal; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class HibernateProxyIntegrationTest { + + private static EntityManager entityManager; + + @BeforeAll + public static void setup() { + EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa-h2-hibernate-unproxy"); + entityManager = factory.createEntityManager(); + populateH2DB(); + } + + @Test + public void givenPaymentReceipt_whenAccessingPayment_thenVerifyType() { + PaymentReceipt paymentReceipt = entityManager.find(PaymentReceipt.class, 3L); + Assert.assertTrue(paymentReceipt.getPayment() instanceof HibernateProxy); + } + + @Test + public void givenWebUserProxy_whenCreatingPayment_thenExecuteSingleStatement() { + entityManager.getTransaction().begin(); + + WebUser webUser = entityManager.getReference(WebUser.class, 1L); + Payment payment = new CreditCardPayment(new BigDecimal(100), webUser, "CN-1234"); + entityManager.persist(payment); + + entityManager.getTransaction().commit(); + Assert.assertTrue(webUser instanceof HibernateProxy); + } + + @Test + public void givenPaymentReceipt_whenCastingPaymentToConcreteClass_thenThrowClassCastException() { + PaymentReceipt paymentReceipt = entityManager.find(PaymentReceipt.class, 3L); + assertThrows(ClassCastException.class, () -> { + CreditCardPayment creditCardPayment = (CreditCardPayment) paymentReceipt.getPayment(); + }); + } + + @Test + public void givenPaymentReceipt_whenPaymentIsUnproxied_thenReturnRealEntityObject() { + PaymentReceipt paymentReceipt = entityManager.find(PaymentReceipt.class, 3L); + Assert.assertTrue(Hibernate.unproxy(paymentReceipt.getPayment()) instanceof CreditCardPayment); + } + + private static void populateH2DB() { + entityManager.getTransaction().begin(); + + WebUser webUser = new WebUser("name"); + entityManager.persist(webUser); + + Payment payment = new CreditCardPayment(new BigDecimal(100), webUser, "CN-1234"); + entityManager.persist(payment); + + PaymentReceipt receipt = new PaymentReceipt(payment); + entityManager.persist(receipt); + + entityManager.getTransaction().commit(); + entityManager.clear(); + } + +} diff --git a/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/index/IndexIntegrationTest.java b/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/index/IndexIntegrationTest.java new file mode 100644 index 0000000000..f59450567b --- /dev/null +++ b/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/index/IndexIntegrationTest.java @@ -0,0 +1,50 @@ +package com.baeldung.jpa.index; + +import org.hibernate.exception.ConstraintViolationException; +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import java.util.Optional; + +public class IndexIntegrationTest { + private static EntityManagerFactory factory; + private static EntityManager entityManager; + + @BeforeClass + public static void setup() { + factory = Persistence.createEntityManagerFactory("jpa-index"); + entityManager = factory.createEntityManager(); + } + + @Test + public void givenStudent_whenPersistStudentWithSameFirstName_thenConstraintViolationException() { + Student student = new Student(); + student.setFirstName("FirstName"); + student.setLastName("LastName"); + + Student student2 = new Student(); + student2.setFirstName("FirstName"); + student2.setLastName("LastName2"); + + entityManager.getTransaction().begin(); + entityManager.persist(student); + entityManager.getTransaction().commit(); + + Assert.assertEquals(1L, (long) student.getId()); + + entityManager.getTransaction().begin(); + try { + entityManager.persist(student2); + entityManager.getTransaction().commit(); + Assert.fail("Should raise an exception - unique key violation"); + } catch (Exception ex) { + Assert.assertTrue(Optional.of(ex).map(Throwable::getCause).map(Throwable::getCause).filter(x -> x instanceof ConstraintViolationException).isPresent()); + } finally { + entityManager.getTransaction().rollback(); + } + } +} diff --git a/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/multiplebagfetchexception/MultipleBagFetchExceptionIntegrationTest.java b/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/multiplebagfetchexception/MultipleBagFetchExceptionIntegrationTest.java new file mode 100644 index 0000000000..648650ad8a --- /dev/null +++ b/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/multiplebagfetchexception/MultipleBagFetchExceptionIntegrationTest.java @@ -0,0 +1,124 @@ +package com.baeldung.jpa.multiplebagfetchexception; + +import org.hibernate.jpa.QueryHints; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.Query; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class MultipleBagFetchExceptionIntegrationTest { + + private static EntityManager entityManager; + + @BeforeAll + public static void setup() { + EntityManagerFactory factory = Persistence.createEntityManagerFactory("jpa-h2-multiple-bag-fetch-exception"); + entityManager = factory.createEntityManager(); + populateH2DB(); + } + + @Test + public void whenFetchingMoreThanOneBag_thenThrowAnException() { + IllegalArgumentException exception = + assertThrows(IllegalArgumentException.class, () -> { + String jpql = "SELECT artist FROM Artist artist " + + "JOIN FETCH artist.songs " + + "JOIN FETCH artist.offers "; + + entityManager.createQuery(jpql); + }); + + final String expectedMessagePart = "MultipleBagFetchException"; + final String actualMessage = exception.getMessage(); + + assertTrue(actualMessage.contains(expectedMessagePart)); + } + + @Test + public void whenFetchingOneBagAndSet_thenRetrieveSuccess() { + String jpql = "SELECT DISTINCT album FROM Album album " + + "LEFT JOIN FETCH album.songs " + + "LEFT JOIN FETCH album.followers " + + "WHERE album.id = 1"; + + Query query = entityManager.createQuery(jpql) + .setHint(QueryHints.HINT_PASS_DISTINCT_THROUGH, false); + + assertEquals(1, query.getResultList().size()); + } + + @Test + public void whenUsingMultipleQueries_thenRetrieveSuccess() { + String jpql = "SELECT DISTINCT artist FROM Artist artist " + + "LEFT JOIN FETCH artist.songs "; + + List artists = entityManager.createQuery(jpql, Artist.class) + .setHint(QueryHints.HINT_PASS_DISTINCT_THROUGH, false) + .getResultList(); + + jpql = "SELECT DISTINCT artist FROM Artist artist " + + "LEFT JOIN FETCH artist.offers " + + "WHERE artist IN :artists "; + + artists = entityManager.createQuery(jpql, Artist.class) + .setParameter("artists", artists) + .setHint(QueryHints.HINT_PASS_DISTINCT_THROUGH, false) + .getResultList(); + + assertEquals(2, artists.size()); + } + + @Test + public void whenFetchingOneBagAndOneList_thenRetrieveSuccess() { + String jpql = "SELECT DISTINCT user FROM User user " + + "LEFT JOIN FETCH user.playlists " + + "LEFT JOIN FETCH user.favoriteSongs "; + + List users = entityManager.createQuery(jpql, User.class) + .setHint(QueryHints.HINT_PASS_DISTINCT_THROUGH, false) + .getResultList(); + + assertEquals(3, users.size()); + } + + private static void populateH2DB() { + entityManager.getTransaction().begin(); + + Album album = new Album("album-name"); + Artist artist1 = new Artist("artist-name-1"); + Artist artist2 = new Artist("artist-name-2"); + artist2.createOffer("offer-name-1"); + artist2.createOffer("offer-name-2"); + entityManager.persist(album); + entityManager.persist(artist1); + entityManager.persist(artist2); + + Song song1 = new Song("song-name-1", artist2); + song1.assignToAlbum(album); + entityManager.persist(song1); + + User user1 = new User("user-name-1"); + user1.followAlbum(album); + entityManager.persist(user1); + + User user2 = new User("user-name-2"); + user2.followAlbum(album); + entityManager.persist(user2); + + User user3 = new User("user-name-3"); + user3.createPlaylist("playlist-name"); + user3.addSongToFavorites(song1); + entityManager.persist(user3); + + entityManager.getTransaction().commit(); + } + +} diff --git a/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/removal/CascadeTypeRemoveIntegrationTest.java b/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/removal/CascadeTypeRemoveIntegrationTest.java new file mode 100644 index 0000000000..8f99723ac6 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/removal/CascadeTypeRemoveIntegrationTest.java @@ -0,0 +1,73 @@ +package com.baeldung.jpa.removal; + +import org.junit.Assert; +import org.junit.BeforeClass; +import org.junit.Test; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; +import java.util.List; + +public class CascadeTypeRemoveIntegrationTest { + + private static EntityManagerFactory factory; + private static EntityManager entityManager; + + @BeforeClass + public static void setup() { + factory = Persistence.createEntityManagerFactory("jpa-h2-removal"); + entityManager = factory.createEntityManager(); + } + + @Test + public void whenOrderRequestIsDeleted_thenDeleteShipmentInfo() { + createOrderRequestWithShipmentInfo(); + + OrderRequest orderRequest = entityManager.find(OrderRequest.class, 1L); + + entityManager.getTransaction().begin(); + entityManager.remove(orderRequest); + entityManager.getTransaction().commit(); + + Assert.assertEquals(0, findAllOrderRequest().size()); + Assert.assertEquals(0, findAllShipmentInfo().size()); + } + + private void createOrderRequestWithShipmentInfo() { + ShipmentInfo shipmentInfo = new ShipmentInfo("name"); + OrderRequest orderRequest = new OrderRequest(shipmentInfo); + + entityManager.getTransaction().begin(); + entityManager.persist(orderRequest); + entityManager.getTransaction().commit(); + + Assert.assertEquals(1, findAllOrderRequest().size()); + Assert.assertEquals(1, findAllShipmentInfo().size()); + } + + private List findAllOrderRequest() { + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery(OrderRequest.class); + Root root = cq.from(OrderRequest.class); + CriteriaQuery findAll = cq.select(root); + TypedQuery findAllQuery = entityManager.createQuery(findAll); + + return findAllQuery.getResultList(); + } + + private List findAllShipmentInfo() { + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery(ShipmentInfo.class); + Root root = cq.from(ShipmentInfo.class); + CriteriaQuery findAll = cq.select(root); + TypedQuery findAllQuery = entityManager.createQuery(findAll); + + return findAllQuery.getResultList(); + } + +} diff --git a/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/removal/OrphanRemovalIntegrationTest.java b/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/removal/OrphanRemovalIntegrationTest.java new file mode 100644 index 0000000000..615e8cf3a8 --- /dev/null +++ b/persistence-modules/java-jpa-3/src/test/java/com/baeldung/jpa/removal/OrphanRemovalIntegrationTest.java @@ -0,0 +1,92 @@ +package com.baeldung.jpa.removal; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; +import javax.persistence.Persistence; +import javax.persistence.PersistenceException; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Root; +import java.util.ArrayList; +import java.util.List; + +public class OrphanRemovalIntegrationTest { + + private static EntityManagerFactory factory; + private static EntityManager entityManager; + + @Before + public void setup() { + factory = Persistence.createEntityManagerFactory("jpa-h2-removal"); + entityManager = factory.createEntityManager(); + } + + @Test + public void whenLineItemIsRemovedFromOrderRequest_thenDeleteOrphanedLineItem() { + createOrderRequestWithLineItems(); + + OrderRequest orderRequest = entityManager.find(OrderRequest.class, 1L); + LineItem lineItem = entityManager.find(LineItem.class, 2L); + orderRequest.removeLineItem(lineItem); + + entityManager.getTransaction().begin(); + entityManager.merge(orderRequest); + entityManager.getTransaction().commit(); + + Assert.assertEquals(1, findAllOrderRequest().size()); + Assert.assertEquals(2, findAllLineItem().size()); + } + + @Test(expected = PersistenceException.class) + public void whenLineItemsIsReassigned_thenThrowAnException() { + createOrderRequestWithLineItems(); + + OrderRequest orderRequest = entityManager.find(OrderRequest.class, 1L); + orderRequest.setLineItems(new ArrayList<>()); + + entityManager.getTransaction().begin(); + entityManager.merge(orderRequest); + entityManager.getTransaction().commit(); + } + + private void createOrderRequestWithLineItems() { + List lineItems = new ArrayList<>(); + lineItems.add(new LineItem("line item 1")); + lineItems.add(new LineItem("line item 2")); + lineItems.add(new LineItem("line item 3")); + + OrderRequest orderRequest = new OrderRequest(lineItems); + + entityManager.getTransaction().begin(); + entityManager.persist(orderRequest); + entityManager.getTransaction().commit(); + + Assert.assertEquals(1, findAllOrderRequest().size()); + Assert.assertEquals(3, findAllLineItem().size()); + } + + private List findAllOrderRequest() { + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery(OrderRequest.class); + Root root = cq.from(OrderRequest.class); + CriteriaQuery findAll = cq.select(root); + TypedQuery findAllQuery = entityManager.createQuery(findAll); + + return findAllQuery.getResultList(); + } + + private List findAllLineItem() { + CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + CriteriaQuery cq = cb.createQuery(LineItem.class); + Root root = cq.from(LineItem.class); + CriteriaQuery findAll = cq.select(root); + TypedQuery findAllQuery = entityManager.createQuery(findAll); + + return findAllQuery.getResultList(); + } +} diff --git a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/enums/ArticleUnitTest.java b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/enums/ArticleUnitTest.java index 82f3abc04d..9d98d6b86f 100644 --- a/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/enums/ArticleUnitTest.java +++ b/persistence-modules/java-jpa/src/test/java/com/baeldung/jpa/enums/ArticleUnitTest.java @@ -7,7 +7,9 @@ import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Persistence; +import javax.persistence.TypedQuery; import java.util.HashMap; +import java.util.List; import java.util.Map; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -19,7 +21,7 @@ public class ArticleUnitTest { @BeforeClass public static void setup() { - Map properties = new HashMap(); + Map properties = new HashMap<>(); properties.put("hibernate.show_sql", "true"); properties.put("hibernate.format_sql", "true"); emFactory = Persistence.createEntityManagerFactory("jpa-h2", properties); @@ -115,4 +117,53 @@ public class ArticleUnitTest { assertEquals(Category.MUSIC, persistedArticle.getCategory()); } + @Test + public void shouldFindArticleByCategory() { + // given + Article article = new Article(); + article.setId(5); + article.setTitle("static"); + article.setCategory(Category.SPORT); + + EntityTransaction tx = em.getTransaction(); + tx.begin(); + em.persist(article); + tx.commit(); + + String jpql = "select a from Article a where a.category = com.baeldung.jpa.enums.Category.SPORT"; + + // when + List
articles = em.createQuery(jpql, Article.class).getResultList(); + + // then + assertEquals(1, articles.size()); + assertEquals(Category.SPORT, articles.get(0).getCategory()); + assertEquals("static", articles.get(0).getTitle()); + } + + @Test + public void shouldFindArticleByCategoryParameter() { + // given + Article article = new Article(); + article.setId(6); + article.setTitle("dynamic"); + article.setCategory(Category.TECHNOLOGY); + + EntityTransaction tx = em.getTransaction(); + tx.begin(); + em.persist(article); + tx.commit(); + + String jpql = "select a from Article a where a.category = :category"; + + // when + TypedQuery
query = em.createQuery(jpql, Article.class); + query.setParameter("category", Category.TECHNOLOGY); + List
articles = query.getResultList(); + + // then + assertEquals(1, articles.size()); + assertEquals(Category.TECHNOLOGY, articles.get(0).getCategory()); + assertEquals("dynamic", articles.get(0).getTitle()); + } } \ No newline at end of file diff --git a/persistence-modules/jnosql/pom.xml b/persistence-modules/jnosql/pom.xml index fb7ac72b05..81c62ee562 100644 --- a/persistence-modules/jnosql/pom.xml +++ b/persistence-modules/jnosql/pom.xml @@ -21,7 +21,7 @@ - 0.0.5 + 0.0.6 diff --git a/persistence-modules/jooq/README.md b/persistence-modules/jooq/README.md new file mode 100644 index 0000000000..348baab50c --- /dev/null +++ b/persistence-modules/jooq/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Getting Started with jOOQ](https://www.baeldung.com/jooq-intro) diff --git a/persistence-modules/jooq/src/main/java/com/baeldung/jooq/Crud.java b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/Crud.java index 0427b71c25..fb3d21c467 100644 --- a/persistence-modules/jooq/src/main/java/com/baeldung/jooq/Crud.java +++ b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/Crud.java @@ -19,14 +19,14 @@ public class Crud { public static Result getAll(DSLContext context, Table table) { return context.select() - .from(table) - .fetch(); + .from(table) + .fetch(); } public static Result getFields(DSLContext context, Table table, SelectFieldOrAsterisk... fields) { return context.select(fields) - .from(table) - .fetch(); + .from(table) + .fetch(); } public static R getOne(DSLContext context, Table table, Condition condition) { @@ -35,9 +35,9 @@ public class Crud { public static void update(DSLContext context, Table table, Map, T> values, Condition condition) { context.update(table) - .set(values) - .where(condition) - .execute(); + .set(values) + .where(condition) + .execute(); } public static > void update(UpdatableRecord record) { @@ -46,8 +46,8 @@ public class Crud { public static void delete(DSLContext context, Table table, Condition condition) { context.delete(table) - .where(condition) - .execute(); + .where(condition) + .execute(); } public static > void delete(UpdatableRecord record) { diff --git a/persistence-modules/jooq/src/main/java/com/baeldung/jooq/CrudExamples.java b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/CrudExamples.java index 87a7b6439e..57f6df4915 100644 --- a/persistence-modules/jooq/src/main/java/com/baeldung/jooq/CrudExamples.java +++ b/persistence-modules/jooq/src/main/java/com/baeldung/jooq/CrudExamples.java @@ -60,8 +60,8 @@ public class CrudExamples { private void readValues(DSLContext context) { Result authors = getAll( - context, - Author.AUTHOR + context, + Author.AUTHOR ); authors.forEach(author -> { @@ -73,15 +73,15 @@ public class CrudExamples { }); Result articles = getFields( - context, - Author.AUTHOR, - Article.ARTICLE.ID, Article.ARTICLE.TITLE + context, + Author.AUTHOR, + Article.ARTICLE.ID, Article.ARTICLE.TITLE ); AuthorRecord author = getOne( - context, - Author.AUTHOR, - Author.AUTHOR.ID.eq(1) + context, + Author.AUTHOR, + Author.AUTHOR.ID.eq(1) ); } @@ -90,24 +90,22 @@ public class CrudExamples { fieldsToUpdate.put(Author.AUTHOR.FIRST_NAME, "David"); fieldsToUpdate.put(Author.AUTHOR.LAST_NAME, "Brown"); update( - context, - Author.AUTHOR, - fieldsToUpdate, - Author.AUTHOR.ID.eq(1) + context, + Author.AUTHOR, + fieldsToUpdate, + Author.AUTHOR.ID.eq(1) ); ArticleRecord article = context.fetchOne(Article.ARTICLE, Article.ARTICLE.ID.eq(1)); article.setTitle("A New Article Title"); - update( - article - ); + update(article); } private void deleteValues(DSLContext context) { delete( - context, - Article.ARTICLE, - Article.ARTICLE.ID.eq(1) + context, + Article.ARTICLE, + Article.ARTICLE.ID.eq(1) ); AuthorRecord author = context.fetchOne(Author.AUTHOR, Author.AUTHOR.ID.eq(1)); diff --git a/persistence-modules/pom.xml b/persistence-modules/pom.xml index 590e5da76e..8789a8473b 100644 --- a/persistence-modules/pom.xml +++ b/persistence-modules/pom.xml @@ -17,6 +17,7 @@ apache-bookkeeper apache-cayenne core-java-persistence + core-java-persistence-2 deltaspike elasticsearch flyway @@ -81,11 +82,11 @@ spring-data-redis spring-data-solr spring-hibernate-3 - spring-hibernate-5 - spring-hibernate4 + spring-hibernate-5 spring-jpa spring-jpa-2 spring-jdbc + spring-jooq spring-persistence-simple diff --git a/persistence-modules/querydsl/pom.xml b/persistence-modules/querydsl/pom.xml index 9f6802ff77..a611c309b6 100644 --- a/persistence-modules/querydsl/pom.xml +++ b/persistence-modules/querydsl/pom.xml @@ -31,7 +31,7 @@ org.hibernate - hibernate-entitymanager + hibernate-core ${hibernate.version} compile diff --git a/persistence-modules/r2dbc/pom.xml b/persistence-modules/r2dbc/pom.xml index 7083eea64d..01f1b351cd 100644 --- a/persistence-modules/r2dbc/pom.xml +++ b/persistence-modules/r2dbc/pom.xml @@ -69,10 +69,6 @@ 0.8.1.RELEASE 1.4.200 - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/redis/pom.xml b/persistence-modules/redis/pom.xml index 9e00566767..fa82bebc64 100644 --- a/persistence-modules/redis/pom.xml +++ b/persistence-modules/redis/pom.xml @@ -62,10 +62,6 @@ 3.3.0 4.1.50.Final - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/redis/src/test/java/com/baeldung/spring/redis/configuration/controller/BooksControllerUnitTest.java b/persistence-modules/redis/src/test/java/com/baeldung/spring/redis/configuration/controller/BooksControllerUnitTest.java index a5c3340065..757b32385b 100644 --- a/persistence-modules/redis/src/test/java/com/baeldung/spring/redis/configuration/controller/BooksControllerUnitTest.java +++ b/persistence-modules/redis/src/test/java/com/baeldung/spring/redis/configuration/controller/BooksControllerUnitTest.java @@ -10,15 +10,15 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.baeldung.spring.redis.configuration.entity.Book; import com.baeldung.spring.redis.configuration.repository.BooksRepository; -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(MockitoJUnitRunner.class) public class BooksControllerUnitTest { - @Spy @InjectMocks private BooksController booksController; diff --git a/persistence-modules/redis/src/test/java/com/baeldung/spring/redis/configuration/repository/BooksRepositoryUnitTest.java b/persistence-modules/redis/src/test/java/com/baeldung/spring/redis/configuration/repository/BooksRepositoryUnitTest.java index 1edf9c7e89..f32800e165 100644 --- a/persistence-modules/redis/src/test/java/com/baeldung/spring/redis/configuration/repository/BooksRepositoryUnitTest.java +++ b/persistence-modules/redis/src/test/java/com/baeldung/spring/redis/configuration/repository/BooksRepositoryUnitTest.java @@ -11,16 +11,16 @@ import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.baeldung.spring.redis.configuration.entity.Book; -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(MockitoJUnitRunner.class) public class BooksRepositoryUnitTest { - @Spy @InjectMocks private BooksRepository booksRepository; diff --git a/persistence-modules/spring-boot-mysql/pom.xml b/persistence-modules/spring-boot-mysql/pom.xml index 9b8c6d0028..834d1d1e64 100644 --- a/persistence-modules/spring-boot-mysql/pom.xml +++ b/persistence-modules/spring-boot-mysql/pom.xml @@ -40,10 +40,6 @@ 8.0.12 - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/spring-boot-persistence-2/README.md b/persistence-modules/spring-boot-persistence-2/README.md index 392218d2bf..d7c13fd363 100644 --- a/persistence-modules/spring-boot-persistence-2/README.md +++ b/persistence-modules/spring-boot-persistence-2/README.md @@ -5,4 +5,6 @@ - [Integrating Spring Boot with HSQLDB](https://www.baeldung.com/spring-boot-hsqldb) - [List of In-Memory Databases](https://www.baeldung.com/java-in-memory-databases) - [Oracle Connection Pooling With Spring](https://www.baeldung.com/spring-oracle-connection-pooling) +- [Object States in Hibernate’s Session](https://www.baeldung.com/hibernate-session-object-states) +- [Storing Files Indexed by a Database](https://www.baeldung.com/java-db-storing-files) - More articles: [[<-- prev]](../spring-boot-persistence) diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/FileLocationService.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/FileLocationService.java new file mode 100644 index 0000000000..6b2f33e885 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/FileLocationService.java @@ -0,0 +1,31 @@ +package com.baeldung.db.indexing; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.web.server.ResponseStatusException; + +@Service +class FileLocationService { + + @Autowired + FileSystemRepository fileSystemRepository; + @Autowired + ImageDbRepository imageDbRepository; + + Long save(byte[] bytes, String imageName) throws Exception { + String location = fileSystemRepository.save(bytes, imageName); + + return imageDbRepository.save(new Image(imageName, location)) + .getId(); + } + + FileSystemResource find(Long imageId) { + Image image = imageDbRepository.findById(imageId) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)); + + return fileSystemRepository.findInFileSystem(image.getLocation()); + } + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/FileSystemImageController.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/FileSystemImageController.java new file mode 100644 index 0000000000..09e33bb943 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/FileSystemImageController.java @@ -0,0 +1,30 @@ +package com.baeldung.db.indexing; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.MediaType; +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.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +@RestController +@RequestMapping("file-system") +class FileSystemImageController { + + @Autowired + FileLocationService fileLocationService; + + @PostMapping("/image") + Long uploadImage(@RequestParam MultipartFile image) throws Exception { + return fileLocationService.save(image.getBytes(), image.getOriginalFilename()); + } + + @GetMapping(value = "/image/{imageId}", produces = MediaType.IMAGE_JPEG_VALUE) + FileSystemResource downloadImage(@PathVariable Long imageId) throws Exception { + return fileLocationService.find(imageId); + } +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/FileSystemRepository.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/FileSystemRepository.java new file mode 100644 index 0000000000..bc6bdecfed --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/FileSystemRepository.java @@ -0,0 +1,36 @@ +package com.baeldung.db.indexing; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Date; + +import org.springframework.core.io.FileSystemResource; +import org.springframework.stereotype.Repository; + +@Repository +class FileSystemRepository { + + String RESOURCES_DIR = FileSystemRepository.class.getResource("/") + .getPath(); + + String save(byte[] content, String imageName) throws Exception { + Path newFile = Paths.get(RESOURCES_DIR + new Date().getTime() + "-" + imageName); + Files.createDirectories(newFile.getParent()); + + Files.write(newFile, content); + + return newFile.toAbsolutePath() + .toString(); + } + + FileSystemResource findInFileSystem(String location) { + try { + return new FileSystemResource(Paths.get(location)); + } catch (Exception e) { + // Handle access or file not found problems. + throw new RuntimeException(); + } + } + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/Image.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/Image.java new file mode 100644 index 0000000000..e3fcf53f81 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/Image.java @@ -0,0 +1,66 @@ +package com.baeldung.db.indexing; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Lob; + +@Entity +class Image { + + @Id + @GeneratedValue + Long id; + + String name; + + String location; + + @Lob + byte[] content; + + public Image() { + } + + public Image(Long id) { + this.id = id; + } + + public Image(String name, String location) { + this.name = name; + this.location = location; + } + + public byte[] getContent() { + return content; + } + + public void setContent(byte[] content) { + this.content = content; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/ImageArchiveApplication.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/ImageArchiveApplication.java new file mode 100644 index 0000000000..02d2db32b3 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/ImageArchiveApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.db.indexing; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ImageArchiveApplication { + + public static void main(String[] args) { + SpringApplication.run(ImageArchiveApplication.class, args); + } + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/ImageController.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/ImageController.java new file mode 100644 index 0000000000..1b2378a51f --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/ImageController.java @@ -0,0 +1,46 @@ +package com.baeldung.db.indexing; + +import java.io.IOException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ByteArrayResource; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +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.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.server.ResponseStatusException; + +import lombok.extern.slf4j.Slf4j; + +@RestController +@Slf4j +class ImageController { + + @Autowired + ImageDbRepository imageDbRepository; + + @PostMapping("/image") + long uploadImage(@RequestParam MultipartFile multipartImage) throws IOException { + Image dbImage = new Image(); + dbImage.setName(multipartImage.getOriginalFilename()); + dbImage.setContent(multipartImage.getBytes()); + + return imageDbRepository.save(dbImage) + .getId(); + } + + @GetMapping(value = "/image/{imageId}", produces = MediaType.IMAGE_JPEG_VALUE) + Resource downloadImage(@PathVariable Long imageId) { + byte[] image = imageDbRepository.findById(imageId) + .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND)) + .getContent(); + + return new ByteArrayResource(image); + } + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/ImageDbRepository.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/ImageDbRepository.java new file mode 100644 index 0000000000..eb33f14dae --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/db/indexing/ImageDbRepository.java @@ -0,0 +1,9 @@ +package com.baeldung.db.indexing; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +interface ImageDbRepository extends JpaRepository { + +} diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/datetime/Application.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/Application.java similarity index 80% rename from persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/datetime/Application.java rename to persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/Application.java index 81e5a2f790..38118354e0 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/datetime/Application.java +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/Application.java @@ -1,13 +1,12 @@ -package com.baeldung.spring.data.jpa.query.datetime; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class Application { - - public static void main(String[] args) { - SpringApplication.run(Application.class, args); - } - -} +package com.baeldung.states; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/UserEntity.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/UserEntity.java new file mode 100644 index 0000000000..90bd275240 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/UserEntity.java @@ -0,0 +1,27 @@ +package com.baeldung.states; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +public class UserEntity { + @Id + private String name; + + @ManyToOne + private UserEntity manager; + + public UserEntity(String name) { + this.name = name; + } +} diff --git a/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/UserEntityWithCascade.java b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/UserEntityWithCascade.java new file mode 100644 index 0000000000..de0d62bfe2 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/main/java/com/baeldung/states/UserEntityWithCascade.java @@ -0,0 +1,28 @@ +package com.baeldung.states; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.ManyToOne; + +@Entity +@AllArgsConstructor +@NoArgsConstructor +@Getter +@Setter +public class UserEntityWithCascade { + @Id + private String name; + + @ManyToOne(cascade = CascadeType.PERSIST) + private UserEntityWithCascade manager; + + public UserEntityWithCascade(String name) { + this.name = name; + } +} diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/db/indexing/FileSystemImageIntegrationTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/db/indexing/FileSystemImageIntegrationTest.java new file mode 100644 index 0000000000..83f5bae095 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/db/indexing/FileSystemImageIntegrationTest.java @@ -0,0 +1,73 @@ +package com.baeldung.db.indexing; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.io.InputStream; +import java.nio.file.Paths; + +import org.junit.jupiter.api.Test; +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.boot.test.mock.mockito.MockBean; +import org.springframework.core.io.FileSystemResource; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +@SpringBootTest(classes = ImageArchiveApplication.class) +@AutoConfigureMockMvc +class FileSystemImageIntegrationTest { + + @Autowired + MockMvc mockMvc; + + @MockBean + FileLocationService fileLocationService; + + @Test + void givenJpegImage_whenUploadIt_thenReturnItsId() throws Exception { + ClassLoader classLoader = ClassLoader.getSystemClassLoader(); + InputStream image = classLoader.getResourceAsStream("baeldung.jpeg"); + + MockMultipartFile jpegImage = new MockMultipartFile("image", "baeldung", MediaType.TEXT_PLAIN_VALUE, image); + MockMultipartHttpServletRequestBuilder multipartRequest = MockMvcRequestBuilders.multipart("/file-system/image") + .file(jpegImage); + + given(fileLocationService.save(jpegImage.getBytes(), "baeldung")) + .willReturn(1L); + + MvcResult result = mockMvc.perform(multipartRequest) + .andExpect(status().isOk()) + .andReturn(); + + assertThat(result.getResponse() + .getContentAsString()) + .isEqualTo("1"); + } + + @Test + void givenBaeldungImage_whenDownloadIt_thenReturnTheImage() throws Exception { + given(fileLocationService.find(1L)) + .willReturn(baeldungJpegResource()); + + mockMvc.perform(MockMvcRequestBuilders + .get("/file-system/image/1") + .contentType(MediaType.IMAGE_JPEG_VALUE)) + .andExpect(status().isOk()); + } + + private FileSystemResource baeldungJpegResource() { + ClassLoader classLoader = ClassLoader.getSystemClassLoader(); + String imagePath = classLoader.getResource("baeldung.jpeg") + .getFile(); + + return new FileSystemResource(Paths.get(imagePath)); + } + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/db/indexing/ImageIntegrationTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/db/indexing/ImageIntegrationTest.java new file mode 100644 index 0000000000..e38e0a21a9 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/db/indexing/ImageIntegrationTest.java @@ -0,0 +1,78 @@ +package com.baeldung.db.indexing; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Optional; + +import org.junit.jupiter.api.Test; +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.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; + +@SpringBootTest(classes = ImageArchiveApplication.class) +@AutoConfigureMockMvc +class ImageIntegrationTest { + + @Autowired + MockMvc mockMvc; + + @MockBean + ImageDbRepository imageRepository; + + @Test + void givenBaeldungJpegImage_whenUploadIt_thenReturnItsId() throws Exception { + given(imageRepository.save(any())) + .willReturn(new Image(1L)); + + MvcResult result = mockMvc.perform(createUploadImageRequest()) + .andExpect(status().isOk()) + .andReturn(); + + assertThat(result.getResponse() + .getContentAsString()) + .isEqualTo("1"); + } + + @Test + void givenExistingImage_whenDownloadIt_thenReturnHttpStatusOk() throws Exception { + given(imageRepository.findById(1L)) + .willReturn(Optional.of(baeldungImage())); + + mockMvc.perform(MockMvcRequestBuilders + .get("/image/1") + .contentType(MediaType.IMAGE_JPEG_VALUE)) + .andExpect(status().isOk()); + } + + private MockMultipartHttpServletRequestBuilder createUploadImageRequest() throws IOException { + ClassLoader classLoader = ClassLoader.getSystemClassLoader(); + InputStream image = classLoader.getResourceAsStream("baeldung.jpeg"); + + return MockMvcRequestBuilders.multipart("/image") + .file(new MockMultipartFile("multipartImage", "baeldung", MediaType.TEXT_PLAIN_VALUE, image)); + } + + private Image baeldungImage() throws IOException { + ClassLoader classLoader = ClassLoader.getSystemClassLoader(); + + Image mockImage = new Image(); + mockImage.setContent(Files.readAllBytes(Paths.get(classLoader.getResource("baeldung.jpeg") + .getFile()))); + return mockImage; + } + +} diff --git a/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/states/UserEntityIntegrationTest.java b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/states/UserEntityIntegrationTest.java new file mode 100644 index 0000000000..5d0dc99ad7 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-2/src/test/java/com/baeldung/states/UserEntityIntegrationTest.java @@ -0,0 +1,136 @@ +package com.baeldung.states; + +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.Transaction; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.persistence.EntityManagerFactory; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@RunWith(SpringRunner.class) +@SpringBootTest +class UserEntityIntegrationTest { + @Autowired + private EntityManagerFactory entityManagerFactory; + + @Test + void givenName_thenShouldCreateDetachedUserEntity() { + // given + Session session = openSession(); + UserEntity userEntity = new UserEntity("John"); + + // then + assertThat(session.contains(userEntity)).isFalse(); + session.close(); + } + + @Test + void givenName_whenPersisted_thenShouldCreatePersistentUserEntity() { + // given + Session session = openSession(); + UserEntity userEntity = new UserEntity("John"); + + // when + session.persist(userEntity); + + // then + assertThat(session.contains(userEntity)).isTrue(); + session.close(); + } + + @Test + void givenPersistentEntity_whenSessionClosed_thenShouldDetachEntity() { + // given + Session session = openSession(); + UserEntity userEntity = new UserEntity("John"); + session.persist(userEntity); + assertThat(session.contains(userEntity)).isTrue(); + + // when + session.close(); + + // then + assertThat(session.isOpen()).isFalse(); + assertThatThrownBy(() -> session.contains(userEntity)); + } + + @Test + void givenPersistentEntity_whenAddedTransientManager_thenShouldThrowException() { + // given + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + UserEntity userEntity = new UserEntity("John"); + session.persist(userEntity); + UserEntity manager = new UserEntity("Adam"); + + // when + userEntity.setManager(manager); + + + // then + assertThatThrownBy(() -> { + session.saveOrUpdate(userEntity); + transaction.commit(); + }); + session.close(); + } + + @Test + void givenPersistentEntity_whenAddedPersistentManager_thenShouldSave() { + // given + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + UserEntity userEntity = new UserEntity("John"); + session.persist(userEntity); + UserEntity manager = new UserEntity("Adam"); + session.persist(manager); + + // when + userEntity.setManager(manager); + + + // then + session.saveOrUpdate(userEntity); + transaction.commit(); + session.close(); + + Session otherSession = openSession(); + UserEntity savedUser = otherSession.get(UserEntity.class, "John"); + assertThat(savedUser.getManager().getName()).isEqualTo("Adam"); + } + + @Test + void givenPersistentEntityWithCascade_whenAddedTransientManager_thenShouldSave() { + // given + Session session = openSession(); + Transaction transaction = session.beginTransaction(); + UserEntityWithCascade userEntity = new UserEntityWithCascade("John"); + session.persist(userEntity); + UserEntityWithCascade manager = new UserEntityWithCascade("Adam"); + + // when + userEntity.setManager(manager); + + + // then + session.saveOrUpdate(userEntity); + transaction.commit(); + session.close(); + + Session otherSession = openSession(); + UserEntityWithCascade savedUser = otherSession.get(UserEntityWithCascade.class, "John"); + assertThat(savedUser.getManager().getName()).isEqualTo("Adam"); + } + + + private Session openSession() { + return entityManagerFactory.unwrap(SessionFactory.class).openSession(); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-2/src/test/resources/baeldung.jpeg b/persistence-modules/spring-boot-persistence-2/src/test/resources/baeldung.jpeg new file mode 100644 index 0000000000..2654748a27 Binary files /dev/null and b/persistence-modules/spring-boot-persistence-2/src/test/resources/baeldung.jpeg differ diff --git a/persistence-modules/spring-boot-persistence-h2/README.md b/persistence-modules/spring-boot-persistence-h2/README.md index d11ec1f409..1d47907a98 100644 --- a/persistence-modules/spring-boot-persistence-h2/README.md +++ b/persistence-modules/spring-boot-persistence-h2/README.md @@ -1,5 +1,7 @@ ### 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) - [Quick Guide to Hibernate enable_lazy_load_no_trans Property](https://www.baeldung.com/hibernate-lazy-loading-workaround) +- [Where Does H2’s Embedded Database Store The Data?](https://www.baeldung.com/h2-embedded-db-data-storage) diff --git a/persistence-modules/spring-boot-persistence-h2/pom.xml b/persistence-modules/spring-boot-persistence-h2/pom.xml index 23520a3fda..c06c35cfee 100644 --- a/persistence-modules/spring-boot-persistence-h2/pom.xml +++ b/persistence-modules/spring-boot-persistence-h2/pom.xml @@ -47,10 +47,6 @@ com.baeldung.h2db.demo.server.SpringBootApp 1.0.4 - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-persistent-on.properties b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-persistent-on.properties new file mode 100644 index 0000000000..be939ffa69 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-persistent-on.properties @@ -0,0 +1,10 @@ +#spring.datasource.url=jdbc:h2:file:C:/data/demodb +#spring.datasource.url=jdbc:h2:file:~/demodb +spring.datasource.url=jdbc:h2:file:./src/main/resources/db/demodb +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password= +spring.h2.console.enabled=true +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +spring.h2.console.path=/h2-console diff --git a/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/persistent/FilesLocationUnitTest.java b/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/persistent/FilesLocationUnitTest.java new file mode 100644 index 0000000000..63f195e88d --- /dev/null +++ b/persistence-modules/spring-boot-persistence-h2/src/test/java/com/baeldung/persistent/FilesLocationUnitTest.java @@ -0,0 +1,52 @@ +package com.baeldung.persistent; + +import static org.junit.Assert.assertTrue; + +import java.io.File; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import com.baeldung.h2db.auto.configuration.AutoConfigurationDemo; + +@ActiveProfiles("persistent-on") +@RunWith(SpringRunner.class) +@DirtiesContext(classMode = ClassMode.BEFORE_EACH_TEST_METHOD) +@SpringBootTest(classes = AutoConfigurationDemo.class) +public class FilesLocationUnitTest { + + @BeforeClass + public static void beforeClass() { + + } + + @Test(expected = Test.None.class) + public void whenApplicationStarted_thenEmbeddedDbSubfolderCreated() { + File subdirectory = new File("src/main/resources/db"); + System.out.println(subdirectory.getAbsolutePath()); + assertTrue(subdirectory.exists()); + assertTrue(subdirectory.isDirectory()); + } + + @Test(expected = Test.None.class) + public void whenApplicationStarted_thenEmbeddedDbFilesCreated() { + File dbFile = new File("src/main/resources/db/demodb.mv.db"); + System.out.println(dbFile.getAbsolutePath()); + + assertTrue(dbFile.exists()); + assertTrue(dbFile.isFile()); + } + + @AfterClass + public static void cleanUp() { + File dbFile = new File("src/main/resources/db/demodb.mv.db"); + dbFile.deleteOnExit(); + } +} diff --git a/persistence-modules/spring-boot-persistence-mongodb/README.md b/persistence-modules/spring-boot-persistence-mongodb/README.md index f277ef66ca..97241ad464 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/README.md +++ b/persistence-modules/spring-boot-persistence-mongodb/README.md @@ -3,3 +3,6 @@ - [Auto-Generated Field for MongoDB using Spring Boot](https://www.baeldung.com/spring-boot-mongodb-auto-generated-field) - [Spring Boot Integration Testing with Embedded MongoDB](http://www.baeldung.com/spring-boot-embedded-mongodb) - [Upload and Retrieve Files Using MongoDB and Spring Boot](https://www.baeldung.com/spring-boot-mongodb-upload-file) +- [GridFS in Spring Data MongoDB](http://www.baeldung.com/spring-data-mongodb-gridfs) +- [ZonedDateTime with Spring Data MongoDB](https://www.baeldung.com/spring-data-mongodb-zoneddatetime) + diff --git a/persistence-modules/spring-boot-persistence-mongodb/pom.xml b/persistence-modules/spring-boot-persistence-mongodb/pom.xml index 69ef09356d..5167483aa3 100644 --- a/persistence-modules/spring-boot-persistence-mongodb/pom.xml +++ b/persistence-modules/spring-boot-persistence-mongodb/pom.xml @@ -37,9 +37,5 @@ - - 2.22.2 - 5.6.2 - 4.13 \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/config/MongoConfig.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/config/MongoConfig.java new file mode 100644 index 0000000000..4eb3872e34 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/config/MongoConfig.java @@ -0,0 +1,31 @@ +package com.baeldung.zoneddatetime.config; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + +import com.baeldung.zoneddatetime.converter.ZonedDateTimeReadConverter; +import com.baeldung.zoneddatetime.converter.ZonedDateTimeWriteConverter; + +@EnableMongoRepositories(basePackages = { "com.baeldung" }) +public class MongoConfig extends AbstractMongoClientConfiguration { + + private final List> converters = new ArrayList>(); + + @Override + protected String getDatabaseName() { + return "test"; + } + + @Override + public MongoCustomConversions customConversions() { + converters.add(new ZonedDateTimeReadConverter()); + converters.add(new ZonedDateTimeWriteConverter()); + return new MongoCustomConversions(converters); + } + +} diff --git a/persistence-modules/spring-data-mongodb/src/main/java/converter/ZonedDateTimeReadConverter.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/converter/ZonedDateTimeReadConverter.java similarity index 88% rename from persistence-modules/spring-data-mongodb/src/main/java/converter/ZonedDateTimeReadConverter.java rename to persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/converter/ZonedDateTimeReadConverter.java index a2d847957b..f4a4c2d040 100644 --- a/persistence-modules/spring-data-mongodb/src/main/java/converter/ZonedDateTimeReadConverter.java +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/converter/ZonedDateTimeReadConverter.java @@ -1,4 +1,4 @@ -package converter; +package com.baeldung.zoneddatetime.converter; import org.springframework.core.convert.converter.Converter; diff --git a/persistence-modules/spring-data-mongodb/src/main/java/converter/ZonedDateTimeWriteConverter.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/converter/ZonedDateTimeWriteConverter.java similarity index 87% rename from persistence-modules/spring-data-mongodb/src/main/java/converter/ZonedDateTimeWriteConverter.java rename to persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/converter/ZonedDateTimeWriteConverter.java index e13ac2d130..2244a1460a 100644 --- a/persistence-modules/spring-data-mongodb/src/main/java/converter/ZonedDateTimeWriteConverter.java +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/converter/ZonedDateTimeWriteConverter.java @@ -1,4 +1,4 @@ -package converter; +package com.baeldung.zoneddatetime.converter; import org.springframework.core.convert.converter.Converter; diff --git a/persistence-modules/spring-data-mongodb/src/main/java/com/baeldung/model/Action.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/model/Action.java similarity index 96% rename from persistence-modules/spring-data-mongodb/src/main/java/com/baeldung/model/Action.java rename to persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/model/Action.java index aa480dbdf7..06202fe465 100644 --- a/persistence-modules/spring-data-mongodb/src/main/java/com/baeldung/model/Action.java +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/model/Action.java @@ -1,4 +1,4 @@ -package com.baeldung.model; +package com.baeldung.zoneddatetime.model; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; diff --git a/persistence-modules/spring-data-mongodb/src/main/java/com/baeldung/repository/ActionRepository.java b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/repository/ActionRepository.java similarity index 55% rename from persistence-modules/spring-data-mongodb/src/main/java/com/baeldung/repository/ActionRepository.java rename to persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/repository/ActionRepository.java index bdca490fe6..e214c4b3c4 100644 --- a/persistence-modules/spring-data-mongodb/src/main/java/com/baeldung/repository/ActionRepository.java +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/java/com/baeldung/zoneddatetime/repository/ActionRepository.java @@ -1,6 +1,7 @@ -package com.baeldung.repository; +package com.baeldung.zoneddatetime.repository; -import com.baeldung.model.Action; import org.springframework.data.mongodb.repository.MongoRepository; +import com.baeldung.zoneddatetime.model.Action; + public interface ActionRepository extends MongoRepository { } \ No newline at end of file diff --git a/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/mongoConfig.xml b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/mongoConfig.xml new file mode 100644 index 0000000000..7a10ef6a69 --- /dev/null +++ b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/mongoConfig.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-data-mongodb/src/main/resources/test.png b/persistence-modules/spring-boot-persistence-mongodb/src/main/resources/test.png similarity index 100% rename from persistence-modules/spring-data-mongodb/src/main/resources/test.png rename to persistence-modules/spring-boot-persistence-mongodb/src/main/resources/test.png diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java b/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java similarity index 100% rename from persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java rename to persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/gridfs/GridFSLiveTest.java diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java b/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/zoneddatetime/ActionRepositoryLiveTest.java similarity index 87% rename from persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java rename to persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/zoneddatetime/ActionRepositoryLiveTest.java index 79648f1a20..3a241418ca 100644 --- a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/repository/ActionRepositoryLiveTest.java +++ b/persistence-modules/spring-boot-persistence-mongodb/src/test/java/com/baeldung/zoneddatetime/ActionRepositoryLiveTest.java @@ -1,7 +1,5 @@ -package com.baeldung.repository; +package com.baeldung.zoneddatetime; -import com.baeldung.config.MongoConfig; -import com.baeldung.model.Action; import org.junit.After; import org.junit.Assert; import org.junit.Before; @@ -12,6 +10,10 @@ import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import com.baeldung.zoneddatetime.config.MongoConfig; +import com.baeldung.zoneddatetime.model.Action; +import com.baeldung.zoneddatetime.repository.ActionRepository; + import java.time.ZoneOffset; import java.time.ZonedDateTime; diff --git a/persistence-modules/spring-boot-persistence/pom.xml b/persistence-modules/spring-boot-persistence/pom.xml index b034f6dad9..9e44a7b9c1 100644 --- a/persistence-modules/spring-boot-persistence/pom.xml +++ b/persistence-modules/spring-boot-persistence/pom.xml @@ -76,11 +76,6 @@ 2.23.0 2.0.1.Final - - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/spring-data-cassandra-reactive/pom.xml b/persistence-modules/spring-data-cassandra-reactive/pom.xml index 42329e03f0..f2f71bceac 100644 --- a/persistence-modules/spring-data-cassandra-reactive/pom.xml +++ b/persistence-modules/spring-data-cassandra-reactive/pom.xml @@ -54,10 +54,6 @@ 2.2.6.RELEASE 3.11.2.0 - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/spring-data-cassandra/pom.xml b/persistence-modules/spring-data-cassandra/pom.xml index a56d067a05..9de1cbf20e 100644 --- a/persistence-modules/spring-data-cassandra/pom.xml +++ b/persistence-modules/spring-data-cassandra/pom.xml @@ -105,10 +105,6 @@ 2.1.9.2 2.0-0 - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/spring-data-cosmosdb/pom.xml b/persistence-modules/spring-data-cosmosdb/pom.xml index 0f9e8ac72f..19a66648b2 100644 --- a/persistence-modules/spring-data-cosmosdb/pom.xml +++ b/persistence-modules/spring-data-cosmosdb/pom.xml @@ -17,10 +17,6 @@ 1.8 2.3.0 - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/spring-data-dynamodb/pom.xml b/persistence-modules/spring-data-dynamodb/pom.xml index 0f4b578088..377e35b635 100644 --- a/persistence-modules/spring-data-dynamodb/pom.xml +++ b/persistence-modules/spring-data-dynamodb/pom.xml @@ -182,11 +182,6 @@ 1.11.86 https://s3-us-west-2.amazonaws.com/dynamodb-local/release 3.1.1 - - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/spring-data-elasticsearch/pom.xml b/persistence-modules/spring-data-elasticsearch/pom.xml index c94962d39d..6a983145ee 100644 --- a/persistence-modules/spring-data-elasticsearch/pom.xml +++ b/persistence-modules/spring-data-elasticsearch/pom.xml @@ -69,10 +69,5 @@ 1.2.47 0.7 1.15.0 - - - 2.22.2 - 5.6.2 - 4.13 \ No newline at end of file diff --git a/persistence-modules/spring-data-jdbc/pom.xml b/persistence-modules/spring-data-jdbc/pom.xml index eca8037e20..15f8d7fb95 100644 --- a/persistence-modules/spring-data-jdbc/pom.xml +++ b/persistence-modules/spring-data-jdbc/pom.xml @@ -28,9 +28,5 @@ - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/spring-data-jpa-annotations/README.md b/persistence-modules/spring-data-jpa-annotations/README.md index 5f1c8dbc27..1ee579cf6c 100644 --- a/persistence-modules/spring-data-jpa-annotations/README.md +++ b/persistence-modules/spring-data-jpa-annotations/README.md @@ -4,7 +4,6 @@ This module contains articles about annotations used in Spring Data JPA ### Relevant articles -- [Spring Data Annotations](https://www.baeldung.com/spring-data-annotations) - [DDD Aggregates and @DomainEvents](https://www.baeldung.com/spring-data-ddd) - [JPA @Embedded And @Embeddable](https://www.baeldung.com/jpa-embedded-embeddable) - [Spring Data JPA @Modifying Annotation](https://www.baeldung.com/spring-data-jpa-modifying-annotation) diff --git a/persistence-modules/spring-data-jpa-annotations/pom.xml b/persistence-modules/spring-data-jpa-annotations/pom.xml index ea2fe34f3c..ff30790eaf 100644 --- a/persistence-modules/spring-data-jpa-annotations/pom.xml +++ b/persistence-modules/spring-data-jpa-annotations/pom.xml @@ -73,10 +73,6 @@ 42.2.5 21.0 - - 2.22.2 - 5.6.2 - 4.13 \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-crud/pom.xml b/persistence-modules/spring-data-jpa-crud/pom.xml index 44944298e0..16ee74aa62 100644 --- a/persistence-modules/spring-data-jpa-crud/pom.xml +++ b/persistence-modules/spring-data-jpa-crud/pom.xml @@ -16,10 +16,6 @@ - - org.springframework.boot - spring-boot-starter-web - org.springframework.boot spring-boot-starter-data-jpa @@ -66,11 +62,6 @@ 1.4.1 21.0 1.12.2 - - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/spring-data-jpa-enterprise/pom.xml b/persistence-modules/spring-data-jpa-enterprise/pom.xml index 9ecab5feaa..7ff2f00fdf 100644 --- a/persistence-modules/spring-data-jpa-enterprise/pom.xml +++ b/persistence-modules/spring-data-jpa-enterprise/pom.xml @@ -99,10 +99,6 @@ 21.0 1.12.2 - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/spring-data-jpa-filtering/pom.xml b/persistence-modules/spring-data-jpa-filtering/pom.xml index 7448a5a818..25ef68fe4c 100644 --- a/persistence-modules/spring-data-jpa-filtering/pom.xml +++ b/persistence-modules/spring-data-jpa-filtering/pom.xml @@ -73,10 +73,6 @@ 42.2.5 21.0 - - 2.22.2 - 5.6.2 - 4.13 \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-query-2/README.md b/persistence-modules/spring-data-jpa-query-2/README.md index fdb4ce3db7..36875c899c 100644 --- a/persistence-modules/spring-data-jpa-query-2/README.md +++ b/persistence-modules/spring-data-jpa-query-2/README.md @@ -3,9 +3,15 @@ This module contains articles about querying data using Spring Data JPA ### Relevant Articles: -- [Spring Data JPA @Query Annotation](https://www.baeldung.com/spring-data-jpa-query) +- [Spring Data JPA @Query](https://www.baeldung.com/spring-data-jpa-query) - [Use Criteria Queries in a Spring Data Application](https://www.baeldung.com/spring-data-criteria-queries) - [Query Entities by Dates and Times with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-query-by-date) +- [Hibernate Pagination](https://www.baeldung.com/hibernate-pagination) +- [Sorting with Hibernate](https://www.baeldung.com/hibernate-sort) +- [Stored Procedures with Hibernate](https://www.baeldung.com/stored-procedures-with-hibernate-tutorial) +- [Eager/Lazy Loading In Hibernate](https://www.baeldung.com/hibernate-lazy-eager-loading) +- [Auditing with JPA, Hibernate, and Spring Data JPA](https://www.baeldung.com/database-auditing-jpa) + - More articles: [[<-- prev]](../spring-data-jpa-query) ### Eclipse Config diff --git a/persistence-modules/spring-data-jpa-query-2/pom.xml b/persistence-modules/spring-data-jpa-query-2/pom.xml index 231640284e..282a1ff83a 100644 --- a/persistence-modules/spring-data-jpa-query-2/pom.xml +++ b/persistence-modules/spring-data-jpa-query-2/pom.xml @@ -18,6 +18,10 @@ org.springframework.boot spring-boot-starter-data-jpa + + org.springframework.security + spring-security-core + com.h2database @@ -28,12 +32,62 @@ com.fasterxml.jackson.core jackson-databind + + + org.hibernate + hibernate-envers + + + javax.transaction + jta + ${jta.version} + + + mysql + mysql-connector-java + + + com.google.guava + guava + ${guava.version} + + + org.apache.tomcat + tomcat-dbcp + ${tomcat-dbcp.version} + + + org.hibernate + hibernate-core + ${hibernate.version} + + + org.hibernate + hibernate-envers + ${hibernate.version} + + + org.springframework + spring-test + test + + + org.springframework.security + spring-security-test + test + + + org.hsqldb + hsqldb + test + - - 2.22.2 - 5.6.2 - 4.13 + 9.0.0.M26 + 1.1 + 21.0 + + 5.2.10.Final \ No newline at end of file diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceConfig.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/config/PersistenceConfig.java similarity index 95% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceConfig.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/config/PersistenceConfig.java index 4927c9957c..a0d70ed006 100644 --- a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceConfig.java +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/config/PersistenceConfig.java @@ -1,4 +1,4 @@ -package com.baeldung.spring; +package com.baeldung.config; import java.util.Properties; @@ -15,8 +15,8 @@ import org.springframework.dao.annotation.PersistenceExceptionTranslationPostPro import org.springframework.data.domain.AuditorAware; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.orm.hibernate4.HibernateTransactionManager; -import org.springframework.orm.hibernate4.LocalSessionFactoryBean; +import org.springframework.orm.hibernate5.HibernateTransactionManager; +import org.springframework.orm.hibernate5.LocalSessionFactoryBean; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @@ -47,7 +47,7 @@ import com.google.common.base.Preconditions; @Configuration @EnableTransactionManagement -@EnableJpaRepositories(basePackages = { "com.baeldung.persistence" }, transactionManagerRef = "jpaTransactionManager") +@EnableJpaRepositories(basePackages = { "com.baeldung.persistence" }, transactionManagerRef = "jpaTransactionManager", entityManagerFactoryRef = "jpaEntityManager") @EnableJpaAuditing(auditorAwareRef = "auditorProvider") @PropertySource({ "classpath:persistence-h2.properties" }) @ComponentScan({ "com.baeldung.persistence" }) @@ -75,7 +75,7 @@ public class PersistenceConfig { return sessionFactory; } - @Bean + @Bean("jpaEntityManager") public LocalContainerEntityManagerFactoryBean entityManagerFactory() { final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource(restDataSource()); diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/config/PersistenceXmlConfig.java similarity index 94% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/config/PersistenceXmlConfig.java index 9cbeb8e1f8..388494b21a 100644 --- a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/spring/PersistenceXmlConfig.java +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/config/PersistenceXmlConfig.java @@ -1,4 +1,4 @@ -package com.baeldung.spring; +package com.baeldung.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/audit/AuditorAwareImpl.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/audit/AuditorAwareImpl.java similarity index 80% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/audit/AuditorAwareImpl.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/audit/AuditorAwareImpl.java index 7aef08b2ce..5dd12e6841 100644 --- a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/audit/AuditorAwareImpl.java +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/audit/AuditorAwareImpl.java @@ -9,11 +9,10 @@ import org.springframework.security.core.context.SecurityContextHolder; public class AuditorAwareImpl implements AuditorAware { @Override - public String getCurrentAuditor() { + public Optional getCurrentAuditor() { return Optional.ofNullable(SecurityContextHolder.getContext()) .map(e -> e.getAuthentication()) - .map(Authentication::getName) - .orElse(null); + .map(Authentication::getName); } } diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/OrderDetail.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/UserEager.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/model/UserLazy.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/util/HibernateUtil.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/hibernate/fetching/view/FetchingAppView.java diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookRepository.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookRepository.java deleted file mode 100644 index 48620f4ff1..0000000000 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.baeldung.persistence.dao; - -import com.baeldung.persistence.model.Book; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.JpaSpecificationExecutor; - -public interface BookRepository extends JpaRepository, BookRepositoryCustom, JpaSpecificationExecutor { - -} diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookRepositoryCustom.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookRepositoryCustom.java deleted file mode 100644 index eda34542df..0000000000 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookRepositoryCustom.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.persistence.dao; - -import com.baeldung.persistence.model.Book; - -import java.util.List; - -public interface BookRepositoryCustom { - - List findBooksByAuthorNameAndTitle(String authorName, String title); - -} diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookRepositoryImpl.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookRepositoryImpl.java deleted file mode 100644 index 7f5bedd018..0000000000 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookRepositoryImpl.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.baeldung.persistence.dao; - -import com.baeldung.persistence.model.Book; -import org.springframework.stereotype.Repository; - -import javax.persistence.EntityManager; -import javax.persistence.TypedQuery; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; -import javax.persistence.criteria.Predicate; -import javax.persistence.criteria.Root; -import java.util.ArrayList; -import java.util.List; - -@Repository -public class BookRepositoryImpl implements BookRepositoryCustom { - - private EntityManager em; - - public BookRepositoryImpl(EntityManager em) { - this.em = em; - } - - @Override - public List findBooksByAuthorNameAndTitle(String authorName, String title) { - CriteriaBuilder cb = em.getCriteriaBuilder(); - CriteriaQuery cq = cb.createQuery(Book.class); - - Root book = cq.from(Book.class); - List predicates = new ArrayList<>(); - - if (authorName != null) { - predicates.add(cb.equal(book.get("author"), authorName)); - } - if (title != null) { - predicates.add(cb.like(book.get("title"), "%" + title + "%")); - } - cq.where(predicates.toArray(new Predicate[0])); - - TypedQuery query = em.createQuery(cq); - return query.getResultList(); - } - -} diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookService.java deleted file mode 100644 index 4165cd8eb9..0000000000 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookService.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.baeldung.persistence.dao; - -import com.baeldung.persistence.model.Book; -import org.springframework.stereotype.Service; - -import java.util.List; - -import static com.baeldung.persistence.dao.BookSpecifications.hasAuthor; -import static com.baeldung.persistence.dao.BookSpecifications.titleContains; -import static org.springframework.data.jpa.domain.Specification.where; - -@Service -public class BookService { - - private BookRepository bookRepository; - - public BookService(BookRepository bookRepository) { - this.bookRepository = bookRepository; - } - - public List query(String author, String title) { - return bookRepository.findAll(where(hasAuthor(author)).and(titleContains(title))); - } - -} diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookSpecifications.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookSpecifications.java deleted file mode 100644 index 16646a5b4b..0000000000 --- a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/BookSpecifications.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.baeldung.persistence.dao; - -import com.baeldung.persistence.model.Book; -import org.springframework.data.jpa.domain.Specification; - -public class BookSpecifications { - - public static Specification hasAuthor(String author) { - return (book, cq, cb) -> cb.equal(book.get("author"), author); - } - - public static Specification titleContains(String title) { - return (book, cq, cb) -> cb.like(book.get("title"), "%" + title + "%"); - } - -} diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/IBarAuditableDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/IBarCrudRepository.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/IBarDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IBarDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/IBarDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IChildDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/IChildDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IChildDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/IChildDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/IFooAuditableDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IFooDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/IFooDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IFooDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/IFooDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IParentDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/IParentDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/IParentDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/IParentDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/AbstractDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateAuditableDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/AbstractHibernateDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java similarity index 96% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java index 69f8e58c25..79bdd86658 100644 --- a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/AbstractJpaDao.java @@ -12,7 +12,7 @@ import javax.persistence.criteria.Root; public class AbstractJpaDao extends AbstractDao implements IOperations { - @PersistenceContext + @PersistenceContext(unitName = "jpaEntityManager") private EntityManager em; // API diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/GenericHibernateDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/IAuditOperations.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/IGenericDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IOperations.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/IOperations.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/common/IOperations.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/common/IOperations.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/impl/BarAuditableDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/impl/BarDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/impl/BarJpaDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/impl/ChildDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/impl/FooAuditableDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/impl/FooDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/dao/impl/ParentDao.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Bar.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Bar.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Bar.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Bar.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Child.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Child.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Child.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Child.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Foo.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Foo.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Foo.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Foo.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Parent.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Parent.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/model/Parent.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Parent.java diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Person.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Person.java new file mode 100644 index 0000000000..6a95a7acf5 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/model/Person.java @@ -0,0 +1,31 @@ +package com.baeldung.persistence.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; + +@Entity +public class Person { + + @Id + @GeneratedValue + private Long id; + + private String 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; + } +} diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/IBarAuditableService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IBarService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/IBarService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IBarService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/IBarService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IChildService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/IChildService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IChildService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/IChildService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/IFooAuditableService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IFooService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/IFooService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IFooService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/IFooService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IParentService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/IParentService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/IParentService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/IParentService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/common/AbstractJpaService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/common/AbstractService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/common/AbstractService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java similarity index 86% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java index cef483e6bf..73fe27e9ec 100644 --- a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/common/AbstractSpringDataJpaService.java @@ -2,6 +2,7 @@ package com.baeldung.persistence.service.common; import java.io.Serializable; import java.util.List; +import java.util.Optional; import com.baeldung.persistence.dao.common.IOperations; import org.springframework.data.repository.CrudRepository; @@ -14,7 +15,8 @@ public abstract class AbstractSpringDataJpaService imple @Override public T findOne(final long id) { - return getDao().findOne(Long.valueOf(id)); + Optional opt = getDao().findById(Long.valueOf(id)); + return opt.get(); } @Override @@ -39,7 +41,7 @@ public abstract class AbstractSpringDataJpaService imple @Override public void deleteById(final long entityId) { - getDao().delete(Long.valueOf(entityId)); + getDao().deleteById(Long.valueOf(entityId)); } protected abstract CrudRepository getDao(); diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/BarAuditableService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/BarJpaService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/BarService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/BarService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/BarSpringDataJpaService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/ChildService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/ChildService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/ChildService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/ChildService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/FooAuditableService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/FooService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/FooService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/FooService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/FooService.java diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/ParentService.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/ParentService.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/java/com/baeldung/persistence/service/impl/ParentService.java rename to persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/persistence/service/impl/ParentService.java diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/QueryApplication.java b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/QueryApplication.java new file mode 100644 index 0000000000..48c29eda23 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/main/java/com/baeldung/spring/data/jpa/query/QueryApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.data.jpa.query; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class QueryApplication { + + public static void main(String[] args) { + SpringApplication.run(QueryApplication.class, args); + } + +} diff --git a/persistence-modules/spring-hibernate4/src/main/resources/fetching.cfg.xml b/persistence-modules/spring-data-jpa-query-2/src/main/resources/fetching.cfg.xml similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/resources/fetching.cfg.xml rename to persistence-modules/spring-data-jpa-query-2/src/main/resources/fetching.cfg.xml diff --git a/persistence-modules/spring-hibernate4/src/main/resources/fetchingLazy.cfg.xml b/persistence-modules/spring-data-jpa-query-2/src/main/resources/fetchingLazy.cfg.xml similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/resources/fetchingLazy.cfg.xml rename to persistence-modules/spring-data-jpa-query-2/src/main/resources/fetchingLazy.cfg.xml diff --git a/persistence-modules/spring-hibernate4/src/main/resources/fetching_create_queries.sql b/persistence-modules/spring-data-jpa-query-2/src/main/resources/fetching_create_queries.sql similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/resources/fetching_create_queries.sql rename to persistence-modules/spring-data-jpa-query-2/src/main/resources/fetching_create_queries.sql diff --git a/persistence-modules/spring-hibernate4/src/main/resources/hibernate4Config.xml b/persistence-modules/spring-data-jpa-query-2/src/main/resources/hibernate5Config.xml similarity index 91% rename from persistence-modules/spring-hibernate4/src/main/resources/hibernate4Config.xml rename to persistence-modules/spring-data-jpa-query-2/src/main/resources/hibernate5Config.xml index ca507802cd..bbb61cb3e0 100644 --- a/persistence-modules/spring-hibernate4/src/main/resources/hibernate4Config.xml +++ b/persistence-modules/spring-data-jpa-query-2/src/main/resources/hibernate5Config.xml @@ -7,7 +7,7 @@ - + @@ -21,11 +21,11 @@ - + - + diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/resources/hibernate5Configuration.xml b/persistence-modules/spring-data-jpa-query-2/src/main/resources/hibernate5Configuration.xml new file mode 100644 index 0000000000..1870cfb917 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/main/resources/hibernate5Configuration.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + ${hibernate.hbm2ddl.auto} + ${hibernate.dialect} + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/persistence-modules/spring-hibernate4/src/main/resources/immutable.cfg.xml b/persistence-modules/spring-data-jpa-query-2/src/main/resources/immutable.cfg.xml similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/resources/immutable.cfg.xml rename to persistence-modules/spring-data-jpa-query-2/src/main/resources/immutable.cfg.xml diff --git a/persistence-modules/spring-hibernate4/src/main/resources/insert_statements.sql b/persistence-modules/spring-data-jpa-query-2/src/main/resources/insert_statements.sql similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/resources/insert_statements.sql rename to persistence-modules/spring-data-jpa-query-2/src/main/resources/insert_statements.sql diff --git a/persistence-modules/spring-data-jpa-query-2/src/main/resources/insert_users.sql b/persistence-modules/spring-data-jpa-query-2/src/main/resources/insert_users.sql new file mode 100644 index 0000000000..330b2e36b0 --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/main/resources/insert_users.sql @@ -0,0 +1,8 @@ +insert into Users(id, name, creation_date, last_login_date, active, age, email, status) +values(1, 'John', TO_DATE('01/01/2018', 'DD/MM/YYYY'), TO_DATE('01/01/2020', 'DD/MM/YYYY'), 1, 23, 'john@email.com', 1); + +insert into Users(id, name, creation_date, last_login_date, active, age, email, status) +values(2, 'Bob', TO_DATE('02/02/2019', 'DD/MM/YYYY'), TO_DATE('02/02/2020', 'DD/MM/YYYY'), 1, 56, 'bob@email.com', 1); + +insert into Users(id, name, creation_date, last_login_date, active, age, email, status) +values(3, 'Cindy', TO_DATE('02/02/2019', 'DD/MM/YYYY'), TO_DATE('02/02/2020', 'DD/MM/YYYY'), 1, 18, 'cindy@email.com', 0); \ No newline at end of file diff --git a/persistence-modules/spring-hibernate4/src/main/resources/logback.xml b/persistence-modules/spring-data-jpa-query-2/src/main/resources/logback.xml similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/resources/logback.xml rename to persistence-modules/spring-data-jpa-query-2/src/main/resources/logback.xml diff --git a/persistence-modules/spring-hibernate4/src/main/resources/persistence-mysql.properties b/persistence-modules/spring-data-jpa-query-2/src/main/resources/persistence-mysql.properties similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/resources/persistence-mysql.properties rename to persistence-modules/spring-data-jpa-query-2/src/main/resources/persistence-mysql.properties diff --git a/persistence-modules/spring-hibernate4/src/main/resources/stored_procedure.sql b/persistence-modules/spring-data-jpa-query-2/src/main/resources/stored_procedure.sql similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/resources/stored_procedure.sql rename to persistence-modules/spring-data-jpa-query-2/src/main/resources/stored_procedure.sql diff --git a/persistence-modules/spring-hibernate4/src/main/resources/webSecurityConfig.xml b/persistence-modules/spring-data-jpa-query-2/src/main/resources/webSecurityConfig.xml similarity index 100% rename from persistence-modules/spring-hibernate4/src/main/resources/webSecurityConfig.xml rename to persistence-modules/spring-data-jpa-query-2/src/main/resources/webSecurityConfig.xml diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingIntegrationTest.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingIntegrationTest.java rename to persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/hibernate/fetching/HibernateFetchingIntegrationTest.java diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java rename to persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/IntegrationTestSuite.java diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java rename to persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/AuditTestSuite.java diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java rename to persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/EnversFooBarAuditIntegrationTest.java diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java similarity index 98% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java rename to persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java index 733074a6a3..f591773cde 100644 --- a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/JPABarAuditIntegrationTest.java @@ -47,6 +47,7 @@ public class JPABarAuditIntegrationTest { private IBarService barService; @Autowired + @Qualifier("jpaEntityManager") private EntityManagerFactory entityManagerFactory; private EntityManager em; diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java similarity index 98% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java rename to persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java index 18227abd28..0603067810 100644 --- a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/audit/SpringDataJPABarAuditIntegrationTest.java @@ -46,6 +46,7 @@ public class SpringDataJPABarAuditIntegrationTest { private IBarService barService; @Autowired + @Qualifier("jpaEntityManager") private EntityManagerFactory entityManagerFactory; private EntityManager em; diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java rename to persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooFixtures.java diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java rename to persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java rename to persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java rename to persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/FooServiceBasicPersistenceIntegrationTest.java diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java rename to persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooStoredProceduresLiveTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/FooStoredProceduresLiveTest.java similarity index 98% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooStoredProceduresLiveTest.java rename to persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/FooStoredProceduresLiveTest.java index d9353f1ad1..8bf33c4110 100644 --- a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/service/FooStoredProceduresLiveTest.java +++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/FooStoredProceduresLiveTest.java @@ -21,8 +21,8 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; +import com.baeldung.config.PersistenceConfig; import com.baeldung.persistence.model.Foo; -import com.baeldung.spring.PersistenceConfig; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java similarity index 100% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java rename to persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/persistence/service/ParentServicePersistenceIntegrationTest.java diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/spring/config/PersistenceTestConfig.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/config/PersistenceTestConfig.java similarity index 96% rename from persistence-modules/spring-hibernate4/src/test/java/com/baeldung/spring/config/PersistenceTestConfig.java rename to persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/config/PersistenceTestConfig.java index 9bf55c902a..34301741fe 100644 --- a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/spring/config/PersistenceTestConfig.java +++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/config/PersistenceTestConfig.java @@ -14,8 +14,8 @@ import org.springframework.core.env.Environment; import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; import org.springframework.data.jpa.repository.config.EnableJpaAuditing; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import org.springframework.orm.hibernate4.HibernateTransactionManager; -import org.springframework.orm.hibernate4.LocalSessionFactoryBean; +import org.springframework.orm.hibernate5.HibernateTransactionManager; +import org.springframework.orm.hibernate5.LocalSessionFactoryBean; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @@ -45,7 +45,7 @@ import com.google.common.base.Preconditions; @Configuration @EnableTransactionManagement -@EnableJpaRepositories(basePackages = { "com.baeldung.persistence" }, transactionManagerRef = "jpaTransactionManager") +@EnableJpaRepositories(basePackages = { "com.baeldung.persistence" }, transactionManagerRef = "jpaTransactionManager", entityManagerFactoryRef = "jpaEntityManager") @EnableJpaAuditing @PropertySource({ "classpath:persistence-h2.properties" }) @ComponentScan({ "com.baeldung.persistence" }) @@ -68,7 +68,7 @@ public class PersistenceTestConfig { return sessionFactory; } - @Bean + @Bean("jpaEntityManager") public LocalContainerEntityManagerFactoryBean entityManagerFactory() { final LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); emf.setDataSource(restDataSource()); diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/UserRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/UserRepositoryIntegrationTest.java new file mode 100644 index 0000000000..0ede418acd --- /dev/null +++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/UserRepositoryIntegrationTest.java @@ -0,0 +1,162 @@ +package com.baeldung.spring.data.jpa.query; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.data.jpa.domain.JpaSort; +import org.springframework.data.mapping.PropertyReferenceException; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@RunWith(SpringRunner.class) +@DataJpaTest(properties = "spring.datasource.data=classpath:insert_users.sql") +public class UserRepositoryIntegrationTest { + + @Autowired + private UserRepository userRepository; + + @Test + public void whenFindAllActiveUsersThenAllActiveFound() { + Collection allActiveUsers = userRepository.findAllActiveUsers(); + assertThat(allActiveUsers).hasSize(2); + } + + @Test + public void whenFindAllActiveUsersNativeThenAllActiveFound() { + Collection allActiveUsers = userRepository.findAllActiveUsersNative(); + assertThat(allActiveUsers).hasSize(2); + } + + @Test + public void whenFindAllSortedByNameThenAllSorted() { + List allUsersSortedByName = userRepository.findAll(Sort.by(Sort.Direction.ASC, "name")); + assertThat(allUsersSortedByName) + .extracting("name") + .containsSequence("Bob", "Cindy", "John"); + } + + @Test + public void whenFindAllSortedByNameLengthThenException() { + assertThatThrownBy(() -> userRepository.findAll(Sort.by("LENGTH(name)"))) + .isInstanceOf(PropertyReferenceException.class); + } + + @Test + public void whenFindAllUsersSortedByNameThenAllSorted() { + List allUsersSortedByName = userRepository.findAllUsers(Sort.by(Sort.Direction.ASC, "name")); + assertThat(allUsersSortedByName) + .extracting("name") + .containsSequence("Bob", "Cindy", "John"); + } + + @Test + public void whenFindAllUsersSortedByNameLengthThenAllSorted() { + List allUsersSortedByName = userRepository.findAllUsers(JpaSort.unsafe("LENGTH(name)")); + assertThat(allUsersSortedByName) + .extracting("name") + .containsSequence("Bob", "John", "Cindy"); + } + + @Test + public void whenFindAllUsersWithPaginationThenPaginated() { + Page page = userRepository.findAllUsersWithPagination(PageRequest.of(0, 1)); + assertThat(page.stream().map(User::getId)) + .hasSize(1) + .containsOnly(1); + } + + @Test + public void whenFindAllUsersWithPaginationNativeThenPaginated() { + Page page = userRepository.findAllUsersWithPaginationNative(PageRequest.of(1, 1)); + assertThat(page.stream().map(User::getId)) + .hasSize(1) + .containsOnly(2); + } + + @Test + public void whenFindUserByStatusThenFound() { + User user = userRepository.findUserByStatus(0); + assertThat(user.getStatus()).isZero(); + } + + @Test + public void whenFindUserByStatusAndNameThenFound() { + User user = userRepository.findUserByStatusAndName(1, "John"); + assertThat(user.getStatus()).isOne(); + assertThat(user.getName()).isEqualTo("John"); + } + + @Test + public void whenFindUserByStatusNativeThenFound() { + User user = userRepository.findUserByStatusNative(0); + assertThat(user.getStatus()).isZero(); + } + + @Test + public void whenFindUserByStatusAndNameNamedParamsThenFound() { + User user = userRepository.findUserByStatusAndNameNamedParams(1, "John"); + assertThat(user.getStatus()).isOne(); + assertThat(user.getName()).isEqualTo("John"); + } + + @Test + public void whenFindUserByUserStatusAndUserNameThenFound() { + User user = userRepository.findUserByUserStatusAndUserName(1, "John"); + assertThat(user.getStatus()).isOne(); + assertThat(user.getName()).isEqualTo("John"); + } + + @Test + public void whenFindUserByStatusAndNameNamedParamsNativeThenFound() { + User user = userRepository.findUserByStatusAndNameNamedParamsNative(1, "Bob"); + assertThat(user.getStatus()).isOne(); + assertThat(user.getName()).isEqualTo("Bob"); + } + + @Test + public void whenFindUserByNameListThenAllFound() { + List users = userRepository.findUserByNameList(Arrays.asList("Bob", "Cindy")); + assertThat(users) + .extracting("name") + .containsOnly("Bob", "Cindy"); + } + + @Test + public void whenUpdateUserSetStatusForNameThenUpdated() { + int updated = userRepository.updateUserSetStatusForName(0, "John"); + assertThat(updated).isOne(); + + User john = userRepository.findUserByStatusAndName(0, "John"); + assertThat(john).isNotNull(); + } + + @Test + public void whenUpdateUserSetStatusForNameNativeThenUpdated() { + int updated = userRepository.updateUserSetStatusForNameNative(0, "John"); + assertThat(updated).isOne(); + + User john = userRepository.findUserByStatusAndName(0, "John"); + assertThat(john).isNotNull(); + } + + @Test + public void whenInsertUserThenInserted() { + User beforeInsert = userRepository.findUserByStatusAndName(0, "Mandy"); + assertThat(beforeInsert).isNull(); + + userRepository.insertUser("Mandy", 20, "mandy@email.com", 0, true); + + User afterInsert = userRepository.findUserByStatusAndName(0, "Mandy"); + assertThat(afterInsert).isNotNull(); + } +} diff --git a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/datetime/ArticleRepositoryIntegrationTest.java b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/datetime/ArticleRepositoryIntegrationTest.java index 38fd804195..b1158b3dae 100644 --- a/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/datetime/ArticleRepositoryIntegrationTest.java +++ b/persistence-modules/spring-data-jpa-query-2/src/test/java/com/baeldung/spring/data/jpa/query/datetime/ArticleRepositoryIntegrationTest.java @@ -6,6 +6,9 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.test.context.junit4.SpringRunner; +import com.baeldung.spring.data.jpa.query.datetime.Article; +import com.baeldung.spring.data.jpa.query.datetime.ArticleRepository; + import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.List; diff --git a/persistence-modules/spring-hibernate4/src/test/resources/fetching.cfg.xml b/persistence-modules/spring-data-jpa-query-2/src/test/resources/fetching.cfg.xml similarity index 100% rename from persistence-modules/spring-hibernate4/src/test/resources/fetching.cfg.xml rename to persistence-modules/spring-data-jpa-query-2/src/test/resources/fetching.cfg.xml diff --git a/persistence-modules/spring-hibernate4/src/test/resources/fetchingLazy.cfg.xml b/persistence-modules/spring-data-jpa-query-2/src/test/resources/fetchingLazy.cfg.xml similarity index 100% rename from persistence-modules/spring-hibernate4/src/test/resources/fetchingLazy.cfg.xml rename to persistence-modules/spring-data-jpa-query-2/src/test/resources/fetchingLazy.cfg.xml diff --git a/persistence-modules/spring-hibernate4/src/test/resources/persistence-h2.properties b/persistence-modules/spring-data-jpa-query-2/src/test/resources/persistence-h2.properties similarity index 100% rename from persistence-modules/spring-hibernate4/src/test/resources/persistence-h2.properties rename to persistence-modules/spring-data-jpa-query-2/src/test/resources/persistence-h2.properties diff --git a/persistence-modules/spring-data-jpa-query/pom.xml b/persistence-modules/spring-data-jpa-query/pom.xml index fe42d4b595..1576fd729d 100644 --- a/persistence-modules/spring-data-jpa-query/pom.xml +++ b/persistence-modules/spring-data-jpa-query/pom.xml @@ -44,10 +44,6 @@ 1.4.1 - - 2.22.2 - 5.6.2 - 4.13 \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-2/README.md b/persistence-modules/spring-data-jpa-repo-2/README.md index de5188c1ad..0a690fe5a5 100644 --- a/persistence-modules/spring-data-jpa-repo-2/README.md +++ b/persistence-modules/spring-data-jpa-repo-2/README.md @@ -2,4 +2,5 @@ ### Relevant Articles: - [Introduction to Spring Data JPA](https://www.baeldung.com/the-persistence-layer-with-spring-data-jpa) -- More articles: [[<-- prev]](/spring-data-jpa-repo/) \ No newline at end of file +- [Performance Difference Between save() and saveAll() in Spring Data](https://www.baeldung.com/spring-data-save-saveall) +- More articles: [[<-- prev]](/spring-data-jpa-repo/) diff --git a/persistence-modules/spring-data-jpa-repo-2/pom.xml b/persistence-modules/spring-data-jpa-repo-2/pom.xml index 98ecdc6645..3be1068d8c 100644 --- a/persistence-modules/spring-data-jpa-repo-2/pom.xml +++ b/persistence-modules/spring-data-jpa-repo-2/pom.xml @@ -44,9 +44,5 @@ 29.0-jre - - 2.22.2 - 5.6.2 - 4.13 \ No newline at end of file diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/Book.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/Book.java new file mode 100644 index 0000000000..b6abdd2ed5 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/Book.java @@ -0,0 +1,25 @@ +package com.baeldung.spring.data.persistence.saveperformance; + +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 title; + private String author; + + public Book(final String title, final String author) { + this.title = title; + this.author = author; + } + + public Book() { + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookApplication.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookApplication.java new file mode 100644 index 0000000000..56ad918be3 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookApplication.java @@ -0,0 +1,48 @@ +package com.baeldung.spring.data.persistence.saveperformance; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.EventListener; + +import java.util.ArrayList; +import java.util.List; + +@SpringBootApplication +public class BookApplication { + + @Autowired + private BookRepository bookRepository; + + public static void main(String[] args) { + SpringApplication.run(BookApplication.class, args); + } + + @EventListener(ApplicationReadyEvent.class) + public void executePerformanceBenchmark() { + + int bookCount = 10000; + + long start = System.currentTimeMillis(); + for(int i = 0; i < bookCount; i++) { + bookRepository.save(new Book("Book " + i, "Author " + i)); + } + long end = System.currentTimeMillis(); + bookRepository.deleteAll(); + + System.out.println("It took " + (end - start) + "ms to execute save() for " + bookCount + " books"); + + List bookList = new ArrayList<>(); + for (int i = 0; i < bookCount; i++) { + bookList.add(new Book("Book " + i, "Author " + i)); + } + + start = System.currentTimeMillis(); + bookRepository.saveAll(bookList); + end = System.currentTimeMillis(); + + System.out.println("It took " + (end - start) + "ms to execute saveAll() with " + bookCount + " books\n"); + + } +} diff --git a/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookRepository.java b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookRepository.java new file mode 100644 index 0000000000..9db4a18796 --- /dev/null +++ b/persistence-modules/spring-data-jpa-repo-2/src/main/java/com/baeldung/spring/data/persistence/saveperformance/BookRepository.java @@ -0,0 +1,7 @@ +package com.baeldung.spring.data.persistence.saveperformance; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface BookRepository extends JpaRepository { + +} diff --git a/persistence-modules/spring-data-jpa-repo/pom.xml b/persistence-modules/spring-data-jpa-repo/pom.xml index 07514e9771..16a214fd7f 100644 --- a/persistence-modules/spring-data-jpa-repo/pom.xml +++ b/persistence-modules/spring-data-jpa-repo/pom.xml @@ -50,9 +50,6 @@ - - 2.22.2 - 5.6.2 - 4.13 + \ No newline at end of file diff --git a/persistence-modules/spring-data-keyvalue/pom.xml b/persistence-modules/spring-data-keyvalue/pom.xml index 190d6c7445..3aaee2f00c 100644 --- a/persistence-modules/spring-data-keyvalue/pom.xml +++ b/persistence-modules/spring-data-keyvalue/pom.xml @@ -29,9 +29,6 @@ - - 2.22.2 - 5.6.2 - 4.13 + \ No newline at end of file diff --git a/persistence-modules/spring-data-mongodb/README.md b/persistence-modules/spring-data-mongodb/README.md index 381bf83fa8..acc978c68e 100644 --- a/persistence-modules/spring-data-mongodb/README.md +++ b/persistence-modules/spring-data-mongodb/README.md @@ -7,13 +7,10 @@ - [A Guide to Queries in Spring Data MongoDB](http://www.baeldung.com/queries-in-spring-data-mongodb) - [Spring Data MongoDB – Indexes, Annotations and Converters](http://www.baeldung.com/spring-data-mongodb-index-annotations-converter) - [Custom Cascading in Spring Data MongoDB](http://www.baeldung.com/cascading-with-dbref-and-lifecycle-events-in-spring-data-mongodb) -- [GridFS in Spring Data MongoDB](http://www.baeldung.com/spring-data-mongodb-gridfs) - [Introduction to Spring Data MongoDB](http://www.baeldung.com/spring-data-mongodb-tutorial) - [Spring Data MongoDB: Projections and Aggregations](http://www.baeldung.com/spring-data-mongodb-projections-aggregations) - [Spring Data Annotations](http://www.baeldung.com/spring-data-annotations) -- [Spring Data MongoDB Transactions](https://www.baeldung.com/spring-data-mongodb-transactions ) -- [ZonedDateTime with Spring Data MongoDB](https://www.baeldung.com/spring-data-mongodb-zoneddatetime) - +- [Spring Data MongoDB Transactions](https://www.baeldung.com/spring-data-mongodb-transactions) ## Spring Data MongoDB Live Testing diff --git a/persistence-modules/spring-data-mongodb/pom.xml b/persistence-modules/spring-data-mongodb/pom.xml index a3a81fe450..448b635667 100644 --- a/persistence-modules/spring-data-mongodb/pom.xml +++ b/persistence-modules/spring-data-mongodb/pom.xml @@ -108,10 +108,6 @@ 3.2.0.RELEASE 4.0.5 - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/spring-data-mongodb/src/main/java/com/baeldung/config/MongoConfig.java b/persistence-modules/spring-data-mongodb/src/main/java/com/baeldung/config/MongoConfig.java index 8036bbbca2..a7db26eba5 100644 --- a/persistence-modules/spring-data-mongodb/src/main/java/com/baeldung/config/MongoConfig.java +++ b/persistence-modules/spring-data-mongodb/src/main/java/com/baeldung/config/MongoConfig.java @@ -5,16 +5,13 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.converter.Converter; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.MongoTransactionManager; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; -import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; -import org.springframework.data.mongodb.gridfs.GridFsTemplate; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import com.baeldung.converter.UserWriterConverter; @@ -25,18 +22,12 @@ import com.mongodb.MongoClientSettings; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; -import converter.ZonedDateTimeReadConverter; -import converter.ZonedDateTimeWriteConverter; - @Configuration @EnableMongoRepositories(basePackages = "com.baeldung.repository") public class MongoConfig extends AbstractMongoClientConfiguration { private final List> converters = new ArrayList>(); - @Autowired - private MappingMongoConverter mongoConverter; - @Override protected String getDatabaseName() { return "test"; @@ -69,19 +60,16 @@ public class MongoConfig extends AbstractMongoClientConfiguration { @Override public MongoCustomConversions customConversions() { converters.add(new UserWriterConverter()); - converters.add(new ZonedDateTimeReadConverter()); - converters.add(new ZonedDateTimeWriteConverter()); return new MongoCustomConversions(converters); } - @Bean - public GridFsTemplate gridFsTemplate() throws Exception { - return new GridFsTemplate(mongoDbFactory(), mongoConverter); - } - @Bean MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) { return new MongoTransactionManager(dbFactory); } + @Override + protected boolean autoIndexCreation() { + return true; + } } diff --git a/persistence-modules/spring-data-mongodb/src/main/resources/mongoConfig.xml b/persistence-modules/spring-data-mongodb/src/main/resources/mongoConfig.xml index 074a203b1a..5067bec78e 100644 --- a/persistence-modules/spring-data-mongodb/src/main/resources/mongoConfig.xml +++ b/persistence-modules/spring-data-mongodb/src/main/resources/mongoConfig.xml @@ -14,11 +14,6 @@ - - - - - diff --git a/persistence-modules/spring-data-redis/pom.xml b/persistence-modules/spring-data-redis/pom.xml index 34674dc223..d271df31c7 100644 --- a/persistence-modules/spring-data-redis/pom.xml +++ b/persistence-modules/spring-data-redis/pom.xml @@ -98,11 +98,6 @@ 3.2.4 0.10.0 0.6 - - - 2.22.2 - 5.6.2 - 4.13 diff --git a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java index 497e1506bd..7fd13d2777 100644 --- a/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java +++ b/persistence-modules/spring-data-redis/src/main/java/com/baeldung/spring/data/redis/config/RedisConfig.java @@ -5,7 +5,6 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; -import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.listener.ChannelTopic; import org.springframework.data.redis.listener.RedisMessageListenerContainer; diff --git a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/SpringContextTest.java b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/SpringContextTest.java index 4df0cbd0ad..5167e63721 100644 --- a/persistence-modules/spring-data-redis/src/test/java/com/baeldung/SpringContextTest.java +++ b/persistence-modules/spring-data-redis/src/test/java/com/baeldung/SpringContextTest.java @@ -1,16 +1,32 @@ package com.baeldung; +import org.junit.AfterClass; +import org.junit.BeforeClass; 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.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; -import com.baeldung.spring.data.redis.config.RedisConfig; +import com.baeldung.spring.data.redis.SpringRedisApplication; -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = RedisConfig.class) +import redis.embedded.RedisServerBuilder; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = SpringRedisApplication.class) +@DirtiesContext(classMode = ClassMode.BEFORE_CLASS) public class SpringContextTest { + + private static redis.embedded.RedisServer redisServer; + + @BeforeClass + public static void startRedisServer() { + redisServer = new RedisServerBuilder().port(6379).setting("maxmemory 256M").build(); + redisServer.start(); + } + @AfterClass + public static void stopRedisServer() { + redisServer.stop(); + } @Test public void whenSpringContextIsBootstrapped_thenNoExceptions() { } diff --git a/persistence-modules/spring-data-solr/pom.xml b/persistence-modules/spring-data-solr/pom.xml index 94a796c466..38b5bf8238 100644 --- a/persistence-modules/spring-data-solr/pom.xml +++ b/persistence-modules/spring-data-solr/pom.xml @@ -46,10 +46,6 @@ 2.0.5.RELEASE - - 2.22.2 - 5.6.2 - 4.13 \ No newline at end of file diff --git a/persistence-modules/spring-hibernate-5/README.md b/persistence-modules/spring-hibernate-5/README.md index 6d7526a13b..eff59a0362 100644 --- a/persistence-modules/spring-hibernate-5/README.md +++ b/persistence-modules/spring-hibernate-5/README.md @@ -12,4 +12,5 @@ This module contains articles about Hibernate 5 with Spring. - [Hibernate Second-Level Cache](http://www.baeldung.com/hibernate-second-level-cache) - [Deleting Objects with Hibernate](http://www.baeldung.com/delete-with-hibernate) - [Spring, Hibernate and a JNDI Datasource](http://www.baeldung.com/spring-persistence-jpa-jndi-datasource) -- [@Immutable in Hibernate](http://www.baeldung.com/hibernate-immutable) \ No newline at end of file +- [@Immutable in Hibernate](http://www.baeldung.com/hibernate-immutable) +- [Bootstrapping Hibernate 5 with Spring](https://www.baeldung.com/hibernate-5-spring) diff --git a/persistence-modules/spring-hibernate4/README.md b/persistence-modules/spring-hibernate4/README.md deleted file mode 100644 index a5a72a9b7e..0000000000 --- a/persistence-modules/spring-hibernate4/README.md +++ /dev/null @@ -1,24 +0,0 @@ -## Spring with Hibernate 4 - -This module contains articles about Spring with Hibernate 4 - -### Relevant Articles: -- [Guide to Hibernate 4 with Spring](https://www.baeldung.com/hibernate-4-spring) -- [Hibernate Pagination](https://www.baeldung.com/hibernate-pagination) -- [Sorting with Hibernate](https://www.baeldung.com/hibernate-sort) -- [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) -- [Auditing with JPA, Hibernate, and Spring Data JPA](https://www.baeldung.com/database-auditing-jpa) - -### Quick Start - -``` -git clone git://github.com/eugenp/REST.git -cd REST -mvn install -mvn cargo:run -``` - -- **note**: starts on port `8082` - diff --git a/persistence-modules/spring-hibernate4/pom.xml b/persistence-modules/spring-hibernate4/pom.xml deleted file mode 100644 index 3e5a6f913f..0000000000 --- a/persistence-modules/spring-hibernate4/pom.xml +++ /dev/null @@ -1,166 +0,0 @@ - - - 4.0.0 - spring-hibernate4 - 0.1-SNAPSHOT - spring-hibernate4 - - - com.baeldung - parent-spring-4 - 0.0.1-SNAPSHOT - ../../parent-spring-4 - - - - - - - org.springframework - spring-context - ${org.springframework.version} - - - commons-logging - commons-logging - - - - - org.springframework - spring-aspects - ${org.springframework.version} - - - org.springframework.security - spring-security-core - ${org.springframework.security.version} - - - - - - org.springframework - spring-orm - ${org.springframework.version} - - - org.springframework.data - spring-data-jpa - ${org.springframework.data.version} - - - org.hibernate - hibernate-core - ${hibernate.version} - - - org.hibernate - hibernate-envers - ${hibernate-envers.version} - - - javax.transaction - jta - ${jta.version} - - - mysql - mysql-connector-java - ${mysql-connector-java.version} - - - - org.apache.tomcat - tomcat-dbcp - ${tomcat-dbcp.version} - - - - - - org.hibernate - hibernate-validator - ${hibernate-validator.version} - - - javax.el - javax.el-api - ${javax.el-api.version} - - - - - - com.google.guava - guava - ${guava.version} - - - - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - test - - - - org.springframework - spring-test - ${org.springframework.version} - test - - - - org.springframework.security - spring-security-test - ${org.springframework.security.version} - test - - - - org.hsqldb - hsqldb - ${hsqldb.version} - test - - - com.h2database - h2 - ${h2.version} - test - - - - - - - 4.3.4.RELEASE - 4.2.0.RELEASE - 1.10.5.RELEASE - - - 4.3.11.Final - ${hibernate.version} - 5.1.40 - 8.5.8 - 1.1 - 2.3.4 - - - 5.3.3.Final - 2.2.5 - - - 19.0 - - - 2.22.2 - 5.6.2 - 4.13 - - - diff --git a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/criteria/model/Item.java b/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/criteria/model/Item.java deleted file mode 100644 index 957207b7e6..0000000000 --- a/persistence-modules/spring-hibernate4/src/main/java/com/baeldung/hibernate/criteria/model/Item.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.baeldung.hibernate.criteria.model; - -import java.io.Serializable; - -public class Item implements Serializable { - - private static final long serialVersionUID = 1L; - private Integer itemId; - private String itemName; - private String itemDescription; - private Integer itemPrice; - - // constructors - public Item() { - - } - - public Item(final Integer itemId, final String itemName, final String itemDescription) { - super(); - this.itemId = itemId; - this.itemName = itemName; - this.itemDescription = itemDescription; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((itemId == null) ? 0 : itemId.hashCode()); - return result; - } - - @Override - public boolean equals(final Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - final Item other = (Item) obj; - if (itemId == null) { - if (other.itemId != null) - return false; - } else if (!itemId.equals(other.itemId)) - return false; - return true; - } - - public Integer getItemId() { - return itemId; - } - - public void setItemId(final Integer itemId) { - this.itemId = itemId; - } - - public String getItemName() { - return itemName; - } - - public void setItemName(final String itemName) { - this.itemName = itemName; - } - - public String getItemDescription() { - return itemDescription; - } - - public Integer getItemPrice() { - return itemPrice; - } - - public void setItemPrice(final Integer itemPrice) { - this.itemPrice = itemPrice; - } - - public void setItemDescription(final String itemDescription) { - this.itemDescription = itemDescription; - } -} diff --git a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/SpringContextTest.java b/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/SpringContextTest.java deleted file mode 100644 index e19965773e..0000000000 --- a/persistence-modules/spring-hibernate4/src/test/java/com/baeldung/SpringContextTest.java +++ /dev/null @@ -1,18 +0,0 @@ -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.support.AnnotationConfigContextLoader; - -import com.baeldung.spring.PersistenceConfig; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) -public class SpringContextTest { - - @Test - public void whenSpringContextIsBootstrapped_thenNoExceptions() { - } -} diff --git a/persistence-modules/spring-jdbc/README.md b/persistence-modules/spring-jdbc/README.md index 58d7bdec43..1433344b7a 100644 --- a/persistence-modules/spring-jdbc/README.md +++ b/persistence-modules/spring-jdbc/README.md @@ -1,6 +1,6 @@ ## Spring JDBC ### Relevant Articles: -- [Spring JDBC Template](https://www.baeldung.com/spring-jdbc-jdbctemplate) -- [Spring JDBC Template Testing](https://www.baeldung.com/spring-jdbctemplate-testing) -- [Spring JDBC Template In Clause](https://www.baeldung.com/spring-jdbctemplate-in-list) \ No newline at end of file +- [Spring JDBC](https://www.baeldung.com/spring-jdbc-jdbctemplate) +- [Spring JdbcTemplate Unit Testing](https://www.baeldung.com/spring-jdbctemplate-testing) +- [Using a List of Values in a JdbcTemplate IN Clause](https://www.baeldung.com/spring-jdbctemplate-in-list) diff --git a/persistence-modules/spring-jdbc/pom.xml b/persistence-modules/spring-jdbc/pom.xml index 77200cd66e..8a5786e1a5 100644 --- a/persistence-modules/spring-jdbc/pom.xml +++ b/persistence-modules/spring-jdbc/pom.xml @@ -18,7 +18,6 @@ org.springframework.data spring-data-jdbc - ${spring-data-jdbc.version} org.springframework.boot @@ -36,11 +35,5 @@ - 2.0.3.RELEASE - - - 2.22.2 - 5.6.2 - 4.13 \ No newline at end of file diff --git a/spring-jooq/.gitignore b/persistence-modules/spring-jooq/.gitignore similarity index 100% rename from spring-jooq/.gitignore rename to persistence-modules/spring-jooq/.gitignore diff --git a/spring-jooq/README.md b/persistence-modules/spring-jooq/README.md similarity index 100% rename from spring-jooq/README.md rename to persistence-modules/spring-jooq/README.md diff --git a/spring-jooq/pom.xml b/persistence-modules/spring-jooq/pom.xml similarity index 98% rename from spring-jooq/pom.xml rename to persistence-modules/spring-jooq/pom.xml index 95418645fa..6b3d565175 100644 --- a/spring-jooq/pom.xml +++ b/persistence-modules/spring-jooq/pom.xml @@ -9,7 +9,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 @@ -206,7 +206,7 @@ 1.0.0 1.5 1.0.0 - org.jooq.example.spring.Application + 1.4.198 \ No newline at end of file diff --git a/spring-jooq/src/main/resources/application.properties b/persistence-modules/spring-jooq/src/main/resources/application.properties similarity index 100% rename from spring-jooq/src/main/resources/application.properties rename to persistence-modules/spring-jooq/src/main/resources/application.properties diff --git a/spring-jooq/src/main/resources/intro_config.properties b/persistence-modules/spring-jooq/src/main/resources/intro_config.properties similarity index 100% rename from spring-jooq/src/main/resources/intro_config.properties rename to persistence-modules/spring-jooq/src/main/resources/intro_config.properties diff --git a/spring-jooq/src/main/resources/intro_schema.sql b/persistence-modules/spring-jooq/src/main/resources/intro_schema.sql similarity index 100% rename from spring-jooq/src/main/resources/intro_schema.sql rename to persistence-modules/spring-jooq/src/main/resources/intro_schema.sql diff --git a/spring-5-mvc/src/main/resources/logback.xml b/persistence-modules/spring-jooq/src/main/resources/logback.xml similarity index 100% rename from spring-5-mvc/src/main/resources/logback.xml rename to persistence-modules/spring-jooq/src/main/resources/logback.xml diff --git a/spring-jooq/src/test/java/com/baeldung/jooq/introduction/ExceptionTranslator.java b/persistence-modules/spring-jooq/src/test/java/com/baeldung/jooq/introduction/ExceptionTranslator.java similarity index 100% rename from spring-jooq/src/test/java/com/baeldung/jooq/introduction/ExceptionTranslator.java rename to persistence-modules/spring-jooq/src/test/java/com/baeldung/jooq/introduction/ExceptionTranslator.java diff --git a/spring-jooq/src/test/java/com/baeldung/jooq/introduction/PersistenceContextIntegrationTest.java b/persistence-modules/spring-jooq/src/test/java/com/baeldung/jooq/introduction/PersistenceContextIntegrationTest.java similarity index 100% rename from spring-jooq/src/test/java/com/baeldung/jooq/introduction/PersistenceContextIntegrationTest.java rename to persistence-modules/spring-jooq/src/test/java/com/baeldung/jooq/introduction/PersistenceContextIntegrationTest.java diff --git a/spring-jooq/src/test/java/com/baeldung/jooq/introduction/QueryIntegrationTest.java b/persistence-modules/spring-jooq/src/test/java/com/baeldung/jooq/introduction/QueryIntegrationTest.java similarity index 100% rename from spring-jooq/src/test/java/com/baeldung/jooq/introduction/QueryIntegrationTest.java rename to persistence-modules/spring-jooq/src/test/java/com/baeldung/jooq/introduction/QueryIntegrationTest.java diff --git a/spring-jooq/src/test/java/com/baeldung/jooq/springboot/Application.java b/persistence-modules/spring-jooq/src/test/java/com/baeldung/jooq/springboot/Application.java similarity index 100% rename from spring-jooq/src/test/java/com/baeldung/jooq/springboot/Application.java rename to persistence-modules/spring-jooq/src/test/java/com/baeldung/jooq/springboot/Application.java diff --git a/spring-jooq/src/test/java/com/baeldung/jooq/springboot/InitialConfiguration.java b/persistence-modules/spring-jooq/src/test/java/com/baeldung/jooq/springboot/InitialConfiguration.java similarity index 100% rename from spring-jooq/src/test/java/com/baeldung/jooq/springboot/InitialConfiguration.java rename to persistence-modules/spring-jooq/src/test/java/com/baeldung/jooq/springboot/InitialConfiguration.java diff --git a/spring-jooq/src/test/java/com/baeldung/jooq/springboot/SpringBootIntegrationTest.java b/persistence-modules/spring-jooq/src/test/java/com/baeldung/jooq/springboot/SpringBootIntegrationTest.java similarity index 100% rename from spring-jooq/src/test/java/com/baeldung/jooq/springboot/SpringBootIntegrationTest.java rename to persistence-modules/spring-jooq/src/test/java/com/baeldung/jooq/springboot/SpringBootIntegrationTest.java diff --git a/spring-jooq/src/test/resources/application.properties b/persistence-modules/spring-jooq/src/test/resources/application.properties similarity index 100% rename from spring-jooq/src/test/resources/application.properties rename to persistence-modules/spring-jooq/src/test/resources/application.properties diff --git a/persistence-modules/spring-jpa-2/README.md b/persistence-modules/spring-jpa-2/README.md index fe661c2f28..59543cade7 100644 --- a/persistence-modules/spring-jpa-2/README.md +++ b/persistence-modules/spring-jpa-2/README.md @@ -3,8 +3,7 @@ ### Relevant Articles: - [Many-To-Many Relationship in JPA](https://www.baeldung.com/jpa-many-to-many) - [A Guide to JPA with Spring](https://www.baeldung.com/the-persistence-layer-with-spring-and-jpa) -- [Bootstrapping Hibernate 5 with Spring](https://www.baeldung.com/hibernate-5-spring) - [Transactions with Spring and JPA](https://www.baeldung.com/transaction-configuration-with-jpa-and-spring) - [The DAO with Spring and Hibernate](https://www.baeldung.com/persistence-layer-with-spring-and-hibernate) - [Simplify the DAO with Spring and Java Generics](https://www.baeldung.com/simplifying-the-data-access-layer-with-spring-and-java-generics) -- More articles: [[<-- prev]](/spring-jpa) \ No newline at end of file +- More articles: [[<-- prev]](/spring-jpa) diff --git a/persistence-modules/spring-jpa-2/pom.xml b/persistence-modules/spring-jpa-2/pom.xml index 8d8dfe3a7b..7770c0e045 100644 --- a/persistence-modules/spring-jpa-2/pom.xml +++ b/persistence-modules/spring-jpa-2/pom.xml @@ -46,7 +46,7 @@ org.hibernate - hibernate-entitymanager + hibernate-core ${hibernate.version} diff --git a/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/spring/transaction/Course.java b/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/spring/transaction/Course.java new file mode 100644 index 0000000000..5add1e4a99 --- /dev/null +++ b/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/spring/transaction/Course.java @@ -0,0 +1,35 @@ +package com.baeldung.spring.transaction; + +import java.io.Serializable; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "course") +public class Course implements Serializable { + + private static final long serialVersionUID = 1L; + + @Id + @Column(name = "id") + private Long id; + + public Course() { + } + + public Course(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + +} diff --git a/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/spring/transaction/CourseDao.java b/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/spring/transaction/CourseDao.java new file mode 100644 index 0000000000..adf138ba67 --- /dev/null +++ b/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/spring/transaction/CourseDao.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.transaction; + +import org.springframework.stereotype.Repository; + +import com.baeldung.spring.hibernate.AbstractHibernateDao; + +@Repository +public class CourseDao extends AbstractHibernateDao { + public CourseDao() { + super(); + setClazz(Course.class); + } +} diff --git a/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/spring/transaction/CourseService.java b/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/spring/transaction/CourseService.java new file mode 100644 index 0000000000..05e3f32cee --- /dev/null +++ b/persistence-modules/spring-jpa-2/src/main/java/com/baeldung/spring/transaction/CourseService.java @@ -0,0 +1,44 @@ +package com.baeldung.spring.transaction; + +import java.sql.SQLException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.interceptor.TransactionAspectSupport; + +@Service +public class CourseService { + + @Autowired + private CourseDao courseDao; + + @Transactional + public void createCourseDeclarativeWithRuntimeException(Course course) { + courseDao.create(course); + throw new DataIntegrityViolationException("Throwing exception for demoing Rollback!!!"); + } + + @Transactional(rollbackFor = { SQLException.class }) + public void createCourseDeclarativeWithCheckedException(Course course) throws SQLException { + courseDao.create(course); + throw new SQLException("Throwing exception for demoing Rollback!!!"); + } + + public void createCourseDefaultRatingProgramatic(Course course) { + try { + courseDao.create(course); + throw new DataIntegrityViolationException("Throwing exception for demoing Rollback!!!"); + } catch (Exception e) { + TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); + } + } + + @Transactional(noRollbackFor = { SQLException.class }) + public void createCourseDeclarativeWithNoRollBack(Course course) throws SQLException { + courseDao.create(course); + throw new SQLException("Throwing exception for demoing Rollback!!!"); + } + +} diff --git a/persistence-modules/spring-jpa/README.md b/persistence-modules/spring-jpa/README.md index f60609e0de..937890cd13 100644 --- a/persistence-modules/spring-jpa/README.md +++ b/persistence-modules/spring-jpa/README.md @@ -7,6 +7,7 @@ - [Self-Contained Testing Using an In-Memory Database](https://www.baeldung.com/spring-jpa-test-in-memory-database) - [A Guide to Spring AbstractRoutingDatasource](https://www.baeldung.com/spring-abstract-routing-data-source) - [Obtaining Auto-generated Keys in Spring JDBC](https://www.baeldung.com/spring-jdbc-autogenerated-keys) +- [Spring Data Annotations](http://www.baeldung.com/spring-data-annotations) - More articles: [[next -->]](/spring-jpa-2) ### Eclipse Config diff --git a/persistence-modules/spring-jpa/pom.xml b/persistence-modules/spring-jpa/pom.xml index 410ed592b0..e389886d8d 100644 --- a/persistence-modules/spring-jpa/pom.xml +++ b/persistence-modules/spring-jpa/pom.xml @@ -41,7 +41,7 @@ org.hibernate - hibernate-entitymanager + hibernate-core ${hibernate.version} diff --git a/persistence-modules/spring-persistence-simple/README.md b/persistence-modules/spring-persistence-simple/README.md index baa9107f4e..f118d12f6f 100644 --- a/persistence-modules/spring-persistence-simple/README.md +++ b/persistence-modules/spring-persistence-simple/README.md @@ -5,8 +5,9 @@ ### Relevant Articles: - [Transaction Propagation and Isolation in Spring @Transactional](https://www.baeldung.com/spring-transactional-propagation-isolation) -- [JTA Transaction with Spring](https://www.baeldung.com/spring-vs-jta-transactional) -- [Mock JNDI Datasource](https://www.baeldung.com/spring-mock-jndi-datasource) +- [Transactional Annotations: Spring vs. JTA](https://www.baeldung.com/spring-vs-jta-transactional) +- [Test a Mock JNDI Datasource with Spring](https://www.baeldung.com/spring-mock-jndi-datasource) +- [Detecting If a Spring Transaction Is Active](https://www.baeldung.com/spring-transaction-active) ### Eclipse Config After importing the project into Eclipse, you may see the following error: diff --git a/persistence-modules/spring-persistence-simple/pom.xml b/persistence-modules/spring-persistence-simple/pom.xml index a069f70994..13898d01e7 100644 --- a/persistence-modules/spring-persistence-simple/pom.xml +++ b/persistence-modules/spring-persistence-simple/pom.xml @@ -72,6 +72,12 @@ ${org.springframework.version} test + + org.springframework.boot + spring-boot-starter-test + test + ${spring-boot-starter.version} + org.mockito mockito-core diff --git a/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/transactional/TransactionalDetectionUnitTest.java b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/transactional/TransactionalDetectionUnitTest.java new file mode 100644 index 0000000000..db4dbd630a --- /dev/null +++ b/persistence-modules/spring-persistence-simple/src/test/java/com/baeldung/transactional/TransactionalDetectionUnitTest.java @@ -0,0 +1,27 @@ +package com.baeldung.transactional; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionSynchronizationManager; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +@SpringBootApplication +@RunWith(SpringJUnit4ClassRunner.class) +public class TransactionalDetectionUnitTest { + + @Test + @Transactional + public void givenTransactional_whenCheckingForActiveTransaction_thenReceiveTrue() { + assertTrue(TransactionSynchronizationManager.isActualTransactionActive()); + } + + @Test + public void givenNoTransactional_whenCheckingForActiveTransaction_thenReceiveFalse() { + assertFalse(TransactionSynchronizationManager.isActualTransactionActive()); + } +} diff --git a/pom.xml b/pom.xml index 065d6abbdd..ccdc91ffe0 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,5 @@ + @@ -325,7 +326,6 @@ parent-spring-4 parent-spring-5 parent-java - parent-kotlin akka-http akka-streams @@ -386,8 +386,6 @@ core-groovy-strings core-java-modules - core-kotlin-modules - core-scala couchbase custom-pmd @@ -397,6 +395,7 @@ ddd deeplearning4j + discord4j disruptor dozer drools @@ -424,7 +423,7 @@ hazelcast helidon httpclient - httpclient-2 + httpclient-simple hystrix @@ -456,7 +455,6 @@ jaxb jee-7 jee-7-security - jee-kotlin jersey jgit jgroups @@ -465,7 +463,7 @@ jjwt jmeter jmh - jni + java-native jooby jsf json @@ -474,11 +472,6 @@ jsoup jta - - kotlin-libraries - kotlin-libraries-2 - kotlin-quasar - language-interop libraries-2 @@ -505,7 +498,6 @@ lombok-custom lucene - machine-learning mapstruct maven-modules @@ -598,7 +590,6 @@ parent-spring-4 parent-spring-5 parent-java - parent-kotlin saas software-security/sql-injection-samples @@ -610,15 +601,11 @@ spring-5 spring-5-data-reactive - spring-5-mvc spring-5-reactive spring-5-reactive-2 spring-5-reactive-client spring-5-reactive-oauth spring-5-reactive-security - spring-5-security - spring-5-security-cognito - spring-5-security-oauth spring-5-webflux spring-activiti @@ -627,7 +614,8 @@ spring-aop spring-apache-camel - spring-batch + spring-batch + spring-batch-2 spring-bom spring-boot-modules spring-boot-rest @@ -643,13 +631,13 @@ spring-core-2 spring-core-3 spring-core-4 + spring-core-5 spring-cucumber spring-data-rest spring-data-rest-querydsl spring-di spring-di-2 - spring-dispatcher-servlet spring-drools spring-ejb @@ -663,70 +651,35 @@ spring-jersey spring-jinq spring-jms - spring-jooq spring-kafka spring-katharsis - spring-ldap - spring-mobile spring-mockito - - spring-mvc-basics - spring-mvc-basics-2 - spring-mvc-basics-3 - spring-mvc-basics-4 - - spring-mvc-forms-jsp - spring-mvc-forms-thymeleaf - spring-mvc-java - spring-mvc-java-2 - spring-mvc-kotlin - - spring-mvc-velocity - spring-mvc-views - spring-mvc-webflow - spring-mvc-xml - spring-protobuf spring-quartz - spring-reactive-kotlin spring-reactor spring-remoting - spring-rest-angular - spring-rest-compress - spring-rest-http - spring-rest-http-2 - spring-rest-query-language - spring-rest-shell - spring-rest-simple - spring-resttemplate - spring-resttemplate-2 - spring-rest-testing spring-roo spring-scheduling spring-security-modules - spring-session spring-shell spring-sleuth - spring-soap - spring-social-login + spring-soap spring-spel spring-state-machine spring-static-resources spring-swagger-codegen spring-threads - spring-thymeleaf - spring-thymeleaf-2 - spring-thymeleaf-3 spring-vault spring-vertx + spring-web-modules spring-webflux-amqp spring-websockets @@ -793,7 +746,6 @@ parent-spring-4 parent-spring-5 parent-java - parent-kotlin jenkins/plugins jhipster @@ -838,7 +790,6 @@ parent-spring-4 parent-spring-5 parent-java - parent-kotlin akka-http akka-streams @@ -898,8 +849,6 @@ core-groovy-strings core-java-modules - core-kotlin-modules - core-scala couchbase custom-pmd @@ -909,6 +858,7 @@ ddd deeplearning4j + discord4j disruptor dozer drools @@ -936,7 +886,7 @@ hazelcast helidon httpclient - httpclient-2 + httpclient-simple hystrix @@ -968,7 +918,6 @@ jaxb jee-7 jee-7-security - jee-kotlin jersey jgit jgroups @@ -977,7 +926,7 @@ jjwt jmeter jmh - jni + java-native jooby jsf json @@ -985,11 +934,6 @@ jsoup jta - - kotlin-libraries - kotlin-libraries-2 - kotlin-quasar - libraries-2 libraries-3 @@ -1015,7 +959,6 @@ lombok-custom lucene - machine-learning mapstruct maven-modules @@ -1100,7 +1043,6 @@ parent-spring-4 parent-spring-5 parent-java - parent-kotlin saas software-security/sql-injection-samples @@ -1112,15 +1054,11 @@ spring-5 spring-5-data-reactive - spring-5-mvc spring-5-reactive spring-5-reactive-2 spring-5-reactive-client spring-5-reactive-oauth spring-5-reactive-security - spring-5-security - spring-5-security-cognito - spring-5-security-oauth spring-5-webflux spring-activiti @@ -1145,12 +1083,12 @@ spring-core-2 spring-core-3 spring-core-4 + spring-core-5 spring-cucumber spring-data-rest spring-data-rest-querydsl spring-di - spring-dispatcher-servlet spring-drools spring-ejb @@ -1164,69 +1102,34 @@ spring-jersey spring-jinq spring-jms - spring-jooq spring-kafka spring-katharsis - spring-ldap - spring-mobile spring-mockito - spring-mvc-basics - spring-mvc-basics-2 - spring-mvc-basics-3 - spring-mvc-basics-4 - - spring-mvc-forms-jsp - spring-mvc-forms-thymeleaf - spring-mvc-java - spring-mvc-java-2 - spring-mvc-kotlin - - spring-mvc-velocity - spring-mvc-views - spring-mvc-webflow - spring-mvc-xml - spring-mvc-crash - spring-protobuf spring-quartz - spring-reactive-kotlin spring-reactor spring-remoting - spring-rest-angular - spring-rest-compress - spring-rest-http - spring-rest-query-language - spring-rest-shell - spring-rest-simple - spring-resttemplate - spring-resttemplate-2 - spring-rest-testing spring-roo spring-scheduling spring-security-modules - spring-session spring-shell spring-sleuth spring-soap - spring-social-login spring-spel spring-state-machine spring-static-resources spring-swagger-codegen - spring-thymeleaf - spring-thymeleaf-2 - spring-thymeleaf-3 - spring-vault spring-vertx + spring-web-modules spring-webflux-amqp spring-websockets @@ -1286,7 +1189,6 @@ parent-spring-4 parent-spring-5 parent-java - parent-kotlin jenkins/plugins jhipster @@ -1343,7 +1245,6 @@ org.apache.maven.plugins maven-surefire-plugin - ${maven-surefire-plugin.version} 3 true @@ -1368,23 +1269,22 @@ core-java-modules/core-java-9 core-java-modules/core-java-9-improvements - - + core-java-modules/core-java-9-jigsaw + core-java-modules/core-java-9-streams core-java-modules/core-java-10 - - - - + core-java-modules/core-java-11 + + + core-java-modules/core-java-collections-set - - - + core-java-modules/core-java-date-operations-1 + core-java-modules/core-java-datetime-conversion + core-java-modules/core-java-datetime-string core-java-modules/core-java-jpms - - + core-java-modules/core-java-os + core-java-modules/core-java-time-measurements core-java-modules/multimodulemavenproject - @@ -1413,23 +1313,22 @@ core-java-modules/core-java-9 core-java-modules/core-java-9-improvements - - + core-java-modules/core-java-9-jigsaw + core-java-modules/core-java-9-streams core-java-modules/core-java-10 - - - - + core-java-modules/core-java-11 + + + core-java-modules/core-java-collections-set - - - + core-java-modules/core-java-date-operations-1 + core-java-modules/core-java-datetime-conversion + core-java-modules/core-java-datetime-string core-java-modules/core-java-jpms - - + core-java-modules/core-java-os + core-java-modules/core-java-time-measurements core-java-modules/multimodulemavenproject - @@ -1471,24 +1370,22 @@ 1.6.0 1.8 1.2.17 - 1.1 2.1.0.1 1.19 1.19 1.6.0 2.21.0 - 2.5 + 2.8.0 2.6 - 3.5 + 3.11 1.4 3.0.0 3.1.0 1.2 2.3.1 - 1.9.13 1.2 - 2.9.8 - 1.3 + 2.11.1 + 1.4 1.2.0 5.2.0 0.3.1 @@ -1502,4 +1399,4 @@ 1.4.197 - \ No newline at end of file + diff --git a/quarkus/pom.xml b/quarkus/pom.xml index 7fdf1557fb..9c14afca3c 100644 --- a/quarkus/pom.xml +++ b/quarkus/pom.xml @@ -48,7 +48,7 @@ org.apache.commons commons-lang3 - 3.9 + ${commons-lang3.version} org.projectlombok diff --git a/spring-5-data-reactive/README.md b/spring-5-data-reactive/README.md index 42fcba96f2..0931161700 100644 --- a/spring-5-data-reactive/README.md +++ b/spring-5-data-reactive/README.md @@ -6,7 +6,6 @@ This module contains articles about reactive Spring 5 Data The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles -- [Reactive Flow with MongoDB, Kotlin, and Spring WebFlux](https://www.baeldung.com/kotlin-mongodb-spring-webflux) - [Spring Data Reactive Repositories with MongoDB](https://www.baeldung.com/spring-data-mongodb-reactive) - [Spring Data MongoDB Tailable Cursors](https://www.baeldung.com/spring-data-mongodb-tailable-cursors) - [A Quick Look at R2DBC with Spring Data](https://www.baeldung.com/spring-data-r2dbc) diff --git a/spring-5-data-reactive/pom.xml b/spring-5-data-reactive/pom.xml index 396f7f5959..0fb689f16d 100644 --- a/spring-5-data-reactive/pom.xml +++ b/spring-5-data-reactive/pom.xml @@ -31,18 +31,6 @@ org.springframework.boot spring-boot-starter-web - - com.fasterxml.jackson.module - jackson-module-kotlin - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - - - org.jetbrains.kotlin - kotlin-reflect - org.projectlombok lombok @@ -52,12 +40,6 @@ reactor-test test - - org.jetbrains.kotlin - kotlin-test - ${kotlin.version} - test - io.reactivex.rxjava2 rxjava @@ -128,53 +110,6 @@ org.springframework.boot spring-boot-maven-plugin - - kotlin-maven-plugin - ${kotlin-maven-plugin.version} - - - compile - - compile - - - - ${project.basedir}/src/main/kotlin - ${project.basedir}/src/main/java - - - - - test-compile - - test-compile - - - - ${project.basedir}/src/test/kotlin - ${project.basedir}/src/test/java - - - - - org.jetbrains.kotlin - - - -Xjsr305=strict - - - spring - - 1.8 - - - - org.jetbrains.kotlin - kotlin-maven-allopen - ${kotlin.version} - - - org.apache.maven.plugins maven-compiler-plugin @@ -215,8 +150,6 @@ - 1.2.40 - 1.2.40 5.2.2.RELEASE 1.0.0.RELEASE 0.8.1.RELEASE diff --git a/spring-5-data-reactive/src/main/kotlin/com/baeldung/Application.kt b/spring-5-data-reactive/src/main/kotlin/com/baeldung/Application.kt deleted file mode 100644 index 5a59d11de0..0000000000 --- a/spring-5-data-reactive/src/main/kotlin/com/baeldung/Application.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung - -import org.springframework.boot.SpringApplication -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration - -@SpringBootApplication(exclude = arrayOf(MongoReactiveDataAutoConfiguration::class)) -class Application - -fun main(args: Array) { - SpringApplication.run(Application::class.java, *args) -} diff --git a/spring-5-data-reactive/src/main/kotlin/com/baeldung/Event.kt b/spring-5-data-reactive/src/main/kotlin/com/baeldung/Event.kt deleted file mode 100644 index 17fa9699a8..0000000000 --- a/spring-5-data-reactive/src/main/kotlin/com/baeldung/Event.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.baeldung - -import org.springframework.data.mongodb.core.mapping.Document - -@Document -data class Event(val id: String, val name: String) diff --git a/spring-5-data-reactive/src/main/kotlin/com/baeldung/EventRepository.kt b/spring-5-data-reactive/src/main/kotlin/com/baeldung/EventRepository.kt deleted file mode 100644 index e66af71ea6..0000000000 --- a/spring-5-data-reactive/src/main/kotlin/com/baeldung/EventRepository.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.baeldung - -import org.springframework.data.mongodb.core.mapping.Document -import org.springframework.data.mongodb.repository.ReactiveMongoRepository - -interface EventRepository : ReactiveMongoRepository diff --git a/spring-5-data-reactive/src/main/kotlin/com/baeldung/MongoConfig.kt b/spring-5-data-reactive/src/main/kotlin/com/baeldung/MongoConfig.kt deleted file mode 100644 index 64d51a176a..0000000000 --- a/spring-5-data-reactive/src/main/kotlin/com/baeldung/MongoConfig.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.baeldung - -import com.mongodb.reactivestreams.client.MongoClient -import com.mongodb.reactivestreams.client.MongoClients -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration -import org.springframework.data.mongodb.core.ReactiveMongoTemplate -import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories - - -@Configuration -@EnableReactiveMongoRepositories(basePackageClasses = arrayOf(EventRepository::class)) -class MongoConfig : AbstractReactiveMongoConfiguration() { - - override fun reactiveMongoClient(): MongoClient = mongoClient() - - @Bean - fun mongoClient(): MongoClient = MongoClients.create() - - override fun getDatabaseName(): String = "mongoDatabase" - - @Bean - override fun reactiveMongoTemplate(): ReactiveMongoTemplate = ReactiveMongoTemplate(mongoClient(), databaseName) -} diff --git a/spring-5-data-reactive/src/main/kotlin/com/baeldung/SendEmitter.kt b/spring-5-data-reactive/src/main/kotlin/com/baeldung/SendEmitter.kt deleted file mode 100644 index 6fa3118d8f..0000000000 --- a/spring-5-data-reactive/src/main/kotlin/com/baeldung/SendEmitter.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.baeldung - -import org.springframework.http.MediaType -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.RequestParam -import org.springframework.web.bind.annotation.RestController -import java.util.* - - -@RestController -class SendEmitter(val eventRepository: EventRepository) { - - @GetMapping(value = "/save", produces = arrayOf(MediaType.TEXT_EVENT_STREAM_VALUE)) - fun executeExample(@RequestParam("eventName") eventName: String) = - eventRepository.save(Event(UUID.randomUUID().toString(), eventName)).flux() -} diff --git a/spring-5-data-reactive/src/main/resources/static/index.html b/spring-5-data-reactive/src/main/resources/static/index.html deleted file mode 100644 index a0b8f6f884..0000000000 --- a/spring-5-data-reactive/src/main/resources/static/index.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - -
- - -
- - - -
- - - - diff --git a/spring-5-mvc/pom.xml b/spring-5-mvc/pom.xml deleted file mode 100644 index fd9868ad66..0000000000 --- a/spring-5-mvc/pom.xml +++ /dev/null @@ -1,183 +0,0 @@ - - - 4.0.0 - spring-5-mvc - spring-5-mvc - jar - spring 5 MVC sample project about new features - - - 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-validation - - - org.springframework.boot - spring-boot-starter-web - - - - org.apache.commons - commons-lang3 - - - org.slf4j - slf4j-api - - - org.slf4j - jcl-over-slf4j - - - - org.jetbrains.kotlin - kotlin-stdlib-jre8 - ${kotlin.version} - - - org.jetbrains.kotlin - kotlin-reflect - ${kotlin.version} - - - com.fasterxml.jackson.module - jackson-module-kotlin - ${jackson.version} - - - - org.springframework.boot - spring-boot-devtools - runtime - - - com.h2database - h2 - runtime - - - org.springframework - spring-test - - - org.springframework.boot - spring-boot-starter-test - test - - - com.jayway.restassured - rest-assured - ${jayway-rest-assured.version} - test - - - com.github.javafaker - javafaker - ${javafaker.version} - - - org.apache.httpcomponents - httpclient - ${httpclient.version} - - - - - ${project.basedir}/src/test/kotlin - - - org.springframework.boot - spring-boot-maven-plugin - - - kotlin-maven-plugin - org.jetbrains.kotlin - ${kotlin.version} - - - spring - - ${java.version} - - - - compile - compile - - compile - - - - test-compile - test-compile - - test-compile - - - - - - org.jetbrains.kotlin - kotlin-maven-allopen - ${kotlin.version} - - - - - org.codehaus.mojo - build-helper-maven-plugin - - - generate-sources - - add-source - - - - ${basedir}/src/main/java - ${basedir}/src/main/kotlin - - - - - test-compile - test-compile - - add-test-source - - - - ${basedir}/src/test/java - ${basedir}/src/test/kotlin - - - - - - - - - - 2.9.0 - 2.9.9 - 1.2.71 - 4.5.8 - com.baeldung.Spring5Application - 0.18 - - - diff --git a/spring-5-mvc/src/main/kotlin/com/baeldung/springbootkotlin/HelloController.kt b/spring-5-mvc/src/main/kotlin/com/baeldung/springbootkotlin/HelloController.kt deleted file mode 100644 index 69be7dac7e..0000000000 --- a/spring-5-mvc/src/main/kotlin/com/baeldung/springbootkotlin/HelloController.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.baeldung.springbootkotlin - -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.RestController - -@RestController -class HelloController(val helloService: HelloService) { - - @GetMapping("/hello") - fun helloKotlin(): String { - return "hello world" - } - - @GetMapping("/hello-service") - fun helloKotlinService(): String { - return helloService.getHello() - } - - @GetMapping("/hello-dto") - fun helloDto(): HelloDto { - return HelloDto("Hello from the dto") - } -} \ No newline at end of file diff --git a/spring-5-mvc/src/main/kotlin/com/baeldung/springbootkotlin/HelloDto.kt b/spring-5-mvc/src/main/kotlin/com/baeldung/springbootkotlin/HelloDto.kt deleted file mode 100644 index f61c101f0f..0000000000 --- a/spring-5-mvc/src/main/kotlin/com/baeldung/springbootkotlin/HelloDto.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.springbootkotlin - -data class HelloDto(val greeting: String) diff --git a/spring-5-mvc/src/main/kotlin/com/baeldung/springbootkotlin/HelloService.kt b/spring-5-mvc/src/main/kotlin/com/baeldung/springbootkotlin/HelloService.kt deleted file mode 100644 index 67791a0c2d..0000000000 --- a/spring-5-mvc/src/main/kotlin/com/baeldung/springbootkotlin/HelloService.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.springbootkotlin - -import org.springframework.stereotype.Service - -@Service -class HelloService { - - fun getHello(): String { - return "hello service" - } -} \ No newline at end of file diff --git a/spring-5-mvc/src/main/kotlin/com/baeldung/springbootkotlin/KotlinDemoApplication.kt b/spring-5-mvc/src/main/kotlin/com/baeldung/springbootkotlin/KotlinDemoApplication.kt deleted file mode 100644 index 8904d8d805..0000000000 --- a/spring-5-mvc/src/main/kotlin/com/baeldung/springbootkotlin/KotlinDemoApplication.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.springbootkotlin - -import org.springframework.boot.SpringApplication -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration - -@SpringBootApplication(scanBasePackages = arrayOf("com.baeldung.springbootkotlin"), exclude = arrayOf(SecurityAutoConfiguration::class)) -class KotlinDemoApplication - -fun main(args: Array) { - SpringApplication.run(KotlinDemoApplication::class.java, *args) -} diff --git a/spring-5-mvc/src/test/kotlin/com/baeldung/springbootkotlin/KotlinDemoApplicationIntegrationTest.kt b/spring-5-mvc/src/test/kotlin/com/baeldung/springbootkotlin/KotlinDemoApplicationIntegrationTest.kt deleted file mode 100644 index d0667177c8..0000000000 --- a/spring-5-mvc/src/test/kotlin/com/baeldung/springbootkotlin/KotlinDemoApplicationIntegrationTest.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.baeldung.springbootkotlin - -import org.junit.Assert.assertEquals -import org.junit.Assert.assertNotNull -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.boot.test.web.client.TestRestTemplate -import org.springframework.http.HttpStatus -import org.springframework.test.context.junit4.SpringRunner - -@RunWith(SpringRunner::class) -@SpringBootTest( - classes = arrayOf(KotlinDemoApplication::class), - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -class KotlinDemoApplicationIntegrationTest { - - @Autowired - lateinit var testRestTemplate: TestRestTemplate - - @Test - fun whenCalled_thenShouldReturnHello() { - val result = testRestTemplate.withBasicAuth("user", "pass") - .getForEntity("/hello", String::class.java) - - assertNotNull(result) - assertEquals(HttpStatus.OK, result?.statusCode) - assertEquals("hello world", result?.body) - } - - @Test - fun whenCalled_thenShouldReturnHelloService() { - val result = testRestTemplate.withBasicAuth("user", "pass") - .getForEntity("/hello-service", String::class.java) - - assertNotNull(result) - assertEquals(HttpStatus.OK, result?.statusCode) - assertEquals(result?.body, "hello service") - } - - @Test - fun whenCalled_thenShouldReturnJson() { - val result = testRestTemplate.withBasicAuth("user", "pass") - .getForEntity("/hello-dto", HelloDto::class.java) - - assertNotNull(result) - assertEquals(HttpStatus.OK, result?.statusCode) - assertEquals(result?.body, HelloDto("Hello from the dto")) - } - -} diff --git a/spring-5-reactive-2/README.md b/spring-5-reactive-2/README.md index 54f7ad35b1..397f6be57c 100644 --- a/spring-5-reactive-2/README.md +++ b/spring-5-reactive-2/README.md @@ -6,7 +6,7 @@ This module contains articles about reactive Spring 5 - [Validation for Functional Endpoints in Spring 5](https://www.baeldung.com/spring-functional-endpoints-validation) - [Logging a Reactive Sequence](https://www.baeldung.com/spring-reactive-sequence-logging) - [Testing Reactive Streams Using StepVerifier and TestPublisher](https://www.baeldung.com/reactive-streams-step-verifier-test-publisher) -- [Debugging Reactive Streams in Spring 5](https://www.baeldung.com/spring-debugging-reactive-streams) +- [Debugging Reactive Streams in Java](https://www.baeldung.com/spring-debugging-reactive-streams) - [Static Content in Spring WebFlux](https://www.baeldung.com/spring-webflux-static-content) - [Server-Sent Events in Spring](https://www.baeldung.com/spring-server-sent-events) - More articles: [[<-- prev]](/spring-5-reactive) diff --git a/spring-5-reactive-client/README.md b/spring-5-reactive-client/README.md index eebdc23aed..154a3cab0b 100644 --- a/spring-5-reactive-client/README.md +++ b/spring-5-reactive-client/README.md @@ -8,6 +8,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles - [Logging Spring WebClient Calls](https://www.baeldung.com/spring-log-webclient-calls) - [Simultaneous Spring WebClient Calls](https://www.baeldung.com/spring-webclient-simultaneous-calls) -- [Logging Spring WebClient Calls](https://www.baeldung.com/spring-log-webclient-calls) - [Mocking a WebClient in Spring](https://www.baeldung.com/spring-mocking-webclient) - [Spring WebClient Filters](https://www.baeldung.com/spring-webclient-filters) +- [Get List of JSON Objects with WebClient](https://www.baeldung.com/spring-webclient-json-list) diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerService.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerService.java new file mode 100644 index 0000000000..17676b3f33 --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerService.java @@ -0,0 +1,18 @@ +package com.baeldung.webclient.json; + +import com.baeldung.webclient.json.model.Book; + +import java.util.List; + +public interface ReaderConsumerService { + + List processReaderDataFromObjectArray(); + + List processReaderDataFromReaderArray(); + + List processReaderDataFromReaderList(); + + List processNestedReaderDataFromReaderArray(); + + List processNestedReaderDataFromReaderList(); +} diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerServiceImpl.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerServiceImpl.java new file mode 100644 index 0000000000..8f1a4c019a --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/ReaderConsumerServiceImpl.java @@ -0,0 +1,90 @@ +package com.baeldung.webclient.json; + +import com.baeldung.webclient.json.model.Book; +import com.baeldung.webclient.json.model.Reader; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class ReaderConsumerServiceImpl implements ReaderConsumerService { + + private final WebClient webClient; + private static final ObjectMapper mapper = new ObjectMapper(); + + public ReaderConsumerServiceImpl(WebClient webClient) { + this.webClient = webClient; + } + @Override + public List processReaderDataFromObjectArray() { + Mono response = webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(Object[].class).log(); + Object[] objects = response.block(); + return Arrays.stream(objects) + .map(object -> mapper.convertValue(object, Reader.class)) + .map(Reader::getFavouriteBook) + .collect(Collectors.toList()); + } + + @Override + public List processReaderDataFromReaderArray() { + Mono response = + webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(Reader[].class).log(); + + Reader[] readers = response.block(); + return Arrays.stream(readers) + .map(Reader::getFavouriteBook) + .collect(Collectors.toList()); + } + + @Override + public List processReaderDataFromReaderList() { + Mono> response = webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(new ParameterizedTypeReference>() {}); + List readers = response.block(); + + return readers.stream() + .map(Reader::getFavouriteBook) + .collect(Collectors.toList()); + } + + @Override + public List processNestedReaderDataFromReaderArray() { + Mono response = webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(Reader[].class).log(); + Reader[] readers = response.block(); + + return Arrays.stream(readers) + .flatMap(reader -> reader.getBooksRead().stream()) + .map(Book::getAuthor) + .collect(Collectors.toList()); + } + + @Override + public List processNestedReaderDataFromReaderList() { + Mono> response = webClient.get() + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono(new ParameterizedTypeReference>() {}); + + List readers = response.block(); + return readers.stream() + .flatMap(reader -> reader.getBooksRead().stream()) + .map(Book::getAuthor) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Book.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Book.java new file mode 100644 index 0000000000..cb3fb258d4 --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Book.java @@ -0,0 +1,22 @@ +package com.baeldung.webclient.json.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Book { + private final String author; + private final String title; + + @JsonCreator + public Book( + @JsonProperty("author") String author, + @JsonProperty("title") String title) { + this.author = author; + this.title = title; + } + public String getAuthor() { + return this.author; + } +} diff --git a/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Reader.java b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Reader.java new file mode 100644 index 0000000000..7d02853ea1 --- /dev/null +++ b/spring-5-reactive-client/src/main/java/com/baeldung/webclient/json/model/Reader.java @@ -0,0 +1,33 @@ +package com.baeldung.webclient.json.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Reader { + private final int id; + private final String name; + private final Book favouriteBook; + private final List booksRead; + + @JsonCreator + public Reader( + @JsonProperty("id") int id, + @JsonProperty("name") String name, + @JsonProperty("favouriteBook") Book favouriteBook, + @JsonProperty("booksRead") List booksRead) { + this.id = id; + this.name = name; + this.favouriteBook = favouriteBook; + this.booksRead =booksRead; + } + + public Book getFavouriteBook() { + return favouriteBook; + } + + public List getBooksRead() { return booksRead; } +} diff --git a/spring-5-reactive-client/src/main/resources/application.properties b/spring-5-reactive-client/src/main/resources/application.properties index 2d93456aeb..05033054b1 100644 --- a/spring-5-reactive-client/src/main/resources/application.properties +++ b/spring-5-reactive-client/src/main/resources/application.properties @@ -1,3 +1,5 @@ logging.level.root=INFO -server.port=8081 \ No newline at end of file +server.port=8081 + +logging.level.reactor.netty.http.client.HttpClient=DEBUG \ No newline at end of file diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java index 95c63f267f..bb4e682481 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java @@ -1,13 +1,13 @@ package com.baeldung.reactive.logging; -import ch.qos.logback.classic.spi.LoggingEvent; -import ch.qos.logback.core.Appender; -import com.baeldung.reactive.logging.filters.LogFilters; -import com.baeldung.reactive.logging.netty.CustomLogger; -import com.fasterxml.jackson.databind.ObjectMapper; +import static com.baeldung.reactive.logging.jetty.RequestLogEnhancer.enhance; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import java.net.URI; -import lombok.AllArgsConstructor; -import lombok.Data; + import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.junit.jupiter.api.BeforeEach; @@ -17,14 +17,17 @@ import org.springframework.http.client.reactive.JettyClientHttpConnector; import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.WebClient; -import reactor.netty.channel.BootstrapHandlers; -import reactor.netty.http.client.HttpClient; -import static com.baeldung.reactive.logging.jetty.RequestLogEnhancer.enhance; -import static org.mockito.ArgumentMatchers.argThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import com.baeldung.reactive.logging.filters.LogFilters; +import com.fasterxml.jackson.databind.ObjectMapper; + +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.core.Appender; +import io.netty.handler.logging.LogLevel; +import lombok.AllArgsConstructor; +import lombok.Data; +import reactor.netty.http.client.HttpClient; +import reactor.netty.transport.logging.AdvancedByteBufFormat; public class WebClientLoggingIntegrationTest { @@ -114,21 +117,17 @@ public class WebClientLoggingIntegrationTest { @Test public void givenNettyHttpClientWithCustomLogger_whenEndpointIsConsumed_thenRequestAndResponseBodyLogged() { + reactor.netty.http.client.HttpClient httpClient = HttpClient.create() + .wiretap("reactor.netty.http.client.HttpClient", LogLevel.DEBUG, AdvancedByteBufFormat.TEXTUAL); - reactor.netty.http.client.HttpClient httpClient = HttpClient - .create() - .tcpConfiguration( - tc -> tc.bootstrap( - b -> BootstrapHandlers.updateLogSupport(b, new CustomLogger(HttpClient.class)))); - WebClient - .builder() - .clientConnector(new ReactorClientHttpConnector(httpClient)) - .build() - .post() - .uri(sampleUrl) - .body(BodyInserters.fromObject(post)) - .exchange() - .block(); + WebClient.builder() + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .build() + .post() + .uri(sampleUrl) + .body(BodyInserters.fromObject(post)) + .exchange() + .block(); verify(nettyAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains(sampleResponseBody))); } diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java deleted file mode 100644 index 9f2a4d127f..0000000000 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.reactive.logging.netty; - -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.logging.LoggingHandler; -import java.nio.charset.Charset; - -import static io.netty.util.internal.PlatformDependent.allocateUninitializedArray; -import static java.lang.Math.max; -import static java.nio.charset.Charset.defaultCharset; - -public class CustomLogger extends LoggingHandler { - public CustomLogger(Class clazz) { - super(clazz); - } - - @Override - protected String format(ChannelHandlerContext ctx, String event, Object arg) { - if (arg instanceof ByteBuf) { - ByteBuf msg = (ByteBuf) arg; - return decode(msg, msg.readerIndex(), msg.readableBytes(), defaultCharset()); - } - return super.format(ctx, event, arg); - } - - private String decode(ByteBuf src, int readerIndex, int len, Charset charset) { - if (len != 0) { - byte[] array; - int offset; - if (src.hasArray()) { - array = src.array(); - offset = src.arrayOffset() + readerIndex; - } else { - array = allocateUninitializedArray(max(len, 1024)); - offset = 0; - src.getBytes(readerIndex, array, 0, len); - } - return new String(array, offset, len, charset); - } - return ""; - } -} diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java new file mode 100644 index 0000000000..51f0a5c1bb --- /dev/null +++ b/spring-5-reactive-client/src/test/java/com/baeldung/webclient/json/ReaderConsumerServiceImplUnitTest.java @@ -0,0 +1,88 @@ +package com.baeldung.webclient.json; + +import com.baeldung.webclient.json.model.Book; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpStatus; +import org.springframework.web.reactive.function.client.ClientResponse; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Mono; + +import java.util.Arrays; +import java.util.List; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.CoreMatchers.hasItems; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.hasProperty; + +public class ReaderConsumerServiceImplUnitTest { + + private static String READER_JSON = "[{\"id\":1,\"name\":\"reader1\",\"favouriteBook\":{\"author\":\"Milan Kundera\",\"title\":\"The Unbearable Lightness of Being\"}," + + "\"booksRead\":[{\"author\":\"Charles Dickens\",\"title\":\"Oliver Twist\"},{\"author\":\"Milan Kundera\",\"title\":\"The Unbearable Lightness of Being\"}]}," + + "{\"id\":2,\"name\":\"reader2\",\"favouriteBook\":{\"author\":\"Douglas Adams\",\"title\":\"The Hitchhiker\'s Guide to the Galaxy\"}," + + "\"booksRead\":[{\"author\":\"J.R.R. Tolkien\",\"title\":\"Lord of the Rings\"}, " + + "{\"author\":\"Douglas Adams\",\"title\":\"The Hitchhiker\'s Guide to the Galaxy\"}]}]"; + + private static String BASE_URL = "http://localhost:8080/readers"; + + WebClient webClientMock = WebClient.builder().baseUrl(BASE_URL) + .exchangeFunction(clientRequest -> Mono.just(ClientResponse.create(HttpStatus.OK) + .header("content-type", "application/json") + .body(READER_JSON) + .build())) + .build(); + + private final ReaderConsumerService tested = new ReaderConsumerServiceImpl(webClientMock); + + @Test + void when_processReaderDataFromObjectArray_then_OK() { + String expectedAuthor1 = "Milan Kundera"; + String expectedAuthor2 = "Douglas Adams"; + List actual = tested.processReaderDataFromObjectArray(); + assertThat(actual, hasItems(hasProperty("author", is(expectedAuthor1)), + hasProperty("author", is(expectedAuthor2)))); + } + + @Test + void when_processReaderDataFromReaderArray_then_OK() { + String expectedAuthor1 = "Milan Kundera"; + String expectedAuthor2 = "Douglas Adams"; + List actual = tested.processReaderDataFromReaderArray(); + assertThat(actual, hasItems(hasProperty("author", is(expectedAuthor1)), + hasProperty("author", is(expectedAuthor2)))); + } + + @Test + void when_processReaderDataFromReaderList_then_OK() { + String expectedAuthor1 = "Milan Kundera"; + String expectedAuthor2 = "Douglas Adams"; + List actual = tested.processReaderDataFromReaderList(); + assertThat(actual, hasItems(hasProperty("author", is(expectedAuthor1)), + hasProperty("author", is(expectedAuthor2)))); + + } + + @Test + void when_processNestedReaderDataFromReaderArray_then_OK() { + List expected = Arrays.asList( + "Milan Kundera", + "Charles Dickens", + "J.R.R. Tolkien", + "Douglas Adams"); + + List actual = tested.processNestedReaderDataFromReaderArray(); + assertThat(actual, hasItems(expected.get(0), expected.get(1), expected.get(2), expected.get(3))); + } + + @Test + void when_processNestedReaderDataFromReaderList_then_OK() { + List expected = Arrays.asList( + "Milan Kundera", + "Charles Dickens", + "J.R.R. Tolkien", + "Douglas Adams"); + + List actual = tested.processNestedReaderDataFromReaderList(); + assertThat(actual, hasItems(expected.get(0), expected.get(1), expected.get(2), expected.get(3))); + } +} \ No newline at end of file diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/actuator/FeaturesEndpoint.java b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/actuator/FeaturesEndpoint.java index b2bc1e037f..d6cf1eb781 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/actuator/FeaturesEndpoint.java +++ b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/actuator/FeaturesEndpoint.java @@ -7,7 +7,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @Component -@Endpoint(id = "features", enableByDefault = true) +@Endpoint(id = "features") public class FeaturesEndpoint { private Map features = new ConcurrentHashMap<>(); diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/actuator/Spring5ReactiveApplication.java b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/actuator/Spring5ReactiveApplication.java index 03943d436d..600bff5948 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/actuator/Spring5ReactiveApplication.java +++ b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/actuator/Spring5ReactiveApplication.java @@ -4,7 +4,7 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication -public class Spring5ReactiveApplication{ +public class Spring5ReactiveApplication { public static void main(String[] args) { SpringApplication.run(Spring5ReactiveApplication.class, args); diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/actuator/WebSecurityConfig.java b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/actuator/WebSecurityConfig.java index 07f805fea4..384e26ac8c 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/actuator/WebSecurityConfig.java +++ b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/actuator/WebSecurityConfig.java @@ -1,10 +1,7 @@ package com.baeldung.reactive.actuator; -import org.springframework.boot.actuate.autoconfigure.security.reactive.EndpointRequest; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity; import org.springframework.security.config.web.server.ServerHttpSecurity; import org.springframework.security.web.server.SecurityWebFilterChain; @@ -12,17 +9,15 @@ import org.springframework.security.web.server.SecurityWebFilterChain; @Configuration @EnableWebFluxSecurity public class WebSecurityConfig { - - + @Bean public SecurityWebFilterChain securitygWebFilterChain( ServerHttpSecurity http) { - return http - - .authorizeExchange() - .matchers(EndpointRequest.to( - FeaturesEndpoint.class - )).permitAll().anyExchange().permitAll().and().csrf().disable().build(); + + return http.authorizeExchange() + .pathMatchers("/actuator/**").permitAll() + .anyExchange().authenticated() + .and().build(); } - + } diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/SecurityConfig.java b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/SecurityConfig.java index 225f78b3f7..64e96ddae1 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/SecurityConfig.java +++ b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/SecurityConfig.java @@ -21,12 +21,12 @@ public class SecurityConfig { @Bean public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) { return http.authorizeExchange() - .pathMatchers("/", "/admin") + .pathMatchers("/admin") .hasAuthority("ROLE_ADMIN") .matchers(EndpointRequest.to(FeaturesEndpoint.class)) .permitAll() .anyExchange() - .permitAll() + .authenticated() .and() .formLogin() .and() diff --git a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/SpringSecurity5Application.java b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/SpringSecurity5Application.java index 325923f577..bb0f007ada 100644 --- a/spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/SpringSecurity5Application.java +++ b/spring-5-reactive-security/src/main/java/com/baeldung/reactive/security/SpringSecurity5Application.java @@ -28,9 +28,7 @@ public class SpringSecurity5Application { HttpHandler handler = WebHttpHandlerBuilder.applicationContext(context) .build(); ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler); - HttpServer httpServer = HttpServer.create(); - httpServer.host("localhost"); - httpServer.port(8080); + HttpServer httpServer = HttpServer.create().host("localhost").port(8083); return httpServer.handle(adapter).bindNow(); } diff --git a/spring-5-reactive/pom.xml b/spring-5-reactive/pom.xml index 3b7383f726..40791faaaf 100644 --- a/spring-5-reactive/pom.xml +++ b/spring-5-reactive/pom.xml @@ -1,6 +1,7 @@ - + 4.0.0 spring-5-reactive 0.0.1-SNAPSHOT @@ -73,6 +74,12 @@ spring-security-test test
+ + io.projectreactor + reactor-test + test + + @@ -149,7 +156,6 @@ - 1.0.1.RELEASE 1.1.3 1.0 1.0 diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/FormHandler.java b/spring-5-reactive/src/main/java/com/baeldung/functional/FormHandler.java index c4f8c9f41f..2b415d5f1e 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/functional/FormHandler.java +++ b/spring-5-reactive/src/main/java/com/baeldung/functional/FormHandler.java @@ -11,7 +11,7 @@ import java.util.concurrent.atomic.AtomicLong; import static org.springframework.web.reactive.function.BodyExtractors.toDataBuffers; import static org.springframework.web.reactive.function.BodyExtractors.toFormData; -import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.BodyInserters.fromValue; import static org.springframework.web.reactive.function.server.ServerResponse.ok; public class FormHandler { @@ -29,7 +29,7 @@ public class FormHandler { Mono handleUpload(ServerRequest request) { return request.body(toDataBuffers()) .collectList() - .flatMap(dataBuffers -> ok().body(fromObject(extractData(dataBuffers).toString()))); + .flatMap(dataBuffers -> ok().body(fromValue(extractData(dataBuffers).toString()))); } private AtomicLong extractData(List dataBuffers) { diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java b/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java index 9cbc1b7669..9bfd0afe7e 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java +++ b/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalSpringBootApplication.java @@ -1,6 +1,6 @@ package com.baeldung.functional; -import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.BodyInserters.fromValue; import static org.springframework.web.reactive.function.server.RequestPredicates.GET; import static org.springframework.web.reactive.function.server.RequestPredicates.POST; import static org.springframework.web.reactive.function.server.RequestPredicates.path; @@ -44,7 +44,7 @@ public class FunctionalSpringBootApplication { .doOnNext(actors::add) .then(ok().build())); - return route(GET("/test"), serverRequest -> ok().body(fromObject("helloworld"))) + return route(GET("/test"), serverRequest -> ok().body(fromValue("helloworld"))) .andRoute(POST("/login"), formHandler::handleLogin) .andRoute(POST("/upload"), formHandler::handleUpload) .and(RouterFunctions.resources("/files/**", new ClassPathResource("files/"))) diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java b/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java index 1f40798ada..9930ffb474 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java +++ b/spring-5-reactive/src/main/java/com/baeldung/functional/FunctionalWebApplication.java @@ -1,9 +1,9 @@ package com.baeldung.functional; -import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.BodyInserters.fromValue; import static org.springframework.web.reactive.function.server.RequestPredicates.GET; import static org.springframework.web.reactive.function.server.RequestPredicates.POST; -import static org.springframework.web.reactive.function.server.RequestPredicates.path; +import static org.springframework.web.reactive.function.server.RequestPredicates.accept; import static org.springframework.web.reactive.function.server.RouterFunctions.route; import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler; import static org.springframework.web.reactive.function.server.ServerResponse.ok; @@ -18,6 +18,7 @@ import org.apache.catalina.startup.Tomcat; import org.springframework.boot.web.embedded.tomcat.TomcatWebServer; import org.springframework.boot.web.server.WebServer; import org.springframework.core.io.ClassPathResource; +import org.springframework.http.MediaType; import org.springframework.http.server.reactive.HttpHandler; import org.springframework.http.server.reactive.ServletHttpHandlerAdapter; import org.springframework.web.reactive.function.server.RouterFunction; @@ -37,14 +38,14 @@ public class FunctionalWebApplication { private RouterFunction routingFunction() { FormHandler formHandler = new FormHandler(); - RouterFunction restfulRouter = route(GET("/"), serverRequest -> ok().body(Flux.fromIterable(actors), Actor.class)).andRoute(POST("/"), serverRequest -> serverRequest.bodyToMono(Actor.class) + RouterFunction restfulRouter = route(GET("/actor"), serverRequest -> ok().body(Flux.fromIterable(actors), Actor.class)).andRoute(POST("/actor"), serverRequest -> serverRequest.bodyToMono(Actor.class) .doOnNext(actors::add) .then(ok().build())); - return route(GET("/test"), serverRequest -> ok().body(fromObject("helloworld"))).andRoute(POST("/login"), formHandler::handleLogin) + return route(GET("/test"), serverRequest -> ok().body(fromValue("helloworld"))).andRoute(POST("/login"), formHandler::handleLogin) .andRoute(POST("/upload"), formHandler::handleUpload) .and(RouterFunctions.resources("/files/**", new ClassPathResource("files/"))) - .andNest(path("/actor"), restfulRouter) + .andNest(accept(MediaType.APPLICATION_JSON), restfulRouter) .filter((request, next) -> { System.out.println("Before handler invocation: " + request.path()); return next.handle(request); diff --git a/spring-5-reactive/src/main/java/com/baeldung/functional/RootServlet.java b/spring-5-reactive/src/main/java/com/baeldung/functional/RootServlet.java index 8fe24821de..6c36b7fa03 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/functional/RootServlet.java +++ b/spring-5-reactive/src/main/java/com/baeldung/functional/RootServlet.java @@ -2,7 +2,7 @@ package com.baeldung.functional; import static org.springframework.web.reactive.function.BodyExtractors.toDataBuffers; import static org.springframework.web.reactive.function.BodyExtractors.toFormData; -import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.BodyInserters.fromValue; import static org.springframework.web.reactive.function.server.RequestPredicates.GET; import static org.springframework.web.reactive.function.server.RequestPredicates.POST; import static org.springframework.web.reactive.function.server.RequestPredicates.path; @@ -46,7 +46,7 @@ public class RootServlet extends ServletHttpHandlerAdapter { private static RouterFunction routingFunction() { - return route(GET("/test"), serverRequest -> ok().body(fromObject("helloworld"))).andRoute(POST("/login"), serverRequest -> serverRequest.body(toFormData()) + return route(GET("/test"), serverRequest -> ok().body(fromValue("helloworld"))).andRoute(POST("/login"), serverRequest -> serverRequest.body(toFormData()) .map(MultiValueMap::toSingleValueMap) .map(formData -> { System.out.println("form data: " + formData.toString()); @@ -65,7 +65,7 @@ public class RootServlet extends ServletHttpHandlerAdapter { dataBuffers.forEach(d -> atomicLong.addAndGet(d.asByteBuffer() .array().length)); System.out.println("data length:" + atomicLong.get()); - return ok().body(fromObject(atomicLong.toString())) + return ok().body(fromValue(atomicLong.toString())) .block(); })) .and(RouterFunctions.resources("/files/**", new ClassPathResource("files/"))) diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorWebExceptionHandler.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorWebExceptionHandler.java index 051e4b8df5..4f3f1795da 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorWebExceptionHandler.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/GlobalErrorWebExceptionHandler.java @@ -2,7 +2,8 @@ package com.baeldung.reactive.errorhandling; import java.util.Map; -import org.springframework.boot.autoconfigure.web.ResourceProperties; + +import org.springframework.boot.autoconfigure.web.WebProperties; import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler; import org.springframework.boot.web.error.ErrorAttributeOptions; import org.springframework.boot.web.reactive.error.ErrorAttributes; @@ -18,6 +19,7 @@ import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; + import reactor.core.publisher.Mono; @Component @@ -26,7 +28,7 @@ public class GlobalErrorWebExceptionHandler extends AbstractErrorWebExceptionHan public GlobalErrorWebExceptionHandler(GlobalErrorAttributes g, ApplicationContext applicationContext, ServerCodecConfigurer serverCodecConfigurer) { - super(g, new ResourceProperties(), applicationContext); + super(g, new WebProperties.Resources(), applicationContext); super.setMessageWriters(serverCodecConfigurer.getWriters()); super.setMessageReaders(serverCodecConfigurer.getReaders()); } @@ -41,8 +43,8 @@ public class GlobalErrorWebExceptionHandler extends AbstractErrorWebExceptionHan final Map errorPropertiesMap = getErrorAttributes(request, ErrorAttributeOptions.defaults()); return ServerResponse.status(HttpStatus.BAD_REQUEST) - .contentType(MediaType.APPLICATION_JSON_UTF8) - .body(BodyInserters.fromObject(errorPropertiesMap)); + .contentType(MediaType.APPLICATION_JSON) + .body(BodyInserters.fromValue(errorPropertiesMap)); } } diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler1.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler1.java index 87b78a4654..c71c8ecac0 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler1.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler1.java @@ -14,7 +14,7 @@ public class Handler1 { return sayHello(request).onErrorReturn("Hello, Stranger") .flatMap(s -> ServerResponse.ok() .contentType(MediaType.TEXT_PLAIN) - .syncBody(s)); + .bodyValue(s)); } private Mono sayHello(ServerRequest request) { diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler2.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler2.java index 12172a0f54..92e881543e 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler2.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler2.java @@ -15,11 +15,11 @@ public Mono handleRequest2(ServerRequest request) { sayHello(request) .flatMap(s -> ServerResponse.ok() .contentType(MediaType.TEXT_PLAIN) - .syncBody(s)) + .bodyValue(s)) .onErrorResume(e -> sayHelloFallback() .flatMap(s -> ServerResponse.ok() .contentType(MediaType.TEXT_PLAIN) - .syncBody(s))); + .bodyValue(s))); } private Mono sayHello(ServerRequest request) { diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler3.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler3.java index e95b039cce..8c988a6633 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler3.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/errorhandling/handlers/Handler3.java @@ -15,11 +15,11 @@ public class Handler3 { sayHello(request) .flatMap(s -> ServerResponse.ok() .contentType(MediaType.TEXT_PLAIN) - .syncBody(s)) + .bodyValue(s)) .onErrorResume(e -> (Mono.just("Hi, I looked around for your name but found: " + e.getMessage())).flatMap(s -> ServerResponse.ok() .contentType(MediaType.TEXT_PLAIN) - .syncBody(s))); + .bodyValue(s))); } private Mono sayHello(ServerRequest request) { diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java index 115a057915..34abada2f1 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/ExploreSpring5URLPatternUsingRouterFunctions.java @@ -1,6 +1,6 @@ package com.baeldung.reactive.urlmatch; -import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.BodyInserters.fromValue; import static org.springframework.web.reactive.function.server.RequestPredicates.GET; import static org.springframework.web.reactive.function.server.RouterFunctions.route; import static org.springframework.web.reactive.function.server.RouterFunctions.toHttpHandler; @@ -24,10 +24,10 @@ public class ExploreSpring5URLPatternUsingRouterFunctions { private RouterFunction routingFunction() { - return route(GET("/p?ths"), serverRequest -> ok().body(fromObject("/p?ths"))).andRoute(GET("/test/{*id}"), serverRequest -> ok().body(fromObject(serverRequest.pathVariable("id")))) - .andRoute(GET("/*card"), serverRequest -> ok().body(fromObject("/*card path was accessed"))) - .andRoute(GET("/{var1}_{var2}"), serverRequest -> ok().body(fromObject(serverRequest.pathVariable("var1") + " , " + serverRequest.pathVariable("var2")))) - .andRoute(GET("/{baeldung:[a-z]+}"), serverRequest -> ok().body(fromObject("/{baeldung:[a-z]+} was accessed and baeldung=" + serverRequest.pathVariable("baeldung")))) + return route(GET("/p?ths"), serverRequest -> ok().body(fromValue("/p?ths"))).andRoute(GET("/test/{*id}"), serverRequest -> ok().body(fromValue(serverRequest.pathVariable("id")))) + .andRoute(GET("/*card"), serverRequest -> ok().body(fromValue("/*card path was accessed"))) + .andRoute(GET("/{var1}_{var2}"), serverRequest -> ok().body(fromValue(serverRequest.pathVariable("var1") + " , " + serverRequest.pathVariable("var2")))) + .andRoute(GET("/{baeldung:[a-z]+}"), serverRequest -> ok().body(fromValue("/{baeldung:[a-z]+} was accessed and baeldung=" + serverRequest.pathVariable("baeldung")))) .and(RouterFunctions.resources("/files/{*filepaths}", new ClassPathResource("files/"))); } diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/FormHandler.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/FormHandler.java index 0781230379..7b1fb06459 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/FormHandler.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/FormHandler.java @@ -11,7 +11,7 @@ import java.util.concurrent.atomic.AtomicLong; import static org.springframework.web.reactive.function.BodyExtractors.toDataBuffers; import static org.springframework.web.reactive.function.BodyExtractors.toFormData; -import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.BodyInserters.fromValue; import static org.springframework.web.reactive.function.server.ServerResponse.ok; public class FormHandler { @@ -29,7 +29,7 @@ public class FormHandler { Mono handleUpload(ServerRequest request) { return request.body(toDataBuffers()) .collectList() - .flatMap(dataBuffers -> ok().body(fromObject(extractData(dataBuffers).toString()))); + .flatMap(dataBuffers -> ok().body(fromValue(extractData(dataBuffers).toString()))); } private AtomicLong extractData(List dataBuffers) { diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/FunctionalWebApplication.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/FunctionalWebApplication.java index 2ea5420a2b..6cec902a0d 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/FunctionalWebApplication.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/urlmatch/FunctionalWebApplication.java @@ -1,6 +1,6 @@ package com.baeldung.reactive.urlmatch; -import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.BodyInserters.fromValue; import static org.springframework.web.reactive.function.server.RequestPredicates.GET; import static org.springframework.web.reactive.function.server.RequestPredicates.POST; import static org.springframework.web.reactive.function.server.RequestPredicates.path; @@ -40,7 +40,7 @@ public class FunctionalWebApplication { .doOnNext(actors::add) .then(ok().build())); - return route(GET("/test"), serverRequest -> ok().body(fromObject("helloworld"))).andRoute(POST("/login"), formHandler::handleLogin) + return route(GET("/test"), serverRequest -> ok().body(fromValue("helloworld"))).andRoute(POST("/login"), formHandler::handleLogin) .andRoute(POST("/upload"), formHandler::handleUpload) .and(RouterFunctions.resources("/files/**", new ClassPathResource("files/"))) .andNest(path("/actor"), restfulRouter) diff --git a/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/Foo.java b/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/Foo.java new file mode 100644 index 0000000000..c6e3678832 --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/Foo.java @@ -0,0 +1,24 @@ +package com.baeldung.web.reactive.client; + +public class Foo { + + private String name; + + public Foo() { + super(); + } + + public Foo(String name) { + super(); + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientApplication.java b/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientApplication.java new file mode 100644 index 0000000000..aa9b81de4f --- /dev/null +++ b/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.web.reactive.client; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration; + +@SpringBootApplication(exclude = { ReactiveSecurityAutoConfiguration.class }) +public class WebClientApplication { + + public static void main(String[] args) { + SpringApplication.run(WebClientApplication.class, args); + } + +} diff --git a/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientController.java b/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientController.java index a719259328..1a91001807 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientController.java +++ b/spring-5-reactive/src/main/java/com/baeldung/web/reactive/client/WebClientController.java @@ -1,83 +1,42 @@ package com.baeldung.web.reactive.client; -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.springframework.http.*; -import org.springframework.util.LinkedMultiValueMap; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.reactive.function.BodyInserter; -import org.springframework.web.reactive.function.BodyInserters; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Mono; -import java.net.URI; -import java.nio.charset.Charset; -import java.time.ZonedDateTime; -import java.util.Collections; +import reactor.core.publisher.Mono; @RestController public class WebClientController { @ResponseStatus(HttpStatus.OK) @GetMapping("/resource") - public void getResource() { + public Map getResource() { + Map response = new HashMap<>(); + response.put("field", "value"); + return response; } - public void demonstrateWebClient() { - // request - WebClient.UriSpec request1 = createWebClientWithServerURLAndDefaultValues().method(HttpMethod.POST); - WebClient.UriSpec request2 = createWebClientWithServerURLAndDefaultValues().post(); - - // request body specifications - WebClient.RequestBodySpec uri1 = createWebClientWithServerURLAndDefaultValues().method(HttpMethod.POST) - .uri("/resource"); - WebClient.RequestBodySpec uri2 = createWebClientWithServerURLAndDefaultValues().post() - .uri(URI.create("/resource")); - - // request header specification - WebClient.RequestHeadersSpec requestSpec1 = uri1.body(BodyInserters.fromPublisher(Mono.just("data"), String.class)); - WebClient.RequestHeadersSpec requestSpec2 = uri2.body(BodyInserters.fromObject("data")); - - // inserters - BodyInserter, ReactiveHttpOutputMessage> inserter1 = BodyInserters - .fromPublisher(Subscriber::onComplete, String.class); - - LinkedMultiValueMap map = new LinkedMultiValueMap<>(); - map.add("key1", "value1"); - map.add("key2", "value2"); - - // BodyInserter, ClientHttpRequest> inserter2 = BodyInserters.fromMultipartData(map); - BodyInserter inserter3 = BodyInserters.fromObject("body"); - - // responses - WebClient.ResponseSpec response1 = uri1.body(inserter3) - .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML) - .acceptCharset(Charset.forName("UTF-8")) - .ifNoneMatch("*") - .ifModifiedSince(ZonedDateTime.now()) - .retrieve(); - WebClient.ResponseSpec response2 = requestSpec2.retrieve(); - + @PostMapping("/resource") + public Mono postStringResource(@RequestBody Mono bodyString) { + return bodyString.map(body -> "processed-" + body); } - private WebClient createWebClient() { - return WebClient.create(); + @PostMapping("/resource-foo") + public Mono postFooResource(@RequestBody Mono bodyFoo) { + return bodyFoo.map(foo -> "processedFoo-" + foo.getName()); } - private WebClient createWebClientWithServerURL() { - return WebClient.create("http://localhost:8081"); + @PostMapping(value = "/resource-multipart", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public String handleFormUpload(@RequestPart("key1") String value1, @RequestPart("key2") String value2) { + return "processed-" + value1 + "-" + value2; } - - private WebClient createWebClientWithServerURLAndDefaultValues() { - return WebClient.builder() - .baseUrl("http://localhost:8081") - .defaultCookie("cookieKey", "cookieValue") - .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .defaultUriVariables(Collections.singletonMap("url", "http://localhost:8080")) - .build(); - } - } diff --git a/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java index 1256d5f129..3164adbe4a 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java @@ -1,6 +1,6 @@ package com.baeldung.functional; -import static org.springframework.web.reactive.function.BodyInserters.fromObject; +import static org.springframework.web.reactive.function.BodyInserters.fromValue; import static org.springframework.web.reactive.function.BodyInserters.fromResource; import org.junit.AfterClass; @@ -10,7 +10,6 @@ import org.springframework.boot.web.server.WebServer; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.http.MediaType; -import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -114,7 +113,7 @@ public class FunctionalWebApplicationIntegrationTest { client.post() .uri("/actor") - .body(fromObject(new Actor("Clint", "Eastwood"))) + .body(fromValue(new Actor("Clint", "Eastwood"))) .exchange() .expectStatus() .isOk(); diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/Spring5ReactiveServerClientIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/reactive/Spring5ReactiveServerClientIntegrationTest.java deleted file mode 100644 index b8dd9c9509..0000000000 --- a/spring-5-reactive/src/test/java/com/baeldung/reactive/Spring5ReactiveServerClientIntegrationTest.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.baeldung.reactive; - -import static org.springframework.web.reactive.function.server.RequestPredicates.GET; -import static org.springframework.web.reactive.function.server.RequestPredicates.POST; - -import java.time.Duration; - -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.springframework.http.server.reactive.HttpHandler; -import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.RouterFunctions; -import org.springframework.web.reactive.function.server.ServerResponse; - -import com.baeldung.web.reactive.Task; - -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; -import reactor.netty.DisposableServer; -import reactor.netty.http.server.HttpServer; - -public class Spring5ReactiveServerClientIntegrationTest { - private static DisposableServer disposableServer; - - @BeforeAll - public static void setUp() throws Exception { - HttpServer server = HttpServer.create() - .host("localhost") - .port(8080); - RouterFunction route = RouterFunctions.route(POST("/task/process"), request -> ServerResponse.ok() - .body(request.bodyToFlux(Task.class) - .map(ll -> new Task("TaskName", 1)), Task.class)) - .and(RouterFunctions.route(GET("/task"), request -> ServerResponse.ok() - .body(Mono.just("server is alive"), String.class))); - HttpHandler httpHandler = RouterFunctions.toHttpHandler(route); - ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler); - disposableServer = server.handle(adapter) - .bindNow(); - } - - @AfterAll - public static void shutDown() { - disposableServer.disposeNow(); - } - - // @Test - // public void givenCheckTask_whenServerHandle_thenServerResponseALiveString() throws Exception { - // WebClient client = WebClient.create("http://localhost:8080"); - // Mono result = client - // .get() - // .uri("/task") - // .exchange() - // .then(response -> response.bodyToMono(String.class)); - // - // assertThat(result.block()).isInstanceOf(String.class); - // } - - // @Test - // public void givenThreeTasks_whenServerHandleTheTasks_thenServerResponseATask() throws Exception { - // URI uri = URI.create("http://localhost:8080/task/process"); - // ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector()); - // ClientRequest request = ClientRequest - // .method(HttpMethod.POST, uri) - // .body(BodyInserters.fromPublisher(getLatLngs(), Task.class)) - // .build(); - // - // Flux taskResponse = exchange - // .exchange(request) - // .flatMap(response -> response.bodyToFlux(Task.class)); - // - // assertThat(taskResponse.blockFirst()).isInstanceOf(Task.class); - // } - - // @Test - // public void givenCheckTask_whenServerHandle_thenOragicServerResponseALiveString() throws Exception { - // URI uri = URI.create("http://localhost:8080/task"); - // ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector()); - // ClientRequest request = ClientRequest - // .method(HttpMethod.GET, uri) - // .body(BodyInserters.fromPublisher(getLatLngs(), Task.class)) - // .build(); - // - // Flux taskResponse = exchange - // .exchange(request) - // .flatMap(response -> response.bodyToFlux(String.class)); - // - // assertThat(taskResponse.blockFirst()).isInstanceOf(String.class); - // } - - private static Flux getLatLngs() { - return Flux.range(0, 3) - .zipWith(Flux.interval(Duration.ofSeconds(1))) - .map(x -> new Task("taskname", 1)) - .doOnNext(ll -> System.out.println("Produced: {}" + ll)); - } -} diff --git a/spring-5-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java index 3bbbed0d77..38443a4eac 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/reactive/errorhandling/ErrorHandlingIntegrationTest.java @@ -133,7 +133,7 @@ public class ErrorHandlingIntegrationTest { .expectStatus() .isBadRequest() .expectHeader() - .contentType(MediaType.APPLICATION_JSON_UTF8) + .contentType(MediaType.APPLICATION_JSON) .expectBody() .jsonPath("$.message") .isNotEmpty() @@ -164,7 +164,7 @@ public class ErrorHandlingIntegrationTest { .expectStatus() .isBadRequest() .expectHeader() - .contentType(MediaType.APPLICATION_JSON_UTF8) + .contentType(MediaType.APPLICATION_JSON) .expectBody() .jsonPath("$.message") .isNotEmpty() diff --git a/spring-5-reactive/src/test/java/com/baeldung/web/client/SpringContextTest.java b/spring-5-reactive/src/test/java/com/baeldung/web/client/SpringContextTest.java new file mode 100644 index 0000000000..8d2ca41451 --- /dev/null +++ b/spring-5-reactive/src/test/java/com/baeldung/web/client/SpringContextTest.java @@ -0,0 +1,14 @@ +package com.baeldung.web.client; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import com.baeldung.web.reactive.client.WebClientApplication; + +@SpringBootTest(classes = WebClientApplication.class) +public class SpringContextTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/spring-5-reactive/src/test/java/com/baeldung/web/client/WebClientIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/web/client/WebClientIntegrationTest.java new file mode 100644 index 0000000000..7e1fc86847 --- /dev/null +++ b/spring-5-reactive/src/test/java/com/baeldung/web/client/WebClientIntegrationTest.java @@ -0,0 +1,331 @@ +package com.baeldung.web.client; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.time.ZonedDateTime; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.core.codec.CodecException; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ReactiveHttpOutputMessage; +import org.springframework.http.client.reactive.ClientHttpRequest; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.reactive.function.BodyInserter; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.client.WebClient.RequestBodySpec; +import org.springframework.web.reactive.function.client.WebClient.RequestBodyUriSpec; +import org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec; +import org.springframework.web.reactive.function.client.WebClient.RequestHeadersUriSpec; +import org.springframework.web.reactive.function.client.WebClient.ResponseSpec; +import org.springframework.web.reactive.function.client.WebClientRequestException; + +import com.baeldung.web.reactive.client.Foo; +import com.baeldung.web.reactive.client.WebClientApplication; + +import io.netty.channel.ChannelOption; +import io.netty.handler.timeout.ReadTimeoutException; +import io.netty.handler.timeout.ReadTimeoutHandler; +import io.netty.handler.timeout.WriteTimeoutHandler; +import reactor.core.publisher.Mono; +import reactor.netty.http.client.HttpClient; +import reactor.test.StepVerifier; + +@SpringBootTest(classes = WebClientApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT) +public class WebClientIntegrationTest { + + @LocalServerPort + private int port; + + private static final String BODY_VALUE = "bodyValue"; + private static final ParameterizedTypeReference> MAP_RESPONSE_REF = new ParameterizedTypeReference>() { + }; + + @Test + public void givenDifferentWebClientCreationMethods_whenUsed_thenObtainExpectedResponse() { + // WebClient creation + WebClient client1 = WebClient.create(); + WebClient client2 = WebClient.create("http://localhost:" + port); + WebClient client3 = WebClient.builder() + .baseUrl("http://localhost:" + port) + .defaultCookie("cookieKey", "cookieValue") + .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .defaultUriVariables(Collections.singletonMap("url", "http://localhost:8080")) + .build(); + + // response assertions + StepVerifier.create(retrieveResponse(client1.post() + .uri("http://localhost:" + port + "/resource"))) + .expectNext("processed-bodyValue") + .verifyComplete(); + StepVerifier.create(retrieveResponse(client2)) + .expectNext("processed-bodyValue") + .verifyComplete(); + StepVerifier.create(retrieveResponse(client3)) + .expectNext("processed-bodyValue") + .verifyComplete(); + // assert response without specifying URI + StepVerifier.create(retrieveResponse(client1)) + .expectErrorMatches(ex -> WebClientRequestException.class.isAssignableFrom(ex.getClass()) && ex.getMessage() + .contains("Connection refused")) + .verify(); + } + + @Test + public void givenDifferentMethodSpecifications_whenUsed_thenObtainExpectedResponse() { + // request specification + RequestBodyUriSpec uriSpecPost1 = createDefaultClient().method(HttpMethod.POST); + RequestBodyUriSpec uriSpecPost2 = createDefaultClient().post(); + RequestHeadersUriSpec requestGet = createDefaultClient().get(); + + // response assertions + StepVerifier.create(retrieveResponse(uriSpecPost1)) + .expectNext("processed-bodyValue") + .verifyComplete(); + StepVerifier.create(retrieveResponse(uriSpecPost2)) + .expectNext("processed-bodyValue") + .verifyComplete(); + StepVerifier.create(retrieveGetResponse(requestGet)) + .expectNextMatches(nextMap -> nextMap.get("field") + .equals("value")) + .verifyComplete(); + } + + @Test + public void givenDifferentUriSpecifications_whenUsed_thenObtainExpectedResponse() { + // uri specification + RequestBodySpec bodySpecUsingString = createDefaultPostRequest().uri("/resource"); + RequestBodySpec bodySpecUsingUriBuilder = createDefaultPostRequest().uri(uriBuilder -> uriBuilder.pathSegment("resource") + .build()); + RequestBodySpec bodySpecusingURI = createDefaultPostRequest().uri(URI.create("http://localhost:" + port + "/resource")); + RequestBodySpec bodySpecOverridenBaseUri = createDefaultPostRequest().uri(URI.create("/resource")); + RequestBodySpec bodySpecOverridenBaseUri2 = WebClient.builder() + .baseUrl("http://localhost:" + port) + .build() + .post() + .uri(URI.create("/resource")); + + // response assertions + StepVerifier.create(retrieveResponse(bodySpecUsingString)) + .expectNext("processed-bodyValue") + .verifyComplete(); + StepVerifier.create(retrieveResponse(bodySpecUsingUriBuilder)) + .expectNext("processed-bodyValue") + .verifyComplete(); + StepVerifier.create(retrieveResponse(bodySpecusingURI)) + .expectNext("processed-bodyValue") + .verifyComplete(); + // assert sending request overriding base URI + StepVerifier.create(retrieveResponse(bodySpecOverridenBaseUri)) + .expectErrorMatches(ex -> WebClientRequestException.class.isAssignableFrom(ex.getClass()) && ex.getMessage() + .contains("Connection refused")) + .verify(); + StepVerifier.create(retrieveResponse(bodySpecOverridenBaseUri2)) + .expectErrorMatches(ex -> WebClientRequestException.class.isAssignableFrom(ex.getClass()) && ex.getMessage() + .contains("Connection refused")) + .verify(); + } + + @Test + public void givenDifferentBodySpecifications_whenUsed_thenObtainExpectedResponse() { + // request body specifications + RequestHeadersSpec headersSpecPost1 = createDefaultPostResourceRequest().body(BodyInserters.fromPublisher(Mono.just(BODY_VALUE), String.class)); + RequestHeadersSpec headersSpecPost2 = createDefaultPostResourceRequest().body(BodyInserters.fromValue(BODY_VALUE)); + RequestHeadersSpec headersSpecPost3 = createDefaultPostResourceRequest().bodyValue(BODY_VALUE); + RequestHeadersSpec headersSpecFooPost = createDefaultPostRequest().uri("/resource-foo") + .body(Mono.just(new Foo("fooName")), Foo.class); + BodyInserter inserterPlainObject = BodyInserters.fromValue(new Object()); + RequestHeadersSpec headersSpecPlainObject = createDefaultPostResourceRequest().body(inserterPlainObject); + + // request body specifications - using other inserter method (multipart request) + LinkedMultiValueMap map = new LinkedMultiValueMap<>(); + map.add("key1", "multipartValue1"); + map.add("key2", "multipartValue2"); + BodyInserter, ClientHttpRequest> inserterMultipart = BodyInserters.fromMultipartData(map); + RequestHeadersSpec headersSpecInserterMultipart = createDefaultPostRequest().uri("/resource-multipart") + .body(inserterMultipart); + + // response assertions + StepVerifier.create(retrieveResponse(headersSpecPost1)) + .expectNext("processed-bodyValue") + .verifyComplete(); + StepVerifier.create(retrieveResponse(headersSpecPost2)) + .expectNext("processed-bodyValue") + .verifyComplete(); + StepVerifier.create(retrieveResponse(headersSpecPost3)) + .expectNext("processed-bodyValue") + .verifyComplete(); + StepVerifier.create(retrieveResponse(headersSpecFooPost)) + .expectNext("processedFoo-fooName") + .verifyComplete(); + StepVerifier.create(retrieveResponse(headersSpecInserterMultipart)) + .expectNext("processed-multipartValue1-multipartValue2") + .verifyComplete(); + // assert error plain `new Object()` as request body + StepVerifier.create(retrieveResponse(headersSpecPlainObject)) + .expectError(CodecException.class) + .verify(); + // assert response for request with no body + Mono> responsePostWithNoBody = createDefaultPostResourceRequest().exchangeToMono(responseHandler -> { + assertThat(responseHandler.statusCode()).isEqualTo(HttpStatus.BAD_REQUEST); + return responseHandler.bodyToMono(MAP_RESPONSE_REF); + }); + StepVerifier.create(responsePostWithNoBody) + .expectNextMatches(nextMap -> nextMap.get("error") + .equals("Bad Request")) + .verifyComplete(); + } + + @Test + public void givenPostSpecifications_whenHeadersAdded_thenObtainExpectedResponse() { + // request header specification + RequestHeadersSpec headersSpecInserterStringWithHeaders = createDefaultPostResourceRequestResponse().header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .accept(MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML) + .acceptCharset(StandardCharsets.UTF_8) + .ifNoneMatch("*") + .ifModifiedSince(ZonedDateTime.now()); + + // response assertions + StepVerifier.create(retrieveResponse(headersSpecInserterStringWithHeaders)) + .expectNext("processed-bodyValue") + .verifyComplete(); + } + + @Test + public void givenDifferentResponseSpecifications_whenUsed_thenObtainExpectedResponse() { + ResponseSpec responseSpecPostString = createDefaultPostResourceRequestResponse().retrieve(); + Mono responsePostString = responseSpecPostString.bodyToMono(String.class); + Mono responsePostString2 = createDefaultPostResourceRequestResponse().exchangeToMono(response -> { + if (response.statusCode() + .equals(HttpStatus.OK)) { + return response.bodyToMono(String.class); + } else if (response.statusCode() + .is4xxClientError()) { + return Mono.just("Error response"); + } else { + return response.createException() + .flatMap(Mono::error); + } + }); + Mono responsePostNoBody = createDefaultPostResourceRequest().exchangeToMono(response -> { + if (response.statusCode() + .equals(HttpStatus.OK)) { + return response.bodyToMono(String.class); + } else if (response.statusCode() + .is4xxClientError()) { + return Mono.just("Error response"); + } else { + return response.createException() + .flatMap(Mono::error); + } + }); + Mono> responseGet = createDefaultClient().get() + .uri("/resource") + .retrieve() + .bodyToMono(MAP_RESPONSE_REF); + + // response assertions + StepVerifier.create(responsePostString) + .expectNext("processed-bodyValue") + .verifyComplete(); + StepVerifier.create(responsePostString2) + .expectNext("processed-bodyValue") + .verifyComplete(); + StepVerifier.create(responsePostNoBody) + .expectNext("Error response") + .verifyComplete(); + StepVerifier.create(responseGet) + .expectNextMatches(nextMap -> nextMap.get("field") + .equals("value")) + .verifyComplete(); + } + + @Test + public void givenWebClientWithTimeoutConfigurations_whenRequestUsingWronglyConfiguredPublisher_thenObtainTimeout() { + HttpClient httpClient = HttpClient.create() + .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000) + .responseTimeout(Duration.ofMillis(1000)) + .doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(1000, TimeUnit.MILLISECONDS)) + .addHandlerLast(new WriteTimeoutHandler(1000, TimeUnit.MILLISECONDS))); + + WebClient timeoutClient = WebClient.builder() + .baseUrl("http://localhost:" + port) + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .build(); + + RequestHeadersSpec neverendingMonoBodyRequest = timeoutClient.post() + .uri("/resource") + .body(Mono.never(), String.class); + + StepVerifier.create(neverendingMonoBodyRequest.retrieve() + .bodyToMono(String.class)) + .expectErrorMatches(ex -> WebClientRequestException.class.isAssignableFrom(ex.getClass()) && ReadTimeoutException.class.isAssignableFrom(ex.getCause() + .getClass())) + .verify(); + } + + // helper methods to create default instances + private WebClient createDefaultClient() { + return WebClient.create("http://localhost:" + port); + } + + private RequestBodyUriSpec createDefaultPostRequest() { + return createDefaultClient().post(); + } + + private RequestBodySpec createDefaultPostResourceRequest() { + return createDefaultPostRequest().uri("/resource"); + } + + private RequestHeadersSpec createDefaultPostResourceRequestResponse() { + return createDefaultPostResourceRequest().bodyValue(BODY_VALUE); + } + + // helper methods to retrieve a response based on different steps of the process (specs) + private Mono retrieveResponse(WebClient client) { + return client.post() + .uri("/resource") + .bodyValue(BODY_VALUE) + .retrieve() + .bodyToMono(String.class); + } + + private Mono retrieveResponse(RequestBodyUriSpec spec) { + return spec.uri("/resource") + .bodyValue(BODY_VALUE) + .retrieve() + .bodyToMono(String.class); + } + + private Mono> retrieveGetResponse(RequestHeadersUriSpec spec) { + return spec.uri("/resource") + .retrieve() + .bodyToMono(MAP_RESPONSE_REF); + } + + private Mono retrieveResponse(RequestBodySpec spec) { + return spec.bodyValue(BODY_VALUE) + .retrieve() + .bodyToMono(String.class); + } + + private Mono retrieveResponse(RequestHeadersSpec spec) { + return spec.retrieve() + .bodyToMono(String.class); + } +} diff --git a/spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java b/spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java index 2e37f2ffbd..07a4c81c91 100644 --- a/spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java +++ b/spring-5-reactive/src/test/java/com/baeldung/web/client/WebTestClientIntegrationTest.java @@ -1,11 +1,11 @@ package com.baeldung.web.client; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.context.ApplicationContext; import org.springframework.security.test.context.support.WithMockUser; -import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.web.reactive.function.server.RequestPredicates; import org.springframework.web.reactive.function.server.RouterFunction; @@ -13,18 +13,23 @@ import org.springframework.web.reactive.function.server.RouterFunctions; import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.server.WebHandler; -import com.baeldung.reactive.Spring5ReactiveApplication; +import com.baeldung.web.reactive.client.WebClientApplication; +import com.baeldung.web.reactive.client.WebClientController; import reactor.core.publisher.Mono; -@RunWith(SpringRunner.class) -@SpringBootTest(classes = Spring5ReactiveApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@WithMockUser +@SpringBootTest(classes = WebClientApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class WebTestClientIntegrationTest { @LocalServerPort private int port; + @Autowired + private ApplicationContext context; + + @Autowired + private WebClientController controller; + private final RouterFunction ROUTER_FUNCTION = RouterFunctions.route(RequestPredicates.GET("/resource"), request -> ServerResponse.ok() .build()); private final WebHandler WEB_HANDLER = exchange -> Mono.empty(); @@ -49,6 +54,7 @@ public class WebTestClientIntegrationTest { } @Test + @WithMockUser public void testWebTestClientWithServerURL() { WebTestClient.bindToServer() .baseUrl("http://localhost:" + port) @@ -58,7 +64,39 @@ public class WebTestClientIntegrationTest { .exchange() .expectStatus() .isOk() - .expectBody(); + .expectBody() + .jsonPath("field") + .isEqualTo("value"); + ; + } + + @Test + @WithMockUser + public void testWebTestClientWithApplicationContext() { + WebTestClient.bindToApplicationContext(context) + .build() + .get() + .uri("/resource") + .exchange() + .expectStatus() + .isOk() + .expectBody() + .jsonPath("field") + .isEqualTo("value"); + } + + @Test + public void testWebTestClientWithController() { + WebTestClient.bindToController(controller) + .build() + .get() + .uri("/resource") + .exchange() + .expectStatus() + .isOk() + .expectBody() + .jsonPath("field") + .isEqualTo("value"); } } diff --git a/spring-5-webflux/pom.xml b/spring-5-webflux/pom.xml index 292e4d7ad9..48b5b823fb 100644 --- a/spring-5-webflux/pom.xml +++ b/spring-5-webflux/pom.xml @@ -64,4 +64,8 @@ + + 2.3.3.RELEASE + + diff --git a/spring-5/README.md b/spring-5/README.md index d50f9c7544..2ddd9fa94f 100644 --- a/spring-5/README.md +++ b/spring-5/README.md @@ -2,18 +2,14 @@ This module contains articles about Spring 5 -### The Course -The "REST With Spring" Classes: http://bit.ly/restwithspring - ### Relevant Articles -- [Concurrent Test Execution in Spring 5](https://www.baeldung.com/spring-5-concurrent-tests) - [Spring 5 Functional Bean Registration](https://www.baeldung.com/spring-5-functional-beans) - [The SpringJUnitConfig and SpringJUnitWebConfig Annotations in Spring 5](https://www.baeldung.com/spring-5-junit-config) -- [Spring 5 Testing with @EnabledIf Annotation](https://www.baeldung.com/spring-5-enabledIf) - [Introduction to Spring REST Docs](https://www.baeldung.com/spring-rest-docs) - [Spring ResponseStatusException](https://www.baeldung.com/spring-response-status-exception) - [Spring Assert Statements](https://www.baeldung.com/spring-assert) -- [Configuring a Hikari Connection Pool with Spring Boot](https://www.baeldung.com/spring-boot-hikari) - [Difference between \ vs \](https://www.baeldung.com/spring-contextannotation-contextcomponentscan) - [Finding the Spring Version](https://www.baeldung.com/spring-find-version) +- [Spring 5 Testing with @EnabledIf Annotation](https://www.baeldung.com/spring-5-enabledIf) +- [Configuring a Hikari Connection Pool with Spring Boot](https://www.baeldung.com/spring-boot-hikari) diff --git a/spring-5/pom.xml b/spring-5/pom.xml index eadfb5e512..e368bcacba 100644 --- a/spring-5/pom.xml +++ b/spring-5/pom.xml @@ -133,18 +133,7 @@ - - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - - methods - true - - + diff --git a/spring-5/src/test/java/com/baeldung/README.md b/spring-5/src/test/java/com/baeldung/README.md new file mode 100644 index 0000000000..0ff61914d5 --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Concurrent Test Execution in Spring 5](https://www.baeldung.com/spring-5-concurrent-tests) diff --git a/spring-aop/README.md b/spring-aop/README.md index 91cccbd114..c92e132d1e 100644 --- a/spring-aop/README.md +++ b/spring-aop/README.md @@ -11,3 +11,4 @@ This module contains articles about Spring aspect oriented programming (AOP) - [Introduction to Pointcut Expressions in Spring](https://www.baeldung.com/spring-aop-pointcut-tutorial) - [Introduction to Advice Types in Spring](https://www.baeldung.com/spring-aop-advice-tutorial) - [When Does Java Throw UndeclaredThrowableException?](https://www.baeldung.com/java-undeclaredthrowableexception) +- [Get Advised Method Info in Spring AOP](https://www.baeldung.com/spring-aop-get-advised-method-info) diff --git a/spring-aop/src/main/java/com/baeldung/method/info/Account.java b/spring-aop/src/main/java/com/baeldung/method/info/Account.java new file mode 100644 index 0000000000..646e403f1e --- /dev/null +++ b/spring-aop/src/main/java/com/baeldung/method/info/Account.java @@ -0,0 +1,28 @@ +package com.baeldung.method.info; + +public class Account { + + private String accountNumber; + private double balance; + + public String getAccountNumber() { + return accountNumber; + } + + public void setAccountNumber(String accountNumber) { + this.accountNumber = accountNumber; + } + + public double getBalance() { + return balance; + } + + public void setBalance(double balance) { + this.balance = balance; + } + + @Override + public String toString() { + return "Account{" + "accountNumber='" + accountNumber + '\'' + ", balance=" + balance + '}'; + } +} diff --git a/spring-aop/src/main/java/com/baeldung/method/info/AccountOperation.java b/spring-aop/src/main/java/com/baeldung/method/info/AccountOperation.java new file mode 100644 index 0000000000..74bc60a6db --- /dev/null +++ b/spring-aop/src/main/java/com/baeldung/method/info/AccountOperation.java @@ -0,0 +1,12 @@ +package com.baeldung.method.info; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface AccountOperation { + String operation(); +} diff --git a/spring-aop/src/main/java/com/baeldung/method/info/BankAccountAspect.java b/spring-aop/src/main/java/com/baeldung/method/info/BankAccountAspect.java new file mode 100644 index 0000000000..f743758cd7 --- /dev/null +++ b/spring-aop/src/main/java/com/baeldung/method/info/BankAccountAspect.java @@ -0,0 +1,55 @@ +package com.baeldung.method.info; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; + +@Aspect +@Component +public class BankAccountAspect { + + @Before(value = "@annotation(com.baeldung.method.info.AccountOperation)") + public void getAccountOperationInfo(JoinPoint joinPoint) { + + // Method Information + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + + System.out.println("full method description: " + signature.getMethod()); + + System.out.println("method name: " + signature.getMethod().getName()); + + System.out.println("declaring type: " + signature.getDeclaringType()); + + // Method args + System.out.println("Method args names:"); + Arrays.stream(signature.getParameterNames()) + .forEach(s -> System.out.println("arg name: " + s)); + + System.out.println("Method args types:"); + Arrays.stream(signature.getParameterTypes()) + .forEach(s -> System.out.println("arg type: " + s)); + + System.out.println("Method args values:"); + Arrays.stream(joinPoint.getArgs()) + .forEach(o -> System.out.println("arg value: " + o.toString())); + + // Additional Information + System.out.println("returning type: " + signature.getReturnType()); + System.out.println("method modifier: " + Modifier.toString(signature.getModifiers())); + Arrays.stream(signature.getExceptionTypes()) + .forEach(aClass -> System.out.println("exception type: " + aClass)); + + // Method annotation + Method method = signature.getMethod(); + AccountOperation accountOperation = method.getAnnotation(AccountOperation.class); + System.out.println("Account operation annotation: " + accountOperation); + System.out.println("Account operation value: " + accountOperation.operation()); + + } +} diff --git a/spring-aop/src/main/java/com/baeldung/method/info/BankAccountService.java b/spring-aop/src/main/java/com/baeldung/method/info/BankAccountService.java new file mode 100644 index 0000000000..6ebab37d9e --- /dev/null +++ b/spring-aop/src/main/java/com/baeldung/method/info/BankAccountService.java @@ -0,0 +1,29 @@ +package com.baeldung.method.info; + +import org.apache.commons.lang3.RandomUtils; +import org.springframework.stereotype.Component; + +@Component +public class BankAccountService { + + @AccountOperation(operation = "deposit") + public void deposit(Account account, Double amount) { + account.setBalance(account.getBalance() + amount); + } + + @AccountOperation(operation = "withdraw") + public void withdraw(Account account, Double amount) throws WithdrawLimitException { + + if (amount > 500.0) { + throw new WithdrawLimitException("Withdraw limit exceeded."); + } + + account.setBalance(account.getBalance() - amount); + + } + + public double getBalance() { + return RandomUtils.nextDouble(); + } + +} diff --git a/spring-aop/src/main/java/com/baeldung/method/info/WithdrawLimitException.java b/spring-aop/src/main/java/com/baeldung/method/info/WithdrawLimitException.java new file mode 100644 index 0000000000..b29a27c94f --- /dev/null +++ b/spring-aop/src/main/java/com/baeldung/method/info/WithdrawLimitException.java @@ -0,0 +1,7 @@ +package com.baeldung.method.info; + +public class WithdrawLimitException extends RuntimeException { + public WithdrawLimitException(String message) { + super(message); + } +} diff --git a/spring-aop/src/test/java/com/baeldung/method/info/BankAccountServiceIntegrationTest.java b/spring-aop/src/test/java/com/baeldung/method/info/BankAccountServiceIntegrationTest.java new file mode 100644 index 0000000000..b1ba97654e --- /dev/null +++ b/spring-aop/src/test/java/com/baeldung/method/info/BankAccountServiceIntegrationTest.java @@ -0,0 +1,49 @@ +package com.baeldung.method.info; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +@SpringBootTest +class BankAccountServiceIntegrationTest { + + private Account account; + + @BeforeEach + public void setup() { + account = new Account(); + account.setAccountNumber("12345"); + account.setBalance(2000.0); + } + + @Autowired + BankAccountService bankAccountService; + + @Test + void withdraw() { + bankAccountService.withdraw(account, 500.0); + assertTrue(account.getBalance() == 1500.0); + } + + @Test + void withdrawWhenLimitReached() { + Assertions.assertThatExceptionOfType(WithdrawLimitException.class) + .isThrownBy(() -> bankAccountService.withdraw(account, 600.0)); + assertTrue(account.getBalance() == 2000.0); + } + + @Test + void deposit() { + bankAccountService.deposit(account, 500.0); + assertTrue(account.getBalance() == 2500.0); + } + + @Test + void getBalance() { + bankAccountService.getBalance(); + } +} diff --git a/spring-apache-camel/README.md b/spring-apache-camel/README.md index e89eb4fe6c..6a16e1da05 100644 --- a/spring-apache-camel/README.md +++ b/spring-apache-camel/README.md @@ -9,6 +9,7 @@ This module contains articles about Spring with Apache Camel - [Introduction To Apache Camel](http://www.baeldung.com/apache-camel-intro) - [Integration Patterns With Apache Camel](http://www.baeldung.com/camel-integration-patterns) - [Using Apache Camel with Spring](http://www.baeldung.com/spring-apache-camel-tutorial) +- [Unmarshalling a JSON Array Using camel-jackson](https://www.baeldung.com/java-camel-jackson-json-array) ### Framework Versions: @@ -23,4 +24,4 @@ To build this application execute: To run this application you can either run our main class App from your IDE or you can execute following maven command: -`mvn exec:java -Dexec.mainClass="com.baeldung.camel.main.App"` \ No newline at end of file +`mvn exec:java -Dexec.mainClass="com.baeldung.camel.main.App"` diff --git a/spring-apache-camel/pom.xml b/spring-apache-camel/pom.xml index 2d0d632546..9c7cc14381 100644 --- a/spring-apache-camel/pom.xml +++ b/spring-apache-camel/pom.xml @@ -47,6 +47,17 @@ camel-spring-javaconfig ${env.camel.version} + + org.apache.camel + camel-jackson + ${env.camel.version} + + + org.apache.camel + camel-test + ${env.camel.version} + test + diff --git a/spring-apache-camel/src/main/java/com/baeldung/camel/jackson/Fruit.java b/spring-apache-camel/src/main/java/com/baeldung/camel/jackson/Fruit.java new file mode 100644 index 0000000000..1932131ddd --- /dev/null +++ b/spring-apache-camel/src/main/java/com/baeldung/camel/jackson/Fruit.java @@ -0,0 +1,24 @@ +package com.baeldung.camel.jackson; + +public class Fruit { + + private String name; + private int id; + + 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; + } + +} diff --git a/spring-apache-camel/src/main/java/com/baeldung/camel/jackson/FruitList.java b/spring-apache-camel/src/main/java/com/baeldung/camel/jackson/FruitList.java new file mode 100644 index 0000000000..02f2b6feb0 --- /dev/null +++ b/spring-apache-camel/src/main/java/com/baeldung/camel/jackson/FruitList.java @@ -0,0 +1,17 @@ +package com.baeldung.camel.jackson; + +import java.util.List; + +public class FruitList { + + private List fruits; + + public List getFruits() { + return fruits; + } + + public void setFruits(List fruits) { + this.fruits = fruits; + } + +} diff --git a/spring-apache-camel/src/test/java/com/baeldung/camel/jackson/FruitArrayJacksonUnmarshalUnitTest.java b/spring-apache-camel/src/test/java/com/baeldung/camel/jackson/FruitArrayJacksonUnmarshalUnitTest.java new file mode 100644 index 0000000000..4810d7370e --- /dev/null +++ b/spring-apache-camel/src/test/java/com/baeldung/camel/jackson/FruitArrayJacksonUnmarshalUnitTest.java @@ -0,0 +1,60 @@ +package com.baeldung.camel.jackson; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.jackson.ListJacksonDataFormat; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Test; + +public class FruitArrayJacksonUnmarshalUnitTest extends CamelTestSupport { + + @Test + public void givenJsonFruitArray_whenUnmarshalled_thenSuccess() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:marshalledObject"); + mock.expectedMessageCount(1); + mock.message(0).body().isInstanceOf(List.class); + + String json = readJsonFromFile("/json/fruit-array.json"); + template.sendBody("direct:jsonInput", json); + assertMockEndpointsSatisfied(); + + @SuppressWarnings("unchecked") + List fruitList = mock.getReceivedExchanges().get(0).getIn().getBody(List.class); + assertNotNull("Fruit lists should not be null", fruitList); + + assertEquals("There should be two fruits", 2, fruitList.size()); + + Fruit fruit = fruitList.get(0); + assertEquals("Fruit name", "Banana", fruit.getName()); + assertEquals("Fruit id", 100, fruit.getId()); + + fruit = fruitList.get(1); + assertEquals("Fruit name", "Apple", fruit.getName()); + assertEquals("Fruit id", 101, fruit.getId()); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + + from("direct:jsonInput").unmarshal(new ListJacksonDataFormat(Fruit.class)) + .to("mock:marshalledObject"); + } + }; + } + + private String readJsonFromFile(String path) throws URISyntaxException, IOException { + URL resource = FruitArrayJacksonUnmarshalUnitTest.class.getResource(path); + return new String(Files.readAllBytes(Paths.get(resource.toURI()))); + } + +} diff --git a/spring-apache-camel/src/test/java/com/baeldung/camel/jackson/FruitListJacksonUnmarshalUnitTest.java b/spring-apache-camel/src/test/java/com/baeldung/camel/jackson/FruitListJacksonUnmarshalUnitTest.java new file mode 100644 index 0000000000..b5647f02f9 --- /dev/null +++ b/spring-apache-camel/src/test/java/com/baeldung/camel/jackson/FruitListJacksonUnmarshalUnitTest.java @@ -0,0 +1,59 @@ +package com.baeldung.camel.jackson; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; + +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.component.jackson.JacksonDataFormat; +import org.apache.camel.component.mock.MockEndpoint; +import org.apache.camel.test.junit4.CamelTestSupport; +import org.junit.Test; + +public class FruitListJacksonUnmarshalUnitTest extends CamelTestSupport { + + @Test + public void givenJsonFruitList_whenUnmarshalled_thenSuccess() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:marshalledObject"); + mock.expectedMessageCount(1); + mock.message(0).body().isInstanceOf(FruitList.class); + + String json = readJsonFromFile("/json/fruit-list.json"); + template.sendBody("direct:jsonInput", json); + assertMockEndpointsSatisfied(); + + FruitList fruitList = mock.getReceivedExchanges().get(0).getIn().getBody(FruitList.class); + assertNotNull("Fruit lists should not be null", fruitList); + + List fruits = fruitList.getFruits(); + assertEquals("There should be two fruits", 2, fruits.size()); + + Fruit fruit = fruits.get(0); + assertEquals("Fruit name", "Banana", fruit.getName()); + assertEquals("Fruit id", 100, fruit.getId()); + + fruit = fruits.get(1); + assertEquals("Fruit name", "Apple", fruit.getName()); + assertEquals("Fruit id", 101, fruit.getId()); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + return new RouteBuilder() { + @Override + public void configure() throws Exception { + from("direct:jsonInput").unmarshal(new JacksonDataFormat(FruitList.class)) + .to("mock:marshalledObject"); + } + }; + } + + private String readJsonFromFile(String path) throws URISyntaxException, IOException { + URL resource = FruitListJacksonUnmarshalUnitTest.class.getResource(path); + return new String(Files.readAllBytes(Paths.get(resource.toURI()))); + } + +} diff --git a/spring-apache-camel/src/test/resources/json/fruit-array.json b/spring-apache-camel/src/test/resources/json/fruit-array.json new file mode 100644 index 0000000000..0bd917c53f --- /dev/null +++ b/spring-apache-camel/src/test/resources/json/fruit-array.json @@ -0,0 +1,10 @@ +[ + { + "id": 100, + "name": "Banana" + }, + { + "id": 101, + "name": "Apple" + } +] \ No newline at end of file diff --git a/spring-apache-camel/src/test/resources/json/fruit-list.json b/spring-apache-camel/src/test/resources/json/fruit-list.json new file mode 100644 index 0000000000..357e08f7d5 --- /dev/null +++ b/spring-apache-camel/src/test/resources/json/fruit-list.json @@ -0,0 +1,12 @@ +{ + "fruits": [ + { + "id": 100, + "name": "Banana" + }, + { + "id": 101, + "name": "Apple" + } + ] +} \ No newline at end of file diff --git a/spring-batch-2/README.md b/spring-batch-2/README.md new file mode 100644 index 0000000000..08bf1933db --- /dev/null +++ b/spring-batch-2/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Spring Boot With Spring Batch](https://www.baeldung.com/spring-boot-spring-batch) diff --git a/spring-batch-2/pom.xml b/spring-batch-2/pom.xml new file mode 100644 index 0000000000..183ad610f3 --- /dev/null +++ b/spring-batch-2/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + spring-batch-2 + 0.1-SNAPSHOT + spring-batch-2 + jar + http://maven.apache.org + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-batch + + + org.hsqldb + hsqldb + ${hsqldb.version} + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + org.springframework.batch + spring-batch-test + ${spring.batch.version} + test + + + + + 4.3.0 + 2.5.1 + + + diff --git a/spring-batch-2/src/main/java/com/baeldung/batch/BatchConfiguration.java b/spring-batch-2/src/main/java/com/baeldung/batch/BatchConfiguration.java new file mode 100644 index 0000000000..0c053dd86c --- /dev/null +++ b/spring-batch-2/src/main/java/com/baeldung/batch/BatchConfiguration.java @@ -0,0 +1,81 @@ +package com.baeldung.batch; + +import javax.sql.DataSource; + +import org.springframework.batch.core.Job; +import org.springframework.batch.core.Step; +import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing; +import org.springframework.batch.core.configuration.annotation.JobBuilderFactory; +import org.springframework.batch.core.configuration.annotation.StepBuilderFactory; +import org.springframework.batch.core.launch.support.RunIdIncrementer; +import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider; +import org.springframework.batch.item.database.JdbcBatchItemWriter; +import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder; +import org.springframework.batch.item.file.FlatFileItemReader; +import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; +import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.ClassPathResource; + +@Configuration +@EnableBatchProcessing +public class BatchConfiguration { + + @Autowired + public JobBuilderFactory jobBuilderFactory; + + @Autowired + public StepBuilderFactory stepBuilderFactory; + + @Value("${file.input}") + private String fileInput; + + @Bean + public FlatFileItemReader reader() { + return new FlatFileItemReaderBuilder().name("coffeeItemReader") + .resource(new ClassPathResource(fileInput)) + .delimited() + .names(new String[] { "brand", "origin", "characteristics" }) + .fieldSetMapper(new BeanWrapperFieldSetMapper() {{ + setTargetType(Coffee.class); + }}) + .build(); + } + + @Bean + public CoffeeItemProcessor processor() { + return new CoffeeItemProcessor(); + } + + @Bean + public JdbcBatchItemWriter writer(DataSource dataSource) { + return new JdbcBatchItemWriterBuilder().itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>()) + .sql("INSERT INTO coffee (brand, origin, characteristics) VALUES (:brand, :origin, :characteristics)") + .dataSource(dataSource) + .build(); + } + + @Bean + public Job importUserJob(JobCompletionNotificationListener listener, Step step1) { + return jobBuilderFactory.get("importUserJob") + .incrementer(new RunIdIncrementer()) + .listener(listener) + .flow(step1) + .end() + .build(); + } + + @Bean + public Step step1(JdbcBatchItemWriter writer) { + return stepBuilderFactory.get("step1") + . chunk(10) + .reader(reader()) + .processor(processor()) + .writer(writer) + .build(); + } + +} diff --git a/spring-batch-2/src/main/java/com/baeldung/batch/Coffee.java b/spring-batch-2/src/main/java/com/baeldung/batch/Coffee.java new file mode 100644 index 0000000000..4dfcd9959c --- /dev/null +++ b/spring-batch-2/src/main/java/com/baeldung/batch/Coffee.java @@ -0,0 +1,47 @@ +package com.baeldung.batch; + +public class Coffee { + + private String brand; + private String origin; + private String characteristics; + + public Coffee() { + } + + public Coffee(String brand, String origin, String characteristics) { + this.brand = brand; + this.origin = origin; + this.characteristics = characteristics; + } + + public String getBrand() { + return brand; + } + + public void setBrand(String brand) { + this.brand = brand; + } + + public String getOrigin() { + return origin; + } + + public void setOrigin(String origin) { + this.origin = origin; + } + + public String getCharacteristics() { + return characteristics; + } + + public void setCharacteristics(String characteristics) { + this.characteristics = characteristics; + } + + @Override + public String toString() { + return "Coffee [brand=" + getBrand() + ", origin=" + getOrigin() + ", characteristics=" + getCharacteristics() + "]"; + } + +} diff --git a/spring-batch-2/src/main/java/com/baeldung/batch/CoffeeItemProcessor.java b/spring-batch-2/src/main/java/com/baeldung/batch/CoffeeItemProcessor.java new file mode 100644 index 0000000000..b154b80453 --- /dev/null +++ b/spring-batch-2/src/main/java/com/baeldung/batch/CoffeeItemProcessor.java @@ -0,0 +1,24 @@ +package com.baeldung.batch; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.springframework.batch.item.ItemProcessor; + +public class CoffeeItemProcessor implements ItemProcessor { + + private static final Logger LOGGER = LoggerFactory.getLogger(CoffeeItemProcessor.class); + + @Override + public Coffee process(final Coffee coffee) throws Exception { + String brand = coffee.getBrand().toUpperCase(); + String origin = coffee.getOrigin().toUpperCase(); + String chracteristics = coffee.getCharacteristics().toUpperCase(); + + Coffee transformedCoffee = new Coffee(brand, origin, chracteristics); + LOGGER.info("Converting ( {} ) into ( {} )", coffee, transformedCoffee); + + return transformedCoffee; + } + +} diff --git a/spring-batch-2/src/main/java/com/baeldung/batch/JobCompletionNotificationListener.java b/spring-batch-2/src/main/java/com/baeldung/batch/JobCompletionNotificationListener.java new file mode 100644 index 0000000000..ca1de40aea --- /dev/null +++ b/spring-batch-2/src/main/java/com/baeldung/batch/JobCompletionNotificationListener.java @@ -0,0 +1,34 @@ +package com.baeldung.batch; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.batch.core.BatchStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.listener.JobExecutionListenerSupport; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Component; + +@Component +public class JobCompletionNotificationListener extends JobExecutionListenerSupport { + + private static final Logger LOGGER = LoggerFactory.getLogger(JobCompletionNotificationListener.class); + + private final JdbcTemplate jdbcTemplate; + + @Autowired + public JobCompletionNotificationListener(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @Override + public void afterJob(JobExecution jobExecution) { + if (jobExecution.getStatus() == BatchStatus.COMPLETED) { + LOGGER.info("!!! JOB FINISHED! Time to verify the results"); + + String query = "SELECT brand, origin, characteristics FROM coffee"; + jdbcTemplate.query(query, (rs, row) -> new Coffee(rs.getString(1), rs.getString(2), rs.getString(3))) + .forEach(coffee -> LOGGER.info("Found < {} > in the database.", coffee)); + } + } +} diff --git a/spring-batch-2/src/main/java/com/baeldung/batch/SpringBootBatchProcessingApplication.java b/spring-batch-2/src/main/java/com/baeldung/batch/SpringBootBatchProcessingApplication.java new file mode 100644 index 0000000000..7682124b8d --- /dev/null +++ b/spring-batch-2/src/main/java/com/baeldung/batch/SpringBootBatchProcessingApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.batch; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBootBatchProcessingApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBootBatchProcessingApplication.class, args); + } + +} diff --git a/spring-batch-2/src/main/resources/application.properties b/spring-batch-2/src/main/resources/application.properties new file mode 100644 index 0000000000..0b8c56d3f8 --- /dev/null +++ b/spring-batch-2/src/main/resources/application.properties @@ -0,0 +1 @@ +file.input=coffee-list.csv \ No newline at end of file diff --git a/spring-batch-2/src/main/resources/coffee-list.csv b/spring-batch-2/src/main/resources/coffee-list.csv new file mode 100644 index 0000000000..6ceef00556 --- /dev/null +++ b/spring-batch-2/src/main/resources/coffee-list.csv @@ -0,0 +1,3 @@ +Blue Mountain,Jamaica,Fruity +Lavazza,Colombia,Strong +Folgers,America,Smokey \ No newline at end of file diff --git a/spring-5-security-cognito/src/main/resources/logback.xml b/spring-batch-2/src/main/resources/logback.xml similarity index 100% rename from spring-5-security-cognito/src/main/resources/logback.xml rename to spring-batch-2/src/main/resources/logback.xml diff --git a/spring-batch-2/src/main/resources/schema-all.sql b/spring-batch-2/src/main/resources/schema-all.sql new file mode 100644 index 0000000000..9f698f7d81 --- /dev/null +++ b/spring-batch-2/src/main/resources/schema-all.sql @@ -0,0 +1,8 @@ +DROP TABLE coffee IF EXISTS; + +CREATE TABLE coffee ( + coffee_id BIGINT IDENTITY NOT NULL PRIMARY KEY, + brand VARCHAR(20), + origin VARCHAR(20), + characteristics VARCHAR(30) +); \ No newline at end of file diff --git a/spring-batch-2/src/test/java/com/baeldung/batch/SpringBootBatchIntegrationTest.java b/spring-batch-2/src/test/java/com/baeldung/batch/SpringBootBatchIntegrationTest.java new file mode 100644 index 0000000000..ba2b8a6a13 --- /dev/null +++ b/spring-batch-2/src/test/java/com/baeldung/batch/SpringBootBatchIntegrationTest.java @@ -0,0 +1,49 @@ +package com.baeldung.batch; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.batch.core.ExitStatus; +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.test.JobLauncherTestUtils; +import org.springframework.batch.test.JobRepositoryTestUtils; +import org.springframework.batch.test.context.SpringBatchTest; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.PropertySource; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; + +@SpringBatchTest +@SpringBootTest +@DirtiesContext +@PropertySource("classpath:application.properties") +@RunWith(SpringRunner.class) +public class SpringBootBatchIntegrationTest { + + @Autowired + private JobLauncherTestUtils jobLauncherTestUtils; + + @Autowired + private JobRepositoryTestUtils jobRepositoryTestUtils; + + @After + public void cleanUp() { + jobRepositoryTestUtils.removeJobExecutions(); + } + + @Test + public void givenCoffeeList_whenJobExecuted_thenSuccess() throws Exception { + JobExecution jobExecution = jobLauncherTestUtils.launchJob(); + JobInstance jobInstance = jobExecution.getJobInstance(); + ExitStatus jobExitStatus = jobExecution.getExitStatus(); + + assertThat(jobInstance.getJobName(), is("importUserJob")); + assertThat(jobExitStatus.getExitCode(), is("COMPLETED")); + } + +} diff --git a/spring-batch/pom.xml b/spring-batch/pom.xml index 9edf8ad3be..75ec0d4877 100644 --- a/spring-batch/pom.xml +++ b/spring-batch/pom.xml @@ -95,8 +95,8 @@ - 5.2.0.RELEASE - 4.2.0.RELEASE + 5.3.0 + 4.3.0 3.15.1 4.1 2.3.1 diff --git a/spring-batch/repository.sqlite b/spring-batch/repository.sqlite index 2b549352ec..a2b87ffa00 100644 Binary files a/spring-batch/repository.sqlite and b/spring-batch/repository.sqlite differ diff --git a/spring-batch/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java b/spring-batch/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java index 4de3e0a4b6..cff4e96c89 100644 --- a/spring-batch/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java +++ b/spring-batch/src/main/java/com/baeldung/batchscheduler/SpringBatchScheduler.java @@ -1,12 +1,5 @@ package com.baeldung.batchscheduler; -import java.util.Date; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; import com.baeldung.batchscheduler.model.Book; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -20,7 +13,7 @@ import org.springframework.batch.core.configuration.annotation.StepBuilderFactor import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.launch.support.SimpleJobLauncher; import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; import org.springframework.batch.item.ItemWriter; import org.springframework.batch.item.file.FlatFileItemReader; import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder; @@ -30,12 +23,22 @@ import org.springframework.beans.factory.annotation.Autowired; 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.scheduling.TaskScheduler; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.support.ScheduledMethodRunnable; +import javax.sql.DataSource; +import java.util.Date; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + @Configuration @EnableBatchProcessing @EnableScheduling @@ -122,9 +125,18 @@ public class SpringBatchScheduler { @Bean public JobRepository jobRepository() throws Exception { - MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean(); + JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); + factory.setDataSource(dataSource()); factory.setTransactionManager(new ResourcelessTransactionManager()); - return (JobRepository) factory.getObject(); + return factory.getObject(); + } + + @Bean + public DataSource dataSource() { + DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName("org.sqlite.JDBC"); + dataSource.setUrl("jdbc:sqlite:repository.sqlite"); + return dataSource; } @Bean diff --git a/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/ChunksConfig.java b/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/ChunksConfig.java index 57288fb312..c8b05848f9 100644 --- a/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/ChunksConfig.java +++ b/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/ChunksConfig.java @@ -12,7 +12,7 @@ import org.springframework.batch.core.configuration.annotation.StepBuilderFactor import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.launch.support.SimpleJobLauncher; import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; import org.springframework.batch.item.ItemProcessor; import org.springframework.batch.item.ItemReader; import org.springframework.batch.item.ItemWriter; @@ -21,8 +21,11 @@ import org.springframework.batch.test.JobLauncherTestUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.transaction.PlatformTransactionManager; +import javax.sql.DataSource; + @Configuration @EnableBatchProcessing public class ChunksConfig { @@ -38,9 +41,18 @@ public class ChunksConfig { @Bean public JobRepository jobRepository() throws Exception { - MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean(); + JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); + factory.setDataSource(dataSource()); factory.setTransactionManager(transactionManager()); - return (JobRepository) factory.getObject(); + return factory.getObject(); + } + + @Bean + public DataSource dataSource() { + DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName("org.sqlite.JDBC"); + dataSource.setUrl("jdbc:sqlite:repository.sqlite"); + return dataSource; } @Bean diff --git a/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/TaskletsConfig.java b/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/TaskletsConfig.java index e7157ac520..5f2f49928c 100644 --- a/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/TaskletsConfig.java +++ b/spring-batch/src/main/java/com/baeldung/taskletsvschunks/config/TaskletsConfig.java @@ -11,14 +11,17 @@ import org.springframework.batch.core.configuration.annotation.StepBuilderFactor import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.launch.support.SimpleJobLauncher; import org.springframework.batch.core.repository.JobRepository; -import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean; +import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean; import org.springframework.batch.support.transaction.ResourcelessTransactionManager; import org.springframework.batch.test.JobLauncherTestUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.transaction.PlatformTransactionManager; +import javax.sql.DataSource; + @Configuration @EnableBatchProcessing public class TaskletsConfig { @@ -34,9 +37,18 @@ public class TaskletsConfig { @Bean public JobRepository jobRepository() throws Exception { - MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean(); + JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean(); + factory.setDataSource(dataSource()); factory.setTransactionManager(transactionManager()); - return (JobRepository) factory.getObject(); + return factory.getObject(); + } + + @Bean + public DataSource dataSource() { + DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName("org.sqlite.JDBC"); + dataSource.setUrl("jdbc:sqlite:repository.sqlite"); + return dataSource; } @Bean diff --git a/spring-batch/src/test/java/com/baeldung/SpringContextTest.java b/spring-batch/src/test/java/com/baeldung/SpringContextTest.java deleted file mode 100644 index b82bb35daf..0000000000 --- a/spring-batch/src/test/java/com/baeldung/SpringContextTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung; - -import com.baeldung.batch.App; -import org.junit.Test; - -public class SpringContextTest { - - @Test - public void testMain() throws Exception { - App.main(null); - } -} diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index fa70a9f058..263d2af089 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -24,8 +24,10 @@ spring-boot-angular spring-boot-annotations spring-boot-artifacts + spring-boot-artifacts-2 spring-boot-autoconfiguration spring-boot-basic-customization + spring-boot-basic-customization-2 spring-boot-bootstrap spring-boot-client spring-boot-config-jpa-error @@ -48,7 +50,6 @@ spring-boot-libraries spring-boot-libraries-2 spring-boot-logging-log4j2 - spring-boot-kotlin spring-boot-mvc spring-boot-mvc-2 spring-boot-mvc-3 @@ -61,13 +62,16 @@ spring-boot-properties-3 spring-boot-property-exp spring-boot-runtime + spring-boot-runtime-2 spring-boot-security spring-boot-springdoc spring-boot-swagger + spring-boot-swagger-jwt spring-boot-testing spring-boot-vue spring-boot-xml spring-boot-actuator + spring-boot-data-2 @@ -113,6 +117,5 @@ 5.6.2 - 2.6 diff --git a/spring-boot-modules/spring-boot-actuator/pom.xml b/spring-boot-modules/spring-boot-actuator/pom.xml index 18da6d3a9a..a808b8cb1b 100644 --- a/spring-boot-modules/spring-boot-actuator/pom.xml +++ b/spring-boot-modules/spring-boot-actuator/pom.xml @@ -11,7 +11,7 @@ org.springframework.boot spring-boot-starter-parent - 2.3.0.RELEASE + 2.3.2.RELEASE diff --git a/spring-boot-modules/spring-boot-actuator/src/main/resources/application.properties b/spring-boot-modules/spring-boot-actuator/src/main/resources/application.properties index 00100d6d97..de7be417a8 100644 --- a/spring-boot-modules/spring-boot-actuator/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-actuator/src/main/resources/application.properties @@ -1,4 +1,6 @@ -management.health.probes.enabled=true +management.endpoint.health.probes.enabled=true +management.health.livenessState.enabled=true +management.health.readinessState.enabled=true management.endpoint.health.show-details=always management.endpoint.health.status.http-mapping.down=500 management.endpoint.health.status.http-mapping.out_of_service=503 @@ -8,4 +10,4 @@ management.endpoint.health.status.http-mapping.warning=500 info.app.name=Spring Sample Application info.app.description=This is my first spring boot application G1 info.app.version=1.0.0 -info.java-vendor = ${java.specification.vendor} \ No newline at end of file +info.java-vendor = ${java.specification.vendor} diff --git a/spring-boot-modules/spring-boot-admin/spring-boot-admin-client/src/test/java/org/baeldung/SpringContextTest.java b/spring-boot-modules/spring-boot-admin/spring-boot-admin-client/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-boot-modules/spring-boot-admin/spring-boot-admin-client/src/test/java/org/baeldung/SpringContextTest.java rename to spring-boot-modules/spring-boot-admin/spring-boot-admin-client/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-boot-modules/spring-boot-admin/spring-boot-admin-server/pom.xml b/spring-boot-modules/spring-boot-admin/spring-boot-admin-server/pom.xml index 4c1dcdef6b..558aed8b26 100644 --- a/spring-boot-modules/spring-boot-admin/spring-boot-admin-server/pom.xml +++ b/spring-boot-modules/spring-boot-admin/spring-boot-admin-server/pom.xml @@ -86,5 +86,6 @@ 2.2.2 1.5.7 2.0.4.RELEASE + 2.3.3.RELEASE diff --git a/spring-boot-modules/spring-boot-admin/spring-boot-admin-server/src/test/java/org/baeldung/SpringContextTest.java b/spring-boot-modules/spring-boot-admin/spring-boot-admin-server/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-boot-modules/spring-boot-admin/spring-boot-admin-server/src/test/java/org/baeldung/SpringContextTest.java rename to spring-boot-modules/spring-boot-admin/spring-boot-admin-server/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-boot-modules/spring-boot-angular/src/test/java/org/baeldung/SpringContextTest.java b/spring-boot-modules/spring-boot-angular/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-boot-modules/spring-boot-angular/src/test/java/org/baeldung/SpringContextTest.java rename to spring-boot-modules/spring-boot-angular/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-boot-modules/spring-boot-annotations/README.md b/spring-boot-modules/spring-boot-annotations/README.md index a721f28d55..1b2bca435c 100644 --- a/spring-boot-modules/spring-boot-annotations/README.md +++ b/spring-boot-modules/spring-boot-annotations/README.md @@ -9,3 +9,5 @@ This module contains articles about Spring Boot annotations - [Spring Web Annotations](https://www.baeldung.com/spring-mvc-annotations) - [Spring Core Annotations](https://www.baeldung.com/spring-core-annotations) - [Spring Bean Annotations](https://www.baeldung.com/spring-bean-annotations) +- [Difference Between @ComponentScan and @EnableAutoConfiguration in Spring Boot](https://www.baeldung.com/spring-componentscan-vs-enableautoconfiguration) +- [Where Should the Spring @Service Annotation Be Kept?](https://www.baeldung.com/spring-service-annotation-placement) diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/EmployeeApplication.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/EmployeeApplication.java new file mode 100644 index 0000000000..17c7af858b --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/EmployeeApplication.java @@ -0,0 +1,19 @@ +package com.baeldung.annotations; + +import com.baeldung.annotations.componentscanautoconfigure.teacher.Teacher; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.ComponentScan; + +@ComponentScan(basePackages = {"com.baeldung.annotations.componentscanautoconfigure.healthcare", + "com.baeldung.annotations.componentscanautoconfigure.employee"}, + basePackageClasses = Teacher.class) +@EnableAutoConfiguration(exclude = {JdbcTemplateAutoConfiguration.class}) +//@EnableAutoConfiguration(excludeName = {"org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration"}) +public class EmployeeApplication { + public static void main(String[] args) { + SpringApplication.run(EmployeeApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/employee/Employee.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/employee/Employee.java new file mode 100644 index 0000000000..9be3388046 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/employee/Employee.java @@ -0,0 +1,12 @@ +package com.baeldung.annotations.componentscanautoconfigure.employee; + +import org.springframework.stereotype.Component; + +@Component("employee") +public class Employee { + + @Override + public String toString() { + return "Employee" + this.hashCode(); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/employee/SeniorEmployee.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/employee/SeniorEmployee.java new file mode 100644 index 0000000000..242e84f887 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/employee/SeniorEmployee.java @@ -0,0 +1,12 @@ +package com.baeldung.annotations.componentscanautoconfigure.employee; + +import org.springframework.stereotype.Component; + +@Component +public class SeniorEmployee { + + @Override + public String toString() { + return "Senior Employee" + this.hashCode(); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/healthcare/Doctor.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/healthcare/Doctor.java new file mode 100644 index 0000000000..7e7e6cb03b --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/healthcare/Doctor.java @@ -0,0 +1,9 @@ +package com.baeldung.annotations.componentscanautoconfigure.healthcare; + +public class Doctor { + + @Override + public String toString() { + return "Doctor" + this.hashCode(); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/healthcare/Hospital.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/healthcare/Hospital.java new file mode 100644 index 0000000000..0711544060 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/healthcare/Hospital.java @@ -0,0 +1,13 @@ +package com.baeldung.annotations.componentscanautoconfigure.healthcare; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class Hospital { + + @Bean("doctor") + public Doctor getDoctor() { + return new Doctor(); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/student/Student.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/student/Student.java new file mode 100644 index 0000000000..56f2ac9830 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/student/Student.java @@ -0,0 +1,12 @@ +package com.baeldung.annotations.componentscanautoconfigure.student; + +import org.springframework.stereotype.Component; + +@Component("student") +public class Student { + + @Override + public String toString() { + return "Student" + this.hashCode(); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/teacher/Teacher.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/teacher/Teacher.java new file mode 100644 index 0000000000..e2c653204d --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/componentscanautoconfigure/teacher/Teacher.java @@ -0,0 +1,12 @@ +package com.baeldung.annotations.componentscanautoconfigure.teacher; + +import org.springframework.stereotype.Component; + +@Component("teacher") +public class Teacher { + + @Override + public String toString() { + return "Teacher" + this.hashCode(); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/AuthApplication.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/AuthApplication.java new file mode 100644 index 0000000000..fa5770b08e --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/AuthApplication.java @@ -0,0 +1,22 @@ +package com.baeldung.annotations.service; + +import com.baeldung.annotations.service.abstracts.AbstractAuthenticationService; +import com.baeldung.annotations.service.interfaces.AuthenticationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AuthApplication { + + @Autowired + private AuthenticationService inMemoryAuthService; + + @Autowired + private AbstractAuthenticationService ldapAuthService; + + public static void main(String[] args) { + SpringApplication.run(AuthApplication.class, args); + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/abstracts/AbstractAuthenticationService.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/abstracts/AbstractAuthenticationService.java new file mode 100644 index 0000000000..47fac229f7 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/abstracts/AbstractAuthenticationService.java @@ -0,0 +1,12 @@ +package com.baeldung.annotations.service.abstracts; + +import org.springframework.stereotype.Service; + +@Service +public abstract class AbstractAuthenticationService { + + public boolean authenticate(String username, String password) { + return false; + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/concretes/InMemoryAuthenticationService.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/concretes/InMemoryAuthenticationService.java new file mode 100644 index 0000000000..8f80cb8593 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/concretes/InMemoryAuthenticationService.java @@ -0,0 +1,14 @@ +package com.baeldung.annotations.service.concretes; + +import com.baeldung.annotations.service.interfaces.AuthenticationService; +import org.springframework.stereotype.Service; + +@Service +public class InMemoryAuthenticationService implements AuthenticationService { + + @Override + public boolean authenticate(String username, String password) { + return false; + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/concretes/LdapAuthenticationService.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/concretes/LdapAuthenticationService.java new file mode 100644 index 0000000000..af93ea13be --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/concretes/LdapAuthenticationService.java @@ -0,0 +1,14 @@ +package com.baeldung.annotations.service.concretes; + +import com.baeldung.annotations.service.abstracts.AbstractAuthenticationService; +import org.springframework.stereotype.Service; + +@Service +public class LdapAuthenticationService extends AbstractAuthenticationService { + + @Override + public boolean authenticate(String username, String password) { + return true; + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/interfaces/AuthenticationService.java b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/interfaces/AuthenticationService.java new file mode 100644 index 0000000000..0537343266 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/main/java/com/baeldung/annotations/service/interfaces/AuthenticationService.java @@ -0,0 +1,10 @@ +package com.baeldung.annotations.service.interfaces; + +import org.springframework.stereotype.Service; + +@Service +public interface AuthenticationService { + + boolean authenticate(String username, String password); + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/EmployeeApplicationUnitTest.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/EmployeeApplicationUnitTest.java new file mode 100644 index 0000000000..8dfc743f3d --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/EmployeeApplicationUnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.annotations; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertAll; + +public class EmployeeApplicationUnitTest { + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner() + .withUserConfiguration(EmployeeApplication.class); + + @Test + void whenApplicationContextRuns_thenContainAllDefinedBeans() { + contextRunner.run(context -> assertAll( + () -> assertTrue(context.containsBeanDefinition("employee")), + () -> assertTrue(context.containsBeanDefinition("seniorEmployee")), + () -> assertTrue(context.containsBeanDefinition("doctor")), + () -> assertTrue(context.containsBeanDefinition("hospital")), + () -> assertFalse(context.containsBeanDefinition("student")), + () -> assertTrue(context.containsBeanDefinition("teacher")))); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/AuthApplicationUnitTest.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/AuthApplicationUnitTest.java new file mode 100644 index 0000000000..ecbf1b38e5 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/AuthApplicationUnitTest.java @@ -0,0 +1,51 @@ +package com.baeldung.annotations.service; + +import com.baeldung.annotations.service.abstracts.AbstractAuthenticationService; +import com.baeldung.annotations.service.config.AbstractsAnnotatedTestConfiguration; +import com.baeldung.annotations.service.config.ConcreteClassesAnnotatedTestConfiguration; +import com.baeldung.annotations.service.config.InterfacesAnnotatedTestConfiguration; +import com.baeldung.annotations.service.interfaces.AuthenticationService; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.boot.test.context.runner.ApplicationContextRunner; + +public class AuthApplicationUnitTest { + + private final ApplicationContextRunner contextRunner = new ApplicationContextRunner(); + + @Test + void whenOnlyInterfacesAnnotated_noSuchBeanDefinitionExceptionThrown() { + contextRunner + .withUserConfiguration(InterfacesAnnotatedTestConfiguration.class) + .run(context -> { + Assertions.assertThrows(NoSuchBeanDefinitionException.class, () -> { + context.getBean(AuthenticationService.class); + }); + }); + } + + @Test + void whenOnlyAbstractClassesAnnotated_noSuchBeanDefinitionExceptionThrown() { + contextRunner + .withUserConfiguration(AbstractsAnnotatedTestConfiguration.class) + .run(context -> { + Assertions.assertThrows(NoSuchBeanDefinitionException.class, () -> { + context.getBean(AbstractAuthenticationService.class); + }); + }); + } + + @Test + void whenConcreteClassesAnnotated_noExceptionThrown() { + contextRunner + .withUserConfiguration(ConcreteClassesAnnotatedTestConfiguration.class) + .run(context -> { + AuthenticationService inMemoryAuthService = context.getBean(AuthenticationService.class); + AbstractAuthenticationService ldapAuthService = context.getBean(AbstractAuthenticationService.class); + + Assertions.assertNotNull(inMemoryAuthService); + Assertions.assertNotNull(ldapAuthService); + }); + } +} diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/AbstractsAnnotatedTestConfiguration.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/AbstractsAnnotatedTestConfiguration.java new file mode 100644 index 0000000000..4c52401a06 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/AbstractsAnnotatedTestConfiguration.java @@ -0,0 +1,10 @@ +package com.baeldung.annotations.service.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.ComponentScan; + +@TestConfiguration +@ComponentScan("com.baeldung.annotations.service.abstracts") +public class AbstractsAnnotatedTestConfiguration { + +} diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/ConcreteClassesAnnotatedTestConfiguration.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/ConcreteClassesAnnotatedTestConfiguration.java new file mode 100644 index 0000000000..baf7fb970c --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/ConcreteClassesAnnotatedTestConfiguration.java @@ -0,0 +1,10 @@ +package com.baeldung.annotations.service.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.ComponentScan; + +@TestConfiguration +@ComponentScan("com.baeldung.annotations.service.concretes") +public class ConcreteClassesAnnotatedTestConfiguration { + +} diff --git a/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/InterfacesAnnotatedTestConfiguration.java b/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/InterfacesAnnotatedTestConfiguration.java new file mode 100644 index 0000000000..94659902a1 --- /dev/null +++ b/spring-boot-modules/spring-boot-annotations/src/test/java/com.baeldung.annotations/service/config/InterfacesAnnotatedTestConfiguration.java @@ -0,0 +1,10 @@ +package com.baeldung.annotations.service.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.ComponentScan; + +@TestConfiguration +@ComponentScan("com.baeldung.annotations.service.interfaces") +public class InterfacesAnnotatedTestConfiguration { + +} diff --git a/spring-boot-modules/spring-boot-artifacts-2/README.md b/spring-boot-modules/spring-boot-artifacts-2/README.md new file mode 100644 index 0000000000..35f9cfab32 --- /dev/null +++ b/spring-boot-modules/spring-boot-artifacts-2/README.md @@ -0,0 +1,7 @@ +## Spring Boot Artifacts 2 + +This module contains articles about configuring the Spring Boot build process 2. + +### Relevant Articles: + +- [Difference Between spring-boot:repackage and Maven package](https://www.baeldung.com/spring-boot-repackage-vs-mvn-package) diff --git a/spring-boot-modules/spring-boot-artifacts-2/pom.xml b/spring-boot-modules/spring-boot-artifacts-2/pom.xml new file mode 100644 index 0000000000..abea13151e --- /dev/null +++ b/spring-boot-modules/spring-boot-artifacts-2/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + ../ + + + spring-boot-artifacts-2 + jar + + spring-boot-artifacts-2 + Demo project for Spring Boot + + + + org.springframework.boot + spring-boot-starter-web + + + + + ${project.artifactId} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + + + + com.baeldung.demo.DemoApplication + + + diff --git a/docker/docker-spring-boot/src/main/java/com/baeldung/docker/DemoApplication.java b/spring-boot-modules/spring-boot-artifacts-2/src/main/java/com/baeldung/demo/DemoApplication.java similarity index 90% rename from docker/docker-spring-boot/src/main/java/com/baeldung/docker/DemoApplication.java rename to spring-boot-modules/spring-boot-artifacts-2/src/main/java/com/baeldung/demo/DemoApplication.java index e0c1d57e89..177d3c834e 100644 --- a/docker/docker-spring-boot/src/main/java/com/baeldung/docker/DemoApplication.java +++ b/spring-boot-modules/spring-boot-artifacts-2/src/main/java/com/baeldung/demo/DemoApplication.java @@ -1,13 +1,11 @@ -package com.baeldung.docker; +package com.baeldung.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class DemoApplication { - public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } - } diff --git a/spring-boot-modules/spring-boot-artifacts-2/src/main/java/com/baeldung/demo/DemoRestController.java b/spring-boot-modules/spring-boot-artifacts-2/src/main/java/com/baeldung/demo/DemoRestController.java new file mode 100644 index 0000000000..0869927926 --- /dev/null +++ b/spring-boot-modules/spring-boot-artifacts-2/src/main/java/com/baeldung/demo/DemoRestController.java @@ -0,0 +1,15 @@ +package com.baeldung.demo; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class DemoRestController { + + @GetMapping(value = "/welcome") + public ResponseEntity welcomeEndpoint() { + return ResponseEntity.ok("Welcome to Baeldung Spring Boot Demo!"); + } + +} diff --git a/spring-boot-modules/spring-boot-artifacts-2/src/main/resources/application.yml b/spring-boot-modules/spring-boot-artifacts-2/src/main/resources/application.yml new file mode 100644 index 0000000000..3cd1d2e797 --- /dev/null +++ b/spring-boot-modules/spring-boot-artifacts-2/src/main/resources/application.yml @@ -0,0 +1,3 @@ +spring: + application: + name: Baeldung_SpringBoot_Demo \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-artifacts/pom.xml b/spring-boot-modules/spring-boot-artifacts/pom.xml index 2704b71bd6..467f931559 100644 --- a/spring-boot-modules/spring-boot-artifacts/pom.xml +++ b/spring-boot-modules/spring-boot-artifacts/pom.xml @@ -86,12 +86,6 @@ ${jquery.version}
- - org.springframework.cloud - spring-cloud-context - ${springcloud.version} - - org.apache.httpcomponents httpclient @@ -216,7 +210,6 @@ 2.2.4 18.0 3.1.7 - 2.0.2.RELEASE 4.5.8 diff --git a/spring-boot-modules/spring-boot-basic-customization-2/README.md b/spring-boot-modules/spring-boot-basic-customization-2/README.md new file mode 100644 index 0000000000..bf7e4abb76 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-2/README.md @@ -0,0 +1,7 @@ +## Spring Boot Basic Customization 2 + +This module contains articles about Spring Boot customization 2 + +### Relevant Articles: + + - [DispatcherServlet and web.xml in Spring Boot](https://www.baeldung.com/spring-boot-dispatcherservlet-web-xml) diff --git a/spring-boot-modules/spring-boot-basic-customization-2/pom.xml b/spring-boot-modules/spring-boot-basic-customization-2/pom.xml new file mode 100644 index 0000000000..3ce9266ebe --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-2/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + ../ + + + spring-boot-basic-customization-2 + jar + + spring-boot-basic-customization-2 + Module For Spring Boot Basic Customization 2 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + diff --git a/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/DispatchServletApplication.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/DispatchServletApplication.java new file mode 100644 index 0000000000..4d58715d88 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/DispatchServletApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.dispatchservlet; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.context.annotation.Configuration; + +@SpringBootApplication +public class DispatchServletApplication { + + public static void main(String[] args) { + SpringApplication.run(DispatchServletApplication.class, args); + } + +} diff --git a/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/conf/WebConf.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/conf/WebConf.java new file mode 100644 index 0000000000..7c52b117fd --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/conf/WebConf.java @@ -0,0 +1,29 @@ +package com.baeldung.dispatchservlet.conf; + +import com.baeldung.dispatchservlet.listener.CustomListener; +import com.baeldung.dispatchservlet.servlet.CustomServlet; +import org.springframework.boot.web.servlet.ServletListenerRegistrationBean; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.servlet.ServletContextListener; + +@Configuration +public class WebConf { + + @Bean + public ServletRegistrationBean customServletBean() { + ServletRegistrationBean bean + = new ServletRegistrationBean(new CustomServlet(), "/servlet"); + return bean; + } + + @Bean + public ServletListenerRegistrationBean customListenerBean() { + ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean(); + bean.setListener(new CustomListener()); + return bean; + } + +} diff --git a/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/controller/Controller.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/controller/Controller.java new file mode 100644 index 0000000000..14d71c60fb --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/controller/Controller.java @@ -0,0 +1,15 @@ +package com.baeldung.dispatchservlet.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping(value = "/") +public class Controller { + + @GetMapping + public String getRequest(){ + return "Baeldung DispatcherServlet"; + } +} diff --git a/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/filter/CustomFilter.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/filter/CustomFilter.java new file mode 100644 index 0000000000..8429fc855f --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/filter/CustomFilter.java @@ -0,0 +1,30 @@ +package com.baeldung.dispatchservlet.filter; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.servlet.*; +import java.io.IOException; + +@Component +public class CustomFilter implements Filter { + + Logger logger = LoggerFactory.getLogger(CustomFilter.class); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + logger.info("CustomFilter is invoked"); + chain.doFilter(request, response); + } + + @Override + public void destroy() { + + } +} diff --git a/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/listener/CustomListener.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/listener/CustomListener.java new file mode 100644 index 0000000000..62b316c012 --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/listener/CustomListener.java @@ -0,0 +1,22 @@ +package com.baeldung.dispatchservlet.listener; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +public class CustomListener implements ServletContextListener { + + Logger logger = LoggerFactory.getLogger(CustomListener.class); + + @Override + public void contextInitialized(ServletContextEvent sce) { + logger.info("CustomListener is initialized"); + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + logger.info("CustomListener is destroyed"); + } +} diff --git a/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/servlet/CustomServlet.java b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/servlet/CustomServlet.java new file mode 100644 index 0000000000..2a99e797ce --- /dev/null +++ b/spring-boot-modules/spring-boot-basic-customization-2/src/main/java/com/baeldung/dispatchservlet/servlet/CustomServlet.java @@ -0,0 +1,29 @@ +package com.baeldung.dispatchservlet.servlet; + +import com.baeldung.dispatchservlet.filter.CustomFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class CustomServlet extends HttpServlet { + + Logger logger = LoggerFactory.getLogger(CustomServlet.class); + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + logger.info("CustomServlet doGet() method is invoked"); + super.doGet(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + logger.info("CustomServlet doPost() method is invoked"); + super.doPost(req, resp); + } +} diff --git a/spring-mvc-java-2/src/main/webapp/resources/hello.css b/spring-boot-modules/spring-boot-basic-customization-2/src/main/resources/application.properties similarity index 100% rename from spring-mvc-java-2/src/main/webapp/resources/hello.css rename to spring-boot-modules/spring-boot-basic-customization-2/src/main/resources/application.properties diff --git a/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/crud/controllers/UserController.java b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/crud/controllers/UserController.java index 8a7ef96f1e..fb86683d6b 100644 --- a/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/crud/controllers/UserController.java +++ b/spring-boot-modules/spring-boot-crud/src/main/java/com/baeldung/crud/controllers/UserController.java @@ -23,6 +23,12 @@ public class UserController { this.userRepository = userRepository; } + @GetMapping("/index") + public String showUserList(Model model) { + model.addAttribute("users", userRepository.findAll()); + return "index"; + } + @GetMapping("/signup") public String showSignUpForm(User user) { return "add-user"; @@ -35,7 +41,6 @@ public class UserController { } userRepository.save(user); - model.addAttribute("users", userRepository.findAll()); return "redirect:/index"; } @@ -43,6 +48,7 @@ public class UserController { public String showUpdateForm(@PathVariable("id") long id, Model model) { User user = userRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id)); model.addAttribute("user", user); + return "update-user"; } @@ -54,7 +60,7 @@ public class UserController { } userRepository.save(user); - model.addAttribute("users", userRepository.findAll()); + return "redirect:/index"; } @@ -62,7 +68,7 @@ public class UserController { public String deleteUser(@PathVariable("id") long id, Model model) { User user = userRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id)); userRepository.delete(user); - model.addAttribute("users", userRepository.findAll()); - return "index"; + + return "redirect:/index"; } } diff --git a/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/crud/UserControllerUnitTest.java b/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/crud/UserControllerUnitTest.java index f1455f7a73..77d83698de 100644 --- a/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/crud/UserControllerUnitTest.java +++ b/spring-boot-modules/spring-boot-crud/src/test/java/com/baeldung/crud/UserControllerUnitTest.java @@ -28,6 +28,11 @@ public class UserControllerUnitTest { userController = new UserController(mockedUserRepository); } + @Test + public void whenCalledIndex_thenCorrect() { + assertThat(userController.showUserList(mockedModel)).isEqualTo("index"); + } + @Test public void whenCalledshowSignUpForm_thenCorrect() { User user = new User("John", "john@domain.com"); @@ -78,6 +83,6 @@ public class UserControllerUnitTest { @Test(expected = IllegalArgumentException.class) public void whenCalleddeleteUser_thenIllegalArgumentException() { - assertThat(userController.deleteUser(1l, mockedModel)).isEqualTo("index"); + assertThat(userController.deleteUser(1l, mockedModel)).isEqualTo("redirect:/index"); } } diff --git a/spring-boot-modules/spring-boot-ctx-fluent/src/test/java/org/baeldung/SpringContextTest.java b/spring-boot-modules/spring-boot-ctx-fluent/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-boot-modules/spring-boot-ctx-fluent/src/test/java/org/baeldung/SpringContextTest.java rename to spring-boot-modules/spring-boot-ctx-fluent/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-boot-modules/spring-boot-data-2/README.md b/spring-boot-modules/spring-boot-data-2/README.md new file mode 100644 index 0000000000..d5020ce354 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Spring Boot: Customize the Jackson ObjectMapper](https://www.baeldung.com/spring-boot-customize-jackson-objectmapper) diff --git a/spring-boot-modules/spring-boot-data-2/pom.xml b/spring-boot-modules/spring-boot-data-2/pom.xml new file mode 100644 index 0000000000..fb0d5f2053 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/pom.xml @@ -0,0 +1,30 @@ + + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + ../ + + 4.0.0 + + spring-boot-data-2 + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + runtime + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/app/Application.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/app/Application.java new file mode 100644 index 0000000000..6f57a534a8 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/app/Application.java @@ -0,0 +1,13 @@ +package com.baeldung.boot.jackson.app; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan(basePackages = "com.baeldung.boot.jackson.controller") +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeConstants.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeConstants.java new file mode 100644 index 0000000000..d1875d03d9 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeConstants.java @@ -0,0 +1,13 @@ +package com.baeldung.boot.jackson.config; + +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +public class CoffeeConstants { + + public static final String DATETIME_FORMAT = "dd-MM-yyyy HH:mm"; + public static final LocalDateTime FIXED_DATE = LocalDateTime.now(); + public static LocalDateTimeSerializer LOCAL_DATETIME_SERIALIZER = new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DATETIME_FORMAT)); +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeCustomizerConfig.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeCustomizerConfig.java new file mode 100644 index 0000000000..edb2b478fc --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeCustomizerConfig.java @@ -0,0 +1,18 @@ +package com.baeldung.boot.jackson.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER; + +@Configuration +public class CoffeeCustomizerConfig { + + @Bean + public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { + return builder -> builder.serializationInclusion(JsonInclude.Include.NON_NULL) + .serializers(LOCAL_DATETIME_SERIALIZER); + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeHttpConverterConfiguration.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeHttpConverterConfiguration.java new file mode 100644 index 0000000000..eff2b5c252 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeHttpConverterConfiguration.java @@ -0,0 +1,21 @@ +package com.baeldung.boot.jackson.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; + +import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER; + +@Configuration +public class CoffeeHttpConverterConfiguration { + + @Bean + public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() { + Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() + .serializers(LOCAL_DATETIME_SERIALIZER) + .serializationInclusion(JsonInclude.Include.NON_NULL); + return new MappingJackson2HttpMessageConverter(builder.build()); + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeJacksonBuilderConfig.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeJacksonBuilderConfig.java new file mode 100644 index 0000000000..8057fff3db --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeJacksonBuilderConfig.java @@ -0,0 +1,21 @@ +package com.baeldung.boot.jackson.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER; + +@Configuration +public class CoffeeJacksonBuilderConfig { + + @Bean + @Primary + public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() { + return new Jackson2ObjectMapperBuilder() + .serializers(LOCAL_DATETIME_SERIALIZER) + .serializationInclusion(JsonInclude.Include.NON_NULL); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeObjectMapperConfig.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeObjectMapperConfig.java new file mode 100644 index 0000000000..f1ce6458ae --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeObjectMapperConfig.java @@ -0,0 +1,23 @@ +package com.baeldung.boot.jackson.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; + +import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER; + +@Configuration +public class CoffeeObjectMapperConfig { + + @Bean + @Primary + public ObjectMapper objectMapper() { + JavaTimeModule module = new JavaTimeModule(); + module.addSerializer(LOCAL_DATETIME_SERIALIZER); + return new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL) + .registerModule(module); + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeRegisterModuleConfig.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeRegisterModuleConfig.java new file mode 100644 index 0000000000..fc157f8156 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/config/CoffeeRegisterModuleConfig.java @@ -0,0 +1,21 @@ +package com.baeldung.boot.jackson.config; + +import com.fasterxml.jackson.databind.Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER; + +@Configuration +@PropertySource("classpath:coffee.properties") +public class CoffeeRegisterModuleConfig { + + @Bean + public Module javaTimeModule() { + JavaTimeModule module = new JavaTimeModule(); + module.addSerializer(LOCAL_DATETIME_SERIALIZER); + return module; + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/controller/CoffeeController.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/controller/CoffeeController.java new file mode 100644 index 0000000000..23749b18a2 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/controller/CoffeeController.java @@ -0,0 +1,21 @@ +package com.baeldung.boot.jackson.controller; + +import com.baeldung.boot.jackson.model.Coffee; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import static com.baeldung.boot.jackson.config.CoffeeConstants.FIXED_DATE; + +@RestController +public class CoffeeController { + + @GetMapping("/coffee") + public Coffee getCoffee( + @RequestParam(required = false) String brand, + @RequestParam(required = false) String name) { + return new Coffee().setBrand(brand) + .setDate(FIXED_DATE) + .setName(name); + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/model/Coffee.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/model/Coffee.java new file mode 100644 index 0000000000..4df6b4bd6d --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/jackson/model/Coffee.java @@ -0,0 +1,39 @@ +package com.baeldung.boot.jackson.model; + +import java.time.LocalDateTime; + +public class Coffee { + + private String name; + + private String brand; + + private LocalDateTime date; + + public String getName() { + return name; + } + + public Coffee setName(String name) { + this.name = name; + return this; + } + + public String getBrand() { + return brand; + } + + public Coffee setBrand(String brand) { + this.brand = brand; + return this; + } + + public LocalDateTime getDate() { + return date; + } + + public Coffee setDate(LocalDateTime date) { + this.date = date; + return this; + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/noconverterfound/NoConverterFoundApplication.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/noconverterfound/NoConverterFoundApplication.java new file mode 100644 index 0000000000..7abfa29bf2 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/noconverterfound/NoConverterFoundApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.boot.noconverterfound; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class NoConverterFoundApplication { + + public static void main(String[] args) { + SpringApplication.run(NoConverterFoundApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/noconverterfound/controller/StudentRestController.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/noconverterfound/controller/StudentRestController.java new file mode 100644 index 0000000000..21cb98710d --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/noconverterfound/controller/StudentRestController.java @@ -0,0 +1,21 @@ +package com.baeldung.boot.noconverterfound.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.boot.noconverterfound.model.Student; + +@RestController +@RequestMapping(value = "/api") +public class StudentRestController { + + @GetMapping("/student/{id}") + public ResponseEntity get(@PathVariable("id") int id) { + // Custom logic + return ResponseEntity.ok(new Student(id, "John", "Wiliams", "AA")); + } + +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/noconverterfound/model/Student.java b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/noconverterfound/model/Student.java new file mode 100644 index 0000000000..94ece02f8f --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/java/com/baeldung/boot/noconverterfound/model/Student.java @@ -0,0 +1,53 @@ +package com.baeldung.boot.noconverterfound.model; + +public class Student { + + private int id; + private String firstName; + private String lastName; + private String grade; + + public Student() { + + } + + public Student(int id, String firstName, String lastName, String grade) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + this.grade = grade; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getGrade() { + return grade; + } + + public void setGrade(String grade) { + this.grade = grade; + } + +} diff --git a/spring-boot-modules/spring-boot-data-2/src/main/resources/coffee.properties b/spring-boot-modules/spring-boot-data-2/src/main/resources/coffee.properties new file mode 100644 index 0000000000..269845cbf1 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/main/resources/coffee.properties @@ -0,0 +1 @@ +spring.jackson.default-property-inclusion=non_null \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/AbstractCoffeeIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/AbstractCoffeeIntegrationTest.java new file mode 100644 index 0000000000..f1bc35a8ce --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/AbstractCoffeeIntegrationTest.java @@ -0,0 +1,33 @@ +package com.baeldung.boot.jackson.app; + +import com.baeldung.boot.jackson.config.CoffeeConstants; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; + +import java.time.format.DateTimeFormatter; + +import static com.baeldung.boot.jackson.config.CoffeeConstants.FIXED_DATE; +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public abstract class AbstractCoffeeIntegrationTest { + + @Autowired + protected TestRestTemplate restTemplate; + + @Test + public void whenGetCoffee_thenSerializedWithDateAndNonNull() { + String formattedDate = DateTimeFormatter.ofPattern(CoffeeConstants.DATETIME_FORMAT) + .format(FIXED_DATE); + + String brand = "Lavazza"; + String url = "/coffee?brand=" + brand; + + String response = restTemplate.getForObject(url, String.class); + + assertThat(response).isEqualTo( + "{\"brand\":\"" + brand + "\",\"date\":\"" + formattedDate + "\"}"); + } +} diff --git a/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeCustomizerIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeCustomizerIntegrationTest.java new file mode 100644 index 0000000000..d690de1b9c --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeCustomizerIntegrationTest.java @@ -0,0 +1,8 @@ +package com.baeldung.boot.jackson.app; + +import com.baeldung.boot.jackson.config.CoffeeCustomizerConfig; +import org.springframework.context.annotation.Import; + +@Import(CoffeeCustomizerConfig.class) +public class CoffeeCustomizerIntegrationTest extends AbstractCoffeeIntegrationTest { +} diff --git a/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeHttpConverterIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeHttpConverterIntegrationTest.java new file mode 100644 index 0000000000..62b1d42152 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeHttpConverterIntegrationTest.java @@ -0,0 +1,8 @@ +package com.baeldung.boot.jackson.app; + +import com.baeldung.boot.jackson.config.CoffeeHttpConverterConfiguration; +import org.springframework.context.annotation.Import; + +@Import(CoffeeHttpConverterConfiguration.class) +public class CoffeeHttpConverterIntegrationTest extends AbstractCoffeeIntegrationTest { +} diff --git a/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeJacksonBuilderIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeJacksonBuilderIntegrationTest.java new file mode 100644 index 0000000000..52a55394c0 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeJacksonBuilderIntegrationTest.java @@ -0,0 +1,8 @@ +package com.baeldung.boot.jackson.app; + +import com.baeldung.boot.jackson.config.CoffeeJacksonBuilderConfig; +import org.springframework.context.annotation.Import; + +@Import(CoffeeJacksonBuilderConfig.class) +public class CoffeeJacksonBuilderIntegrationTest extends AbstractCoffeeIntegrationTest { +} diff --git a/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeObjectMapperIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeObjectMapperIntegrationTest.java new file mode 100644 index 0000000000..34743ceba5 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeObjectMapperIntegrationTest.java @@ -0,0 +1,8 @@ +package com.baeldung.boot.jackson.app; + +import com.baeldung.boot.jackson.config.CoffeeObjectMapperConfig; +import org.springframework.context.annotation.Import; + +@Import(CoffeeObjectMapperConfig.class) +public class CoffeeObjectMapperIntegrationTest extends AbstractCoffeeIntegrationTest { +} diff --git a/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeRegisterModuleIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeRegisterModuleIntegrationTest.java new file mode 100644 index 0000000000..69bbd5be2a --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/jackson/app/CoffeeRegisterModuleIntegrationTest.java @@ -0,0 +1,8 @@ +package com.baeldung.boot.jackson.app; + +import com.baeldung.boot.jackson.config.CoffeeRegisterModuleConfig; +import org.springframework.context.annotation.Import; + +@Import(CoffeeRegisterModuleConfig.class) +public class CoffeeRegisterModuleIntegrationTest extends AbstractCoffeeIntegrationTest { +} diff --git a/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/noconverterfound/NoConverterFoundIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/noconverterfound/NoConverterFoundIntegrationTest.java new file mode 100644 index 0000000000..3304a33957 --- /dev/null +++ b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/boot/noconverterfound/NoConverterFoundIntegrationTest.java @@ -0,0 +1,50 @@ +package com.baeldung.boot.noconverterfound; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +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.WebMvcTest; +import org.springframework.http.converter.HttpMessageNotWritableException; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import com.baeldung.boot.noconverterfound.controller.StudentRestController; + +@RunWith(SpringRunner.class) +@WebMvcTest(StudentRestController.class) +public class NoConverterFoundIntegrationTest { + + @Autowired + private MockMvc mockMvc; + + @Test + public void whenGettersNotDefined_thenThrowException() throws Exception { + + String url = "/api/student/1"; + + this.mockMvc.perform(get(url)) + .andExpect(status().isInternalServerError()) + .andExpect(result -> assertThat(result.getResolvedException()) + .isInstanceOf(HttpMessageNotWritableException.class)) + .andExpect(result -> assertThat(result.getResolvedException().getMessage()) + .contains("No converter found for return value of type")); + + } + + @Test + public void whenGettersAreDefined_thenReturnObject() throws Exception { + + String url = "/api/student/2"; + + this.mockMvc.perform(get(url)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.firstName").value("John")); + + } + +} diff --git a/spring-5/src/test/java/com/baeldung/hikari/ApplicationWithHikariConnectionPool.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/hikari/ApplicationWithHikariConnectionPool.java similarity index 100% rename from spring-5/src/test/java/com/baeldung/hikari/ApplicationWithHikariConnectionPool.java rename to spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/hikari/ApplicationWithHikariConnectionPool.java diff --git a/spring-5/src/test/java/com/baeldung/hikari/HikariIntegrationTest.java b/spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/hikari/HikariIntegrationTest.java similarity index 100% rename from spring-5/src/test/java/com/baeldung/hikari/HikariIntegrationTest.java rename to spring-boot-modules/spring-boot-data-2/src/test/java/com/baeldung/hikari/HikariIntegrationTest.java diff --git a/spring-boot-modules/spring-boot-data/README.md b/spring-boot-modules/spring-boot-data/README.md index 98589cf2d2..f72864e6d9 100644 --- a/spring-boot-modules/spring-boot-data/README.md +++ b/spring-boot-modules/spring-boot-data/README.md @@ -10,4 +10,5 @@ This module contains articles about Spring Boot with Spring Data - [Repositories with Multiple Spring Data Modules](https://www.baeldung.com/spring-multiple-data-modules) - [Spring Custom Property Editor](https://www.baeldung.com/spring-mvc-custom-property-editor) - [Using @JsonComponent in Spring Boot](https://www.baeldung.com/spring-boot-jsoncomponent) -- [Running Setup Data on Startup in Spring](https://www.baeldung.com/running-setup-logic-on-startup-in-spring) +- [Guide To Running Logic on Startup in Spring](https://www.baeldung.com/running-setup-logic-on-startup-in-spring) +- [Using JaVers for Data Model Auditing in Spring Data](https://www.baeldung.com/spring-data-javers-audit) diff --git a/spring-boot-modules/spring-boot-data/pom.xml b/spring-boot-modules/spring-boot-data/pom.xml index fe64b07379..06f09c70fe 100644 --- a/spring-boot-modules/spring-boot-data/pom.xml +++ b/spring-boot-modules/spring-boot-data/pom.xml @@ -168,7 +168,7 @@ - 5.6.3 + 5.14.0 2.2.4 1.8 1.8 diff --git a/spring-boot-modules/spring-boot-data/src/main/java/com/baeldung/javers/README.md b/spring-boot-modules/spring-boot-data/src/main/java/com/baeldung/javers/README.md deleted file mode 100644 index 4f8dd4abff..0000000000 --- a/spring-boot-modules/spring-boot-data/src/main/java/com/baeldung/javers/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles - -- [Using JaVers for Data Model Auditing in Spring Data](https://www.baeldung.com/spring-data-javers-audit) diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/startup/AppStartupRunner.java b/spring-boot-modules/spring-boot-data/src/main/java/com/baeldung/startup/AppStartupRunner.java similarity index 99% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/startup/AppStartupRunner.java rename to spring-boot-modules/spring-boot-data/src/main/java/com/baeldung/startup/AppStartupRunner.java index 0495473704..0ba719d32b 100644 --- a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/startup/AppStartupRunner.java +++ b/spring-boot-modules/spring-boot-data/src/main/java/com/baeldung/startup/AppStartupRunner.java @@ -8,6 +8,7 @@ import org.springframework.stereotype.Component; @Component public class AppStartupRunner implements ApplicationRunner { + private static final Logger LOG = LoggerFactory.getLogger(AppStartupRunner.class); public static int counter; diff --git a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/startup/CommandLineAppStartupRunner.java b/spring-boot-modules/spring-boot-data/src/main/java/com/baeldung/startup/CommandLineAppStartupRunner.java similarity index 99% rename from spring-boot-modules/spring-boot/src/main/java/com/baeldung/startup/CommandLineAppStartupRunner.java rename to spring-boot-modules/spring-boot-data/src/main/java/com/baeldung/startup/CommandLineAppStartupRunner.java index 48c5225cf1..bdedbbe94c 100644 --- a/spring-boot-modules/spring-boot/src/main/java/com/baeldung/startup/CommandLineAppStartupRunner.java +++ b/spring-boot-modules/spring-boot-data/src/main/java/com/baeldung/startup/CommandLineAppStartupRunner.java @@ -7,6 +7,7 @@ import org.springframework.stereotype.Component; @Component public class CommandLineAppStartupRunner implements CommandLineRunner { + private static final Logger LOG = LoggerFactory.getLogger(CommandLineAppStartupRunner.class); public static int counter; @@ -15,4 +16,4 @@ public class CommandLineAppStartupRunner implements CommandLineRunner { LOG.info("Increment counter"); counter++; } -} \ No newline at end of file +} diff --git a/spring-boot-modules/spring-boot-data/src/main/java/com/baeldung/startup/SpringStartupConfig.java b/spring-boot-modules/spring-boot-data/src/main/java/com/baeldung/startup/SpringStartupConfig.java index ad6492dadc..27c903955a 100644 --- a/spring-boot-modules/spring-boot-data/src/main/java/com/baeldung/startup/SpringStartupConfig.java +++ b/spring-boot-modules/spring-boot-data/src/main/java/com/baeldung/startup/SpringStartupConfig.java @@ -1,9 +1,15 @@ package com.baeldung.startup; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan("com.baeldung.startup") public class SpringStartupConfig { + + @Bean(initMethod="init") + public InitMethodExampleBean initMethodExampleBean() { + return new InitMethodExampleBean(); + } } \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/startup/SpringStartupIntegrationTest.java b/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/startup/SpringStartupIntegrationTest.java index b58c093c31..ac2b98da6f 100644 --- a/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/startup/SpringStartupIntegrationTest.java +++ b/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/startup/SpringStartupIntegrationTest.java @@ -37,6 +37,11 @@ public class SpringStartupIntegrationTest { ctx.getBean(InitializingBeanExampleBean.class); } + @Test + public void whenInitMethod_shouldLogEnv() throws Exception { + ctx.getBean(InitMethodExampleBean.class); + } + @Test public void whenApplicationListener_shouldRunOnce() throws Exception { Assertions.assertThat(StartupApplicationListenerExample.counter).isEqualTo(1); diff --git a/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/startup/SpringStartupXMLConfigIntegrationTest.java b/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/startup/SpringStartupXMLConfigIntegrationTest.java index 3dfd4835df..67b430fced 100644 --- a/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/startup/SpringStartupXMLConfigIntegrationTest.java +++ b/spring-boot-modules/spring-boot-data/src/test/java/com/baeldung/startup/SpringStartupXMLConfigIntegrationTest.java @@ -15,7 +15,7 @@ public class SpringStartupXMLConfigIntegrationTest { private ApplicationContext ctx; @Test - public void whenPostConstruct_shouldLogEnv() throws Exception { + public void whenInitMethod_shouldLogEnv() throws Exception { ctx.getBean(InitMethodExampleBean.class); } diff --git a/spring-boot-modules/spring-boot-deployment/README.md b/spring-boot-modules/spring-boot-deployment/README.md index b6aa468098..85f288d33b 100644 --- a/spring-boot-modules/spring-boot-deployment/README.md +++ b/spring-boot-modules/spring-boot-deployment/README.md @@ -5,6 +5,5 @@ This module contains articles about deployment of a Spring Boot Application ### Relevant Articles: - [Deploy a Spring Boot WAR into a Tomcat Server](https://www.baeldung.com/spring-boot-war-tomcat-deploy) - [Spring Boot Console Application](https://www.baeldung.com/spring-boot-console-app) - - [How to Configure Spring Boot Tomcat](https://www.baeldung.com/spring-boot-configure-tomcat) - [Comparing Embedded Servlet Containers in Spring Boot](https://www.baeldung.com/spring-boot-servlet-containers) - [Graceful Shutdown of a Spring Boot Application](https://www.baeldung.com/spring-boot-graceful-shutdown) diff --git a/spring-boot-modules/spring-boot-deployment/pom.xml b/spring-boot-modules/spring-boot-deployment/pom.xml index 6b5e75bd62..94a4018103 100644 --- a/spring-boot-modules/spring-boot-deployment/pom.xml +++ b/spring-boot-modules/spring-boot-deployment/pom.xml @@ -197,6 +197,7 @@ 3.1.7 2.0.2.RELEASE 4.5.8 + 2.3.3.RELEASE diff --git a/spring-boot-modules/spring-boot-environment/README.md b/spring-boot-modules/spring-boot-environment/README.md index e916c503bc..e7b0ace7a4 100644 --- a/spring-boot-modules/spring-boot-environment/README.md +++ b/spring-boot-modules/spring-boot-environment/README.md @@ -4,4 +4,5 @@ This module contains articles about configuring the Spring Boot `Environment` ### Relevant Articles: - [EnvironmentPostProcessor in Spring Boot](https://www.baeldung.com/spring-boot-environmentpostprocessor) - - [Spring Properties File Outside jar](https://www.baeldung.com/spring-properties-file-outside-jar) \ No newline at end of file + - [Spring Properties File Outside jar](https://www.baeldung.com/spring-properties-file-outside-jar) + - [Get the Running Port in Spring Boot](https://www.baeldung.com/spring-boot-running-port) diff --git a/spring-boot-modules/spring-boot-environment/additional.properties b/spring-boot-modules/spring-boot-environment/additional.properties new file mode 100644 index 0000000000..676536efa5 --- /dev/null +++ b/spring-boot-modules/spring-boot-environment/additional.properties @@ -0,0 +1 @@ +bael.property1=value1 \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-environment/pom.xml b/spring-boot-modules/spring-boot-environment/pom.xml index 694e17fd72..a3aab63a2d 100644 --- a/spring-boot-modules/spring-boot-environment/pom.xml +++ b/spring-boot-modules/spring-boot-environment/pom.xml @@ -1,6 +1,7 @@ - + 4.0.0 @@ -33,6 +34,17 @@ spring-boot-starter-test test + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + org.springframework.boot @@ -77,7 +89,6 @@ org.springframework.cloud spring-cloud-context - ${springcloud.version} @@ -88,6 +99,18 @@ + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring.cloud-version} + pom + import + + + + ${project.artifactId} @@ -142,8 +165,8 @@ 2.2 18.0 3.1.7 - 2.0.2.RELEASE 4.5.8 + 2020.0.0 diff --git a/spring-boot-modules/spring-boot-environment/src/main/java/com/baeldung/serverport/GetServerPortApplication.java b/spring-boot-modules/spring-boot-environment/src/main/java/com/baeldung/serverport/GetServerPortApplication.java new file mode 100644 index 0000000000..d7658ad8d5 --- /dev/null +++ b/spring-boot-modules/spring-boot-environment/src/main/java/com/baeldung/serverport/GetServerPortApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.serverport; + + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class GetServerPortApplication { + public static void main(String[] args) { + SpringApplication.run(GetServerPortApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-environment/src/main/java/com/baeldung/serverport/ServerPortService.java b/spring-boot-modules/spring-boot-environment/src/main/java/com/baeldung/serverport/ServerPortService.java new file mode 100644 index 0000000000..59c0a0f333 --- /dev/null +++ b/spring-boot-modules/spring-boot-environment/src/main/java/com/baeldung/serverport/ServerPortService.java @@ -0,0 +1,20 @@ +package com.baeldung.serverport; + +import org.springframework.boot.web.servlet.context.ServletWebServerInitializedEvent; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Service; + +@Service +public class ServerPortService { + private int port; + + public int getPort() { + return port; + } + + @EventListener + public void onApplicationEvent(final ServletWebServerInitializedEvent event) { + port = event.getWebServer().getPort(); + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-environment/src/main/resources/application.properties b/spring-boot-modules/spring-boot-environment/src/main/resources/application.properties index 27b7915cff..3d6f37230c 100644 --- a/spring-boot-modules/spring-boot-environment/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-environment/src/main/resources/application.properties @@ -2,6 +2,7 @@ management.endpoints.web.exposure.include=* management.metrics.enable.root=true management.metrics.enable.jvm=true management.endpoint.restart.enabled=true -spring.datasource.jmx-enabled=false +spring.datasource.tomcat.jmx-enabled=false spring.main.allow-bean-definition-overriding=true -management.endpoint.shutdown.enabled=true \ No newline at end of file +management.endpoint.shutdown.enabled=true +spring.config.import=file:./additional.properties,optional:file:/Users/home/config/jdbc.properties \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-environment/src/test/java/com/baeldung/properties/ApplicationPropertyImportExternalFileIntegrationTest.java b/spring-boot-modules/spring-boot-environment/src/test/java/com/baeldung/properties/ApplicationPropertyImportExternalFileIntegrationTest.java new file mode 100644 index 0000000000..04f5445639 --- /dev/null +++ b/spring-boot-modules/spring-boot-environment/src/test/java/com/baeldung/properties/ApplicationPropertyImportExternalFileIntegrationTest.java @@ -0,0 +1,22 @@ +package com.baeldung.properties; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class ApplicationPropertyImportExternalFileIntegrationTest { + + @Value("${bael.property1}") + String baelProperty; + + @Test + public void whenExternalisedPropertiesLoadedUsinApplicationProperties_thenReadValues() throws IOException { + assertEquals(baelProperty, "value1"); + } + +} diff --git a/spring-boot-modules/spring-boot-environment/src/test/java/com/baeldung/serverport/GetServerFixedPortUnitTest.java b/spring-boot-modules/spring-boot-environment/src/test/java/com/baeldung/serverport/GetServerFixedPortUnitTest.java new file mode 100644 index 0000000000..81e663b7a1 --- /dev/null +++ b/spring-boot-modules/spring-boot-environment/src/test/java/com/baeldung/serverport/GetServerFixedPortUnitTest.java @@ -0,0 +1,37 @@ +package com.baeldung.serverport; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = GetServerPortApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@ActiveProfiles("fixedport") +public class GetServerFixedPortUnitTest { + private final static int EXPECTED_PORT = 7777; + + @Value("${server.port}") + private int serverPort; + + @Autowired + private ServerProperties serverProperties; + + @Test + public void givenFixedPortAsServerPort_whenReadServerPort_thenGetThePort() { + assertEquals("Reading fixed port by @Value(\"${server.port}\") will get the port.", EXPECTED_PORT, serverPort); + } + + @Test + public void givenFixedPortAsServerPort_whenReadServerProps_thenGetThePort() { + int port = serverProperties.getPort(); + assertEquals("Reading fixed port from serverProperties will get the port.", EXPECTED_PORT, port); + } + +} diff --git a/spring-boot-modules/spring-boot-environment/src/test/java/com/baeldung/serverport/GetServerRandomPortUnitTest.java b/spring-boot-modules/spring-boot-environment/src/test/java/com/baeldung/serverport/GetServerRandomPortUnitTest.java new file mode 100644 index 0000000000..3ad7e0fdf1 --- /dev/null +++ b/spring-boot-modules/spring-boot-environment/src/test/java/com/baeldung/serverport/GetServerRandomPortUnitTest.java @@ -0,0 +1,55 @@ +package com.baeldung.serverport; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.web.ServerProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = GetServerPortApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@ActiveProfiles("randomport") +public class GetServerRandomPortUnitTest { + + @Value("${server.port}") + private int randomServerPort; + + @Autowired + private ServerPortService serverPortService; + + @Autowired + private ServerProperties serverProperties; + + @Autowired + private ServletWebServerApplicationContext webServerAppCtxt; + + @Test + public void given0AsServerPort_whenReadServerPort_thenGet0() { + assertEquals("Reading random port by @Value(\"${server.port}\") will get 0.", 0, randomServerPort); + } + + @Test + public void given0AsServerPort_whenReadServerProps_thenGet0() { + int port = serverProperties.getPort(); + assertEquals("Reading random port by serverProperties will get 0.", 0, port); + } + + @Test + public void given0AsServerPort_whenReadWebAppCtxt_thenGetThePort() { + int port = webServerAppCtxt.getWebServer().getPort(); + assertTrue("The random port should be greater than 1023", port > 1023); + } + + @Test + public void given0AsServerPort_whenReadFromListener_thenGetThePort() { + int port = serverPortService.getPort(); + assertTrue("The random port should be greater than 1023", port > 1023); + } +} diff --git a/spring-boot-modules/spring-boot-environment/src/test/resources/application-fixedport.properties b/spring-boot-modules/spring-boot-environment/src/test/resources/application-fixedport.properties new file mode 100644 index 0000000000..0c5e84f3a2 --- /dev/null +++ b/spring-boot-modules/spring-boot-environment/src/test/resources/application-fixedport.properties @@ -0,0 +1 @@ +server.port=7777 diff --git a/spring-boot-modules/spring-boot-environment/src/test/resources/application-randomport.properties b/spring-boot-modules/spring-boot-environment/src/test/resources/application-randomport.properties new file mode 100644 index 0000000000..cbe617ef03 --- /dev/null +++ b/spring-boot-modules/spring-boot-environment/src/test/resources/application-randomport.properties @@ -0,0 +1 @@ +server.port=0 diff --git a/spring-boot-modules/spring-boot-jasypt/src/test/java/org/baeldung/SpringContextTest.java b/spring-boot-modules/spring-boot-jasypt/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-boot-modules/spring-boot-jasypt/src/test/java/org/baeldung/SpringContextTest.java rename to spring-boot-modules/spring-boot-jasypt/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-boot-modules/spring-boot-keycloak/README.md b/spring-boot-modules/spring-boot-keycloak/README.md index 74fbbb6f09..2aff4664a6 100644 --- a/spring-boot-modules/spring-boot-keycloak/README.md +++ b/spring-boot-modules/spring-boot-keycloak/README.md @@ -5,3 +5,7 @@ This module contains articles about Keycloak in Spring Boot projects. ## Relevant articles: - [A Quick Guide to Using Keycloak with Spring Boot](https://www.baeldung.com/spring-boot-keycloak) - [Custom User Attributes with Keycloak](https://www.baeldung.com/keycloak-custom-user-attributes) +- [Customizing the Login Page for Keycloak](https://www.baeldung.com/keycloak-custom-login-page) +- [Keycloak User Self-Registration](https://www.baeldung.com/keycloak-user-registration) +- [Customizing Themes for Keycloak](https://www.baeldung.com/spring-keycloak-custom-themes) + diff --git a/spring-boot-modules/spring-boot-keycloak/pom.xml b/spring-boot-modules/spring-boot-keycloak/pom.xml index 5049cc3651..cfcdcf2c37 100644 --- a/spring-boot-modules/spring-boot-keycloak/pom.xml +++ b/spring-boot-modules/spring-boot-keycloak/pom.xml @@ -76,7 +76,7 @@ - 10.0.2 + 11.0.2 diff --git a/spring-boot-modules/spring-boot-kotlin/README.md b/spring-boot-modules/spring-boot-kotlin/README.md deleted file mode 100644 index fb91fdee15..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## Spring Boot Kotlin - -This module contains articles about Kotlin in Spring Boot projects. - -### Relevant Articles: -- [Non-blocking Spring Boot with Kotlin Coroutines](https://www.baeldung.com/spring-boot-kotlin-coroutines) diff --git a/spring-boot-modules/spring-boot-kotlin/pom.xml b/spring-boot-modules/spring-boot-kotlin/pom.xml deleted file mode 100644 index 7ee048546a..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/pom.xml +++ /dev/null @@ -1,119 +0,0 @@ - - - 4.0.0 - spring-boot-kotlin - spring-boot-kotlin - jar - Demo project showing how to use non-blocking in Kotlin with Spring Boot - - - com.baeldung - parent-kotlin - 1.0.0-SNAPSHOT - ../../parent-kotlin - - - - - org.jetbrains.kotlin - kotlin-reflect - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - - - org.jetbrains.kotlinx - kotlinx-coroutines-core - ${kotlinx-coroutines.version} - - - org.jetbrains.kotlinx - kotlinx-coroutines-reactor - ${kotlinx-coroutines.version} - - - org.springframework.boot - spring-boot-starter-webflux - - - com.fasterxml.jackson.module - jackson-module-kotlin - - - org.springframework.data - spring-data-r2dbc - ${r2dbc.version} - - - io.r2dbc - r2dbc-h2 - ${h2-r2dbc.version} - - - io.r2dbc - r2dbc-spi - ${r2dbc-spi.version} - - - org.springframework.boot - spring-boot-starter-test - test - - - junit - junit - - - - - org.junit.jupiter - junit-jupiter-api - test - - - org.junit.jupiter - junit-jupiter-engine - test - - - io.projectreactor - reactor-test - test - - - - - - - org.jetbrains.kotlin - kotlin-maven-plugin - - - -Xjsr305=strict - - - spring - - - - - org.jetbrains.kotlin - kotlin-maven-allopen - ${kotlin.version} - - - - - - - - 1.3.31 - 1.0.0.RELEASE - 0.8.2.RELEASE - 0.8.4.RELEASE - 1.2.1 - - - diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/SpringApplication.kt b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/SpringApplication.kt deleted file mode 100644 index 23af4fe90b..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/SpringApplication.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.nonblockingcoroutines - -import org.springframework.boot.SpringApplication.run -import org.springframework.boot.autoconfigure.SpringBootApplication - -@SpringBootApplication -class SpringApplication - -fun main(args: Array) { - run(SpringApplication::class.java, *args) -} diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/DatastoreConfig.kt b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/DatastoreConfig.kt deleted file mode 100644 index 52ef8a708b..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/DatastoreConfig.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.nonblockingcoroutines.config - -import io.r2dbc.h2.H2ConnectionConfiguration -import io.r2dbc.h2.H2ConnectionFactory -import io.r2dbc.spi.ConnectionFactory -import org.springframework.beans.factory.annotation.Value -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration -import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories - -@Configuration -@EnableR2dbcRepositories -class DatastoreConfig : AbstractR2dbcConfiguration() { - @Value("\${spring.datasource.username}") - private val userName: String = "" - - @Value("\${spring.datasource.password}") - private val password: String = "" - - @Value("\${spring.datasource.dbname}") - private val dbName: String = "" - - @Bean - override fun connectionFactory(): ConnectionFactory { - return H2ConnectionFactory(H2ConnectionConfiguration.builder() - .inMemory(dbName) - .username(userName) - .password(password) - .build()) - } -} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/RouterConfiguration.kt b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/RouterConfiguration.kt deleted file mode 100644 index bda1d26278..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/RouterConfiguration.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.nonblockingcoroutines.config - -import com.baeldung.nonblockingcoroutines.handlers.ProductsHandler -import kotlinx.coroutines.FlowPreview -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.web.reactive.function.server.coRouter - -@Configuration -class RouterConfiguration { - - @FlowPreview - @Bean - fun productRoutes(productsHandler: ProductsHandler) = coRouter { - GET("/", productsHandler::findAll) - GET("/{id}", productsHandler::findOne) - GET("/{id}/stock", productsHandler::findOneInStock) - } -} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/WebClientConfiguration.kt b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/WebClientConfiguration.kt deleted file mode 100644 index 85938b8be2..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/WebClientConfiguration.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.nonblockingcoroutines.config - -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.web.reactive.function.client.WebClient - -@Configuration -class WebClientConfiguration { - - @Bean - fun webClient() = WebClient.builder().baseUrl("http://localhost:8080").build() -} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductController.kt b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductController.kt deleted file mode 100644 index 91b091859a..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductController.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.baeldung.nonblockingcoroutines.controller - -import com.baeldung.nonblockingcoroutines.model.Product -import com.baeldung.nonblockingcoroutines.repository.ProductRepository -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.http.MediaType -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PathVariable -import org.springframework.web.reactive.function.client.WebClient -import org.springframework.web.reactive.function.client.bodyToMono -import reactor.core.publisher.Flux -import reactor.core.publisher.Mono - -class ProductController { - @Autowired - lateinit var webClient: WebClient - @Autowired - lateinit var productRepository: ProductRepository - - @GetMapping("/{id}") - fun findOne(@PathVariable id: Int): Mono { - return productRepository - .getProductById(id) - } - - @GetMapping("/{id}/stock") - fun findOneInStock(@PathVariable id: Int): Mono { - val product = productRepository.getProductById(id) - - val stockQuantity = webClient.get() - .uri("/stock-service/product/$id/quantity") - .accept(MediaType.APPLICATION_JSON) - .retrieve() - .bodyToMono() - return product.zipWith(stockQuantity) { productInStock, stockQty -> - ProductStockView(productInStock, stockQty) - } - } - - @GetMapping("/stock-service/product/{id}/quantity") - fun getStockQuantity(): Mono { - return Mono.just(2) - } - - @GetMapping("/") - fun findAll(): Flux { - return productRepository.getAllProducts() - } -} diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductControllerCoroutines.kt b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductControllerCoroutines.kt deleted file mode 100644 index 464ed2773a..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductControllerCoroutines.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.baeldung.nonblockingcoroutines.controller - -import com.baeldung.nonblockingcoroutines.model.Product -import com.baeldung.nonblockingcoroutines.repository.ProductRepositoryCoroutines -import kotlinx.coroutines.CoroutineStart -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.async -import kotlinx.coroutines.coroutineScope -import kotlinx.coroutines.flow.Flow -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.http.MediaType.APPLICATION_JSON -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PathVariable -import org.springframework.web.reactive.function.client.WebClient -import org.springframework.web.reactive.function.client.awaitBody - -class ProductControllerCoroutines { - @Autowired - lateinit var webClient: WebClient - - @Autowired - lateinit var productRepository: ProductRepositoryCoroutines - - @GetMapping("/{id}") - suspend fun findOne(@PathVariable id: Int): Product? { - return productRepository.getProductById(id) - } - - @GetMapping("/{id}/stock") - suspend fun findOneInStock(@PathVariable id: Int): ProductStockView = coroutineScope { - val product: Deferred = async(start = CoroutineStart.LAZY) { - productRepository.getProductById(id) - } - val quantity: Deferred = async(start = CoroutineStart.LAZY) { - webClient.get() - .uri("/stock-service/product/$id/quantity") - .accept(APPLICATION_JSON) - .retrieve().awaitBody() - } - ProductStockView(product.await()!!, quantity.await()) - } - - @FlowPreview - @GetMapping("/") - fun findAll(): Flow { - return productRepository.getAllProducts() - } -} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductStockView.kt b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductStockView.kt deleted file mode 100644 index 44611fd1de..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductStockView.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.nonblockingcoroutines.controller - -import com.baeldung.nonblockingcoroutines.model.Product - -class ProductStockView(product: Product, var stockQuantity: Int) { - var id: Int = 0 - var name: String = "" - var price: Float = 0.0f - - init { - this.id = product.id - this.name = product.name - this.price = product.price - } -} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/handlers/ProductsHandler.kt b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/handlers/ProductsHandler.kt deleted file mode 100644 index e05b718e64..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/handlers/ProductsHandler.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.baeldung.nonblockingcoroutines.handlers - -import com.baeldung.nonblockingcoroutines.controller.ProductStockView -import com.baeldung.nonblockingcoroutines.model.Product -import com.baeldung.nonblockingcoroutines.repository.ProductRepositoryCoroutines -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.async -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.http.MediaType -import org.springframework.stereotype.Component -import org.springframework.web.reactive.function.client.WebClient -import org.springframework.web.reactive.function.client.awaitBody -import org.springframework.web.reactive.function.server.ServerRequest -import org.springframework.web.reactive.function.server.ServerResponse -import org.springframework.web.reactive.function.server.bodyAndAwait -import org.springframework.web.reactive.function.server.json - -@Component -class ProductsHandler( - @Autowired var webClient: WebClient, - @Autowired var productRepository: ProductRepositoryCoroutines) { - - @FlowPreview - suspend fun findAll(request: ServerRequest): ServerResponse = - ServerResponse.ok().json().bodyAndAwait(productRepository.getAllProducts()) - - suspend fun findOneInStock(request: ServerRequest): ServerResponse { - val id = request.pathVariable("id").toInt() - - val product: Deferred = GlobalScope.async { - productRepository.getProductById(id) - } - val quantity: Deferred = GlobalScope.async { - webClient.get() - .uri("/stock-service/product/$id/quantity") - .accept(MediaType.APPLICATION_JSON) - .retrieve().awaitBody() - } - return ServerResponse.ok().json().bodyAndAwait(ProductStockView(product.await()!!, quantity.await())) - } - - suspend fun findOne(request: ServerRequest): ServerResponse { - val id = request.pathVariable("id").toInt() - return ServerResponse.ok().json().bodyAndAwait(productRepository.getProductById(id)!!) - } -} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/model/Product.kt b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/model/Product.kt deleted file mode 100644 index c6dcbdc9c4..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/model/Product.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.baeldung.nonblockingcoroutines.model - -data class Product( - var id: Int = 0, - var name: String = "", - var price: Float = 0.0f -) diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepository.kt b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepository.kt deleted file mode 100644 index 64ffd014ad..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepository.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.baeldung.nonblockingcoroutines.repository - -import com.baeldung.nonblockingcoroutines.model.Product -import org.springframework.data.r2dbc.core.DatabaseClient -import org.springframework.stereotype.Repository -import reactor.core.publisher.Flux -import reactor.core.publisher.Mono - -@Repository -class ProductRepository(private val client: DatabaseClient) { - - fun getProductById(id: Int): Mono { - return client.execute("SELECT * FROM products WHERE id = $1") - .bind(0, id) - .`as`(Product::class.java) - .fetch() - .one() - } - - fun addNewProduct(name: String, price: Float): Mono { - return client.execute("INSERT INTO products (name, price) VALUES($1, $2)") - .bind(0, name) - .bind(1, price) - .then() - } - - fun getAllProducts(): Flux { - return client.select().from("products") - .`as`(Product::class.java) - .fetch() - .all() - } -} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepositoryCoroutines.kt b/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepositoryCoroutines.kt deleted file mode 100644 index f2667ec033..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepositoryCoroutines.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.baeldung.nonblockingcoroutines.repository - - -import com.baeldung.nonblockingcoroutines.model.Product -import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.reactive.awaitFirstOrNull -import kotlinx.coroutines.reactive.flow.asFlow -import org.springframework.data.r2dbc.core.DatabaseClient -import org.springframework.stereotype.Repository - -@Repository -class ProductRepositoryCoroutines(private val client: DatabaseClient) { - - suspend fun getProductById(id: Int): Product? = - client.execute("SELECT * FROM products WHERE id = $1") - .bind(0, id) - .`as`(Product::class.java) - .fetch() - .one() - .awaitFirstOrNull() - - suspend fun addNewProduct(name: String, price: Float) = - client.execute("INSERT INTO products (name, price) VALUES($1, $2)") - .bind(0, name) - .bind(1, price) - .then() - .awaitFirstOrNull() - - @FlowPreview - fun getAllProducts(): Flow = - client.select() - .from("products") - .`as`(Product::class.java) - .fetch() - .all() - .log() - .asFlow() -} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/resources/application.properties b/spring-boot-modules/spring-boot-kotlin/src/main/resources/application.properties deleted file mode 100644 index 0f84ff2d75..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/src/main/resources/application.properties +++ /dev/null @@ -1,8 +0,0 @@ -logging.level.org.springframework.data.r2dbc=DEBUG -logging.level.org.springframework.web.reactive.function.client.ExchangeFunctions=TRACE -spring.http.log-request-details=true -spring.h2.console.enabled=true -spring.datasource.username=sa -spring.datasource.url=jdbc:h2:mem:testdb -spring.datasource.password= -spring.datasource.dbname=testdb \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-kotlin/src/test/kotlin/com/baeldung/nonblockingcoroutines/ProductHandlerTest.kt b/spring-boot-modules/spring-boot-kotlin/src/test/kotlin/com/baeldung/nonblockingcoroutines/ProductHandlerTest.kt deleted file mode 100644 index 53b1d50f21..0000000000 --- a/spring-boot-modules/spring-boot-kotlin/src/test/kotlin/com/baeldung/nonblockingcoroutines/ProductHandlerTest.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.baeldung.nonblockingcoroutines - -import com.baeldung.nonblockingcoroutines.config.RouterConfiguration -import com.baeldung.nonblockingcoroutines.handlers.ProductsHandler -import com.baeldung.nonblockingcoroutines.model.Product -import com.baeldung.nonblockingcoroutines.repository.ProductRepositoryCoroutines -import kotlinx.coroutines.FlowPreview -import kotlinx.coroutines.reactive.flow.asFlow -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.BDDMockito.given -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration -import org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration -import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest -import org.springframework.boot.test.mock.mockito.MockBean -import org.springframework.test.context.junit4.SpringRunner -import org.springframework.test.web.reactive.server.WebTestClient -import org.springframework.test.web.reactive.server.expectBodyList -import org.springframework.web.reactive.function.client.WebClient -import reactor.core.publisher.Flux -import org.springframework.test.context.ContextConfiguration - -@WebFluxTest( - excludeAutoConfiguration = [ReactiveUserDetailsServiceAutoConfiguration::class, ReactiveSecurityAutoConfiguration::class] -) -@RunWith(SpringRunner::class) -@ContextConfiguration(classes = [ProductsHandler::class, RouterConfiguration::class]) -class ProductHandlerTest { - - @Autowired - private lateinit var client: WebTestClient - - @MockBean - private lateinit var webClient: WebClient - - @MockBean - private lateinit var productsRepository: ProductRepositoryCoroutines - - - @FlowPreview - @Test - public fun `get all products`() { - val productsFlow = Flux.just( - Product(1, "product1", 1000.0F), - Product(2, "product2", 2000.0F), - Product(3, "product3", 3000.0F) - ).asFlow() - given(productsRepository.getAllProducts()).willReturn(productsFlow) - client.get() - .uri("/") - .exchange() - .expectStatus() - .isOk - .expectBodyList() - } - -} diff --git a/spring-boot-modules/spring-boot-libraries-2/README.md b/spring-boot-modules/spring-boot-libraries-2/README.md index b0840798e3..4218dfc1be 100644 --- a/spring-boot-modules/spring-boot-libraries-2/README.md +++ b/spring-boot-modules/spring-boot-libraries-2/README.md @@ -4,4 +4,4 @@ This module contains articles about various Spring Boot libraries ### Relevant Articles: -- Running background jobs in Spring with JobRunr +- [Background Jobs in Spring with JobRunr](https://www.baeldung.com/java-jobrunr-spring) diff --git a/spring-boot-modules/spring-boot-libraries-2/pom.xml b/spring-boot-modules/spring-boot-libraries-2/pom.xml index 2633c8fad3..35dec54450 100644 --- a/spring-boot-modules/spring-boot-libraries-2/pom.xml +++ b/spring-boot-modules/spring-boot-libraries-2/pom.xml @@ -39,8 +39,8 @@ - 1.0.0 + 1.1.0 4.0.3 - \ No newline at end of file + diff --git a/spring-boot-modules/spring-boot-libraries-2/src/main/resources/application.properties b/spring-boot-modules/spring-boot-libraries-2/src/main/resources/application.properties index 69f5a7356e..bb2a31f1d9 100644 --- a/spring-boot-modules/spring-boot-libraries-2/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-libraries-2/src/main/resources/application.properties @@ -1,2 +1,2 @@ -org.jobrunr.background_job_server=true -org.jobrunr.dashboard=true +org.jobrunr.background-job-server.enabled=true +org.jobrunr.dashboard.enabled=true diff --git a/spring-boot-modules/spring-boot-libraries/README.md b/spring-boot-modules/spring-boot-libraries/README.md index 10c56ca576..6976435866 100644 --- a/spring-boot-modules/spring-boot-libraries/README.md +++ b/spring-boot-modules/spring-boot-libraries/README.md @@ -15,3 +15,21 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring Boot and Togglz Aspect](https://www.baeldung.com/spring-togglz) - [Getting Started with GraphQL and Spring Boot](https://www.baeldung.com/spring-graphql) - [An Introduction to Kong](https://www.baeldung.com/kong) + +### GraphQL sample queries + +Query +```shell script +curl \ +--request POST 'localhost:8081/graphql' \ +--header 'Content-Type: application/json' \ +--data-raw '{"query":"query {\n recentPosts(count: 2, offset: 0) {\n id\n title\n author {\n id\n posts {\n id\n }\n }\n }\n}"}' +``` + +Mutation +```shell script +curl \ +--request POST 'localhost:8081/graphql' \ +--header 'Content-Type: application/json' \ +--data-raw '{"query":"mutation {\n writePost(title: \"New Title\", author: \"Author2\", text: \"New Text\") {\n id\n category\n author {\n id\n name\n }\n }\n}"}' +``` diff --git a/spring-boot-modules/spring-boot-libraries/pom.xml b/spring-boot-modules/spring-boot-libraries/pom.xml index 3913babaa8..c96a881573 100644 --- a/spring-boot-modules/spring-boot-libraries/pom.xml +++ b/spring-boot-modules/spring-boot-libraries/pom.xml @@ -6,7 +6,6 @@ spring-boot-libraries spring-boot-libraries war - This is simple boot application for Spring boot actuator test com.baeldung.spring-boot-modules @@ -240,7 +239,7 @@ - com.baeldung.intro.App + com.baeldung.graphql.DemoApplication 8.5.11 2.4.1.Final 1.9.0 diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/demo/DemoApplication.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/DemoApplication.java similarity index 65% rename from spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/demo/DemoApplication.java rename to spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/DemoApplication.java index eb091b4695..1fd93af3b7 100644 --- a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/demo/DemoApplication.java +++ b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/DemoApplication.java @@ -1,13 +1,15 @@ -package com.baeldung.demo; +package com.baeldung.graphql; import com.baeldung.graphql.GraphqlConfiguration; import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; - +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; import org.springframework.context.annotation.Import; @SpringBootApplication @Import(GraphqlConfiguration.class) +@EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class}) public class DemoApplication { public static void main(String[] args) { diff --git a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/PostResolver.java b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/PostResolver.java index dbfde330ea..329d1f469a 100644 --- a/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/PostResolver.java +++ b/spring-boot-modules/spring-boot-libraries/src/main/java/com/baeldung/graphql/PostResolver.java @@ -1,7 +1,5 @@ package com.baeldung.graphql; -import java.util.Optional; - import com.coxautodev.graphql.tools.GraphQLResolver; public class PostResolver implements GraphQLResolver { @@ -11,7 +9,7 @@ public class PostResolver implements GraphQLResolver { this.authorDao = authorDao; } - public Optional getAuthor(Post post) { - return authorDao.getAuthor(post.getAuthorId()); + public Author getAuthor(Post post) { + return authorDao.getAuthor(post.getAuthorId()).orElseThrow(RuntimeException::new); } } diff --git a/spring-boot-modules/spring-boot-libraries/src/main/resources/demo.yml b/spring-boot-modules/spring-boot-libraries/src/main/resources/demo.yml new file mode 100644 index 0000000000..11e54c5449 --- /dev/null +++ b/spring-boot-modules/spring-boot-libraries/src/main/resources/demo.yml @@ -0,0 +1,2 @@ +server: + port: 8081 diff --git a/spring-boot-modules/spring-boot/src/main/resources/graphql/blog.graphqls b/spring-boot-modules/spring-boot-libraries/src/main/resources/graphql/post.graphqls similarity index 95% rename from spring-boot-modules/spring-boot/src/main/resources/graphql/blog.graphqls rename to spring-boot-modules/spring-boot-libraries/src/main/resources/graphql/post.graphqls index aa0c8757e9..0e42f7255c 100644 --- a/spring-boot-modules/spring-boot/src/main/resources/graphql/blog.graphqls +++ b/spring-boot-modules/spring-boot-libraries/src/main/resources/graphql/post.graphqls @@ -3,7 +3,7 @@ type Post { title: String! text: String! category: String - author: Author + author: Author! } type Author { diff --git a/spring-boot-modules/spring-boot-logging-log4j2/src/test/java/org/baeldung/SpringContextTest.java b/spring-boot-modules/spring-boot-logging-log4j2/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-boot-modules/spring-boot-logging-log4j2/src/test/java/org/baeldung/SpringContextTest.java rename to spring-boot-modules/spring-boot-logging-log4j2/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-boot-modules/spring-boot-mvc-3/README.md b/spring-boot-modules/spring-boot-mvc-3/README.md index 796ab72425..bc3eb9e496 100644 --- a/spring-boot-modules/spring-boot-mvc-3/README.md +++ b/spring-boot-modules/spring-boot-mvc-3/README.md @@ -8,4 +8,5 @@ This module contains articles about Spring Web MVC in Spring Boot projects. - [Download an Image or a File with Spring MVC](https://www.baeldung.com/spring-controller-return-image-file) - [Spring MVC Async vs Spring WebFlux](https://www.baeldung.com/spring-mvc-async-vs-webflux) - [Differences in @Valid and @Validated Annotations in Spring](https://www.baeldung.com/spring-valid-vs-validated) +- [CharacterEncodingFilter In SpringBoot](https://www.baeldung.com/spring-boot-characterencodingfilter) - More articles: [[prev -->]](/spring-boot-modules/spring-boot-mvc-2) diff --git a/spring-boot-modules/spring-boot-mvc-3/pom.xml b/spring-boot-modules/spring-boot-mvc-3/pom.xml index 1290b0432f..5a5d4c3cd8 100644 --- a/spring-boot-modules/spring-boot-mvc-3/pom.xml +++ b/spring-boot-modules/spring-boot-mvc-3/pom.xml @@ -37,8 +37,4 @@ - - 2.7 - - diff --git a/spring-boot-modules/spring-boot-mvc-birt/pom.xml b/spring-boot-modules/spring-boot-mvc-birt/pom.xml index 0ab744bb26..4963cc3036 100644 --- a/spring-boot-modules/spring-boot-mvc-birt/pom.xml +++ b/spring-boot-modules/spring-boot-mvc-birt/pom.xml @@ -4,11 +4,12 @@ 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.spring-boot-modules - spring-boot-modules - 1.0.0-SNAPSHOT - ../ + org.springframework.boot + spring-boot-starter-parent + 2.1.1.RELEASE + spring-boot-mvc-birt @@ -19,10 +20,6 @@ Module For Spring Boot Integration with BIRT - - org.springframework.boot - spring-boot-starter - org.springframework.boot @@ -51,17 +48,14 @@ org.eclipse.birt.runtime_4.8.0-20180626 ${eclipse.birt.runtime.version} - log4j log4j ${log4j.version} - org.projectlombok lombok - ${lombok.version} provided @@ -81,6 +75,7 @@ 1.8 1.8 4.8.0 + 1.2.17 diff --git a/spring-boot-modules/spring-boot-mvc-birt/src/main/resources/log4j.properties b/spring-boot-modules/spring-boot-mvc-birt/src/main/resources/log4j.properties new file mode 100644 index 0000000000..e4fcb01308 --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-birt/src/main/resources/log4j.properties @@ -0,0 +1,9 @@ +# Set root logger level to DEBUG and its only appender to A1. +log4j.rootLogger=DEBUG, A1 + +# A1 is set to be a ConsoleAppender. +log4j.appender.A1=org.apache.log4j.ConsoleAppender + +# A1 uses PatternLayout. +log4j.appender.A1.layout=org.apache.log4j.PatternLayout +log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-mvc-birt/src/test/java/com/baeldung/birt/engine/SpringContextTest.java b/spring-boot-modules/spring-boot-mvc-birt/src/test/java/com/baeldung/birt/engine/SpringContextTest.java new file mode 100644 index 0000000000..5235a494df --- /dev/null +++ b/spring-boot-modules/spring-boot-mvc-birt/src/test/java/com/baeldung/birt/engine/SpringContextTest.java @@ -0,0 +1,13 @@ +package com.baeldung.birt.engine; + +import org.junit.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class SpringContextTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + + } +} diff --git a/spring-boot-modules/spring-boot-properties-2/src/main/java/com/baeldung/properties/value/defaults/ValuesWithDefaultsApp.java b/spring-boot-modules/spring-boot-properties-2/src/main/java/com/baeldung/properties/value/defaults/ValuesWithDefaultsApp.java index 72fa0e03c0..2a2b535be7 100644 --- a/spring-boot-modules/spring-boot-properties-2/src/main/java/com/baeldung/properties/value/defaults/ValuesWithDefaultsApp.java +++ b/spring-boot-modules/spring-boot-properties-2/src/main/java/com/baeldung/properties/value/defaults/ValuesWithDefaultsApp.java @@ -51,21 +51,21 @@ public class ValuesWithDefaultsApp { @PostConstruct public void afterInitialize() { // strings - Assert.isTrue(stringWithDefaultValue.equals("my default value")); - Assert.isTrue(stringWithBlankDefaultValue.equals("")); + Assert.isTrue(stringWithDefaultValue.equals("my default value"), "unexpected value for stringWithDefaultValue"); + Assert.isTrue(stringWithBlankDefaultValue.equals(""), "unexpected value for stringWithBlankDefaultValue"); // other primitives - Assert.isTrue(booleanWithDefaultValue); - Assert.isTrue(intWithDefaultValue == 42); + Assert.isTrue(booleanWithDefaultValue, "unexpected value for booleanWithDefaultValue"); + Assert.isTrue(intWithDefaultValue == 42, "unexpected value for intWithDefaultValue"); // arrays List stringListValues = Arrays.asList("one", "two", "three"); - Assert.isTrue(Arrays.asList(stringArrayWithDefaults).containsAll(stringListValues)); + Assert.isTrue(Arrays.asList(stringArrayWithDefaults).containsAll(stringListValues), "unexpected value for stringArrayWithDefaults"); List intListValues = Arrays.asList(1, 2, 3); - Assert.isTrue(Arrays.asList(ArrayUtils.toObject(intArrayWithDefaults)).containsAll(intListValues)); + Assert.isTrue(Arrays.asList(ArrayUtils.toObject(intArrayWithDefaults)).containsAll(intListValues), "unexpected value for intArrayWithDefaults"); // SpEL - Assert.isTrue(spelWithDefaultValue.equals("my default system property value")); + Assert.isTrue(spelWithDefaultValue.equals("my default system property value"), "unexpected value for spelWithDefaultValue"); } } diff --git a/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java b/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java index 60ba4cc108..1abb643d75 100644 --- a/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java +++ b/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/lists/ListsPropertiesUnitTest.java @@ -13,6 +13,7 @@ import java.util.Collections; import java.util.List; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertArrayEquals; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SpringListPropertiesApplication.class) @@ -47,7 +48,7 @@ public class ListsPropertiesUnitTest { @Test public void whenContextIsInitialized_thenInjectedArrayContainsExpectedValues() { - assertEquals(new String[] {"Baeldung", "dot", "com"}, arrayOfStrings); + assertArrayEquals(new String[] {"Baeldung", "dot", "com"}, arrayOfStrings); } @Test @@ -82,7 +83,7 @@ public class ListsPropertiesUnitTest { String[] arrayOfStrings = environment.getProperty("arrayOfStrings", String[].class); List listOfStrings = (List)environment.getProperty("arrayOfStrings", List.class); - assertEquals(new String[] {"Baeldung", "dot", "com"}, arrayOfStrings); + assertArrayEquals(new String[] {"Baeldung", "dot", "com"}, arrayOfStrings); assertEquals(Arrays.asList("Baeldung", "dot", "com"), listOfStrings); } } diff --git a/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/yamllist/YamlComplexListsUnitTest.java b/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/yamllist/YamlComplexListsUnitTest.java index 6dc5d61d09..ce9ec38551 100644 --- a/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/yamllist/YamlComplexListsUnitTest.java +++ b/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/yamllist/YamlComplexListsUnitTest.java @@ -6,14 +6,14 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import com.baeldung.properties.yamllist.pojo.ApplicationProps; @ExtendWith(SpringExtension.class) -@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class) +@ContextConfiguration(initializers = ConfigDataApplicationContextInitializer.class) @EnableConfigurationProperties(value = ApplicationProps.class) class YamlComplexListsUnitTest { diff --git a/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/yamllist/YamlSimpleListUnitTest.java b/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/yamllist/YamlSimpleListUnitTest.java index 475a73c7d7..5315c7b9bc 100644 --- a/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/yamllist/YamlSimpleListUnitTest.java +++ b/spring-boot-modules/spring-boot-properties-2/src/test/java/com/baeldung/properties/yamllist/YamlSimpleListUnitTest.java @@ -6,14 +6,14 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import com.baeldung.properties.yamllist.pojo.ApplicationProps; @ExtendWith(SpringExtension.class) -@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class) +@ContextConfiguration(initializers = ConfigDataApplicationContextInitializer.class) @EnableConfigurationProperties(value = ApplicationProps.class) class YamlSimpleListUnitTest { diff --git a/spring-boot-modules/spring-boot-properties-3/pom.xml b/spring-boot-modules/spring-boot-properties-3/pom.xml index 44e2ef52ac..809fd6e2d4 100644 --- a/spring-boot-modules/spring-boot-properties-3/pom.xml +++ b/spring-boot-modules/spring-boot-properties-3/pom.xml @@ -26,12 +26,6 @@ org.springframework.boot spring-boot-starter-test test - - - org.junit.vintage - junit-vintage-engine - - org.springframework.boot diff --git a/spring-boot-modules/spring-boot-properties-3/src/main/resources/application-multidocument-integration.properties b/spring-boot-modules/spring-boot-properties-3/src/main/resources/application-multidocument-integration.properties new file mode 100644 index 0000000000..f3bac4c614 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties-3/src/main/resources/application-multidocument-integration.properties @@ -0,0 +1,4 @@ +spring.datasource.password=password +spring.datasource.url=jdbc:mysql://localhost:3306/db_integration +spring.datasource.username=user +bael.property=integrationValue \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties-3/src/main/resources/application.properties b/spring-boot-modules/spring-boot-properties-3/src/main/resources/application.properties index eace1f0e46..a079837942 100644 --- a/spring-boot-modules/spring-boot-properties-3/src/main/resources/application.properties +++ b/spring-boot-modules/spring-boot-properties-3/src/main/resources/application.properties @@ -8,4 +8,22 @@ spring.datasource.url=jdbc:h2:dev spring.datasource.username=SA spring.datasource.password=password app.name=MyApp -app.description=${app.name} is a Spring Boot application \ No newline at end of file +app.description=${app.name} is a Spring Boot application +logging.file.name=myapplication.log +bael.property=defaultValue +bael.otherProperty=defaultOtherValue +#--- +spring.config.activate.on-profile=multidocument-dev +spring.datasource.password=password +spring.datasource.url=jdbc:h2:dev +spring.datasource.username=SA +bael.property=devValue +#--- +spring.config.activate.on-profile=multidocument-integration-extension +bael.otherProperty=integrationExtensionOtherValue +#--- +spring.config.activate.on-profile=multidocument-prod +spring.datasource.password=password +spring.datasource.url=jdbc:h2:prod +spring.datasource.username=prodUser +bael.property=prodValue \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties-3/src/main/resources/application.yml b/spring-boot-modules/spring-boot-properties-3/src/main/resources/application.yml index 00baeade9c..10570bb738 100644 --- a/spring-boot-modules/spring-boot-properties-3/src/main/resources/application.yml +++ b/spring-boot-modules/spring-boot-properties-3/src/main/resources/application.yml @@ -1,17 +1,21 @@ -logging: - file: - name: myapplication.log +bael: + root-level-property: defaultRootLevelValue spring: - datasource: - password: 'password' - url: jdbc:h2:dev - username: SA + profiles: + group: + multidocument-integration: multidocument-integration-extension --- spring: + config: + activate: + on-profile: multidocument-staging datasource: password: 'password' - url: jdbc:mysql://localhost:3306/db_production - username: user + url: jdbc:h2:staging + username: SA +bael: + property: stagingValue +--- application: servers: - ip: '127.0.0.1' diff --git a/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/DefaultMultidocumentFilesIntegrationTest.java b/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/DefaultMultidocumentFilesIntegrationTest.java new file mode 100644 index 0000000000..af1f7f705f --- /dev/null +++ b/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/DefaultMultidocumentFilesIntegrationTest.java @@ -0,0 +1,26 @@ +package com.baeldung.boot.properties.multidocument; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; + +import com.baeldung.boot.properties.DemoApplication; + +@SpringBootTest(classes = { DemoApplication.class }, webEnvironment = WebEnvironment.MOCK) +public class DefaultMultidocumentFilesIntegrationTest { + + @Value("${bael.property}") + private String baelCustomProperty; + + @Value("${bael.root-level-property}") + private String baelRootProperty; + + @Test + public void givenDefaultProfileActive_whenApplicationStarts_thenDefaultPropertiesUser() { + assertThat(baelCustomProperty).isEqualTo("defaultValue"); + assertThat(baelRootProperty).isEqualTo("defaultRootLevelValue"); + } +} diff --git a/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/DevMultidocumentFilesIntegrationTest.java b/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/DevMultidocumentFilesIntegrationTest.java new file mode 100644 index 0000000000..54188595c0 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/DevMultidocumentFilesIntegrationTest.java @@ -0,0 +1,28 @@ +package com.baeldung.boot.properties.multidocument; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.ActiveProfiles; + +import com.baeldung.boot.properties.DemoApplication; + +@SpringBootTest(classes = { DemoApplication.class }, webEnvironment = WebEnvironment.MOCK) +@ActiveProfiles("multidocument-dev") +public class DevMultidocumentFilesIntegrationTest { + + @Value("${bael.property}") + private String baelCustomProperty; + + @Value("${bael.root-level-property}") + private String baelRootProperty; + + @Test + public void givenDefaultProfileActive_whenApplicationStarts_thenDefaultPropertiesUser() { + assertThat(baelCustomProperty).isEqualTo("devValue"); + assertThat(baelRootProperty).isEqualTo("defaultRootLevelValue"); + } +} diff --git a/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/IntegrationMultidocumentFilesIntegrationTest.java b/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/IntegrationMultidocumentFilesIntegrationTest.java new file mode 100644 index 0000000000..e0727154d0 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/IntegrationMultidocumentFilesIntegrationTest.java @@ -0,0 +1,32 @@ +package com.baeldung.boot.properties.multidocument; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.ActiveProfiles; + +import com.baeldung.boot.properties.DemoApplication; + +@SpringBootTest(classes = { DemoApplication.class }, webEnvironment = WebEnvironment.MOCK) +@ActiveProfiles("multidocument-integration") +public class IntegrationMultidocumentFilesIntegrationTest { + + @Value("${bael.property}") + private String baelCustomProperty; + + @Value("${bael.otherProperty}") + private String baelCustomOtherProperty; + + @Value("${bael.root-level-property}") + private String baelRootProperty; + + @Test + public void givenProductionProfileActive_whenApplicationStarts_thenDefaultPropertiesUser() { + assertThat(baelCustomProperty).isEqualTo("integrationValue"); + assertThat(baelCustomOtherProperty).isEqualTo("integrationExtensionOtherValue"); + assertThat(baelRootProperty).isEqualTo("defaultRootLevelValue"); + } +} diff --git a/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/ProdMultidocumentFilesIntegrationTest.java b/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/ProdMultidocumentFilesIntegrationTest.java new file mode 100644 index 0000000000..9270995da0 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/ProdMultidocumentFilesIntegrationTest.java @@ -0,0 +1,28 @@ +package com.baeldung.boot.properties.multidocument; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.ActiveProfiles; + +import com.baeldung.boot.properties.DemoApplication; + +@SpringBootTest(classes = { DemoApplication.class }, webEnvironment = WebEnvironment.MOCK) +@ActiveProfiles("multidocument-prod") +public class ProdMultidocumentFilesIntegrationTest { + + @Value("${bael.property}") + private String baelCustomProperty; + + @Value("${bael.root-level-property}") + private String baelRootProperty; + + @Test + public void givenProductionProfileActive_whenApplicationStarts_thenDefaultPropertiesUser() { + assertThat(baelCustomProperty).isEqualTo("prodValue"); + assertThat(baelRootProperty).isEqualTo("defaultRootLevelValue"); + } +} diff --git a/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/StagingMultidocumentFilesIntegrationTest.java b/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/StagingMultidocumentFilesIntegrationTest.java new file mode 100644 index 0000000000..8040c93ee0 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties-3/src/test/java/com/baeldung/boot/properties/multidocument/StagingMultidocumentFilesIntegrationTest.java @@ -0,0 +1,28 @@ +package com.baeldung.boot.properties.multidocument; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.ActiveProfiles; + +import com.baeldung.boot.properties.DemoApplication; + +@SpringBootTest(classes = { DemoApplication.class }, webEnvironment = WebEnvironment.MOCK) +@ActiveProfiles("multidocument-staging") +public class StagingMultidocumentFilesIntegrationTest { + + @Value("${bael.property}") + private String baelCustomProperty; + + @Value("${bael.root-level-property}") + private String baelRootProperty; + + @Test + public void givenProductionProfileActive_whenApplicationStarts_thenDefaultPropertiesUser() { + assertThat(baelCustomProperty).isEqualTo("stagingValue"); + assertThat(baelRootProperty).isEqualTo("defaultRootLevelValue"); + } +} diff --git a/spring-boot-modules/spring-boot-properties/pom.xml b/spring-boot-modules/spring-boot-properties/pom.xml index cfdc71b8d6..40668f47fd 100644 --- a/spring-boot-modules/spring-boot-properties/pom.xml +++ b/spring-boot-modules/spring-boot-properties/pom.xml @@ -1,6 +1,7 @@ - + 4.0.0 @@ -47,12 +48,10 @@ org.apache.httpcomponents httpcore - ${httpcore.version} org.springframework.boot spring-boot-configuration-processor - ${configuration-processor.version} true @@ -126,15 +125,21 @@ + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + + 1.8 - Greenwich.SR1 + 2020.0.0-M5 1.10 20.0 - 4.4.11 @ - 2.2.4.RELEASE - + com.baeldung.yaml.MyApplication diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configurationproperties/ConfigurationScanDemoApplication.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configurationproperties/ConfigurationScanDemoApplication.java new file mode 100644 index 0000000000..b2339b9980 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configurationproperties/ConfigurationScanDemoApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.configurationproperties; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.ConfigurationPropertiesScan; + +@SpringBootApplication +@ConfigurationPropertiesScan("com.baeldung.configurationproperties") +public class ConfigurationScanDemoApplication{ + + public static void main(String[] args) { + SpringApplication.run(ConfigurationScanDemoApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configurationproperties/EnableConfigurationDemoApplication.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configurationproperties/EnableConfigurationDemoApplication.java new file mode 100644 index 0000000000..69b8c2802b --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/configurationproperties/EnableConfigurationDemoApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.configurationproperties; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.properties.EnableConfigurationProperties; + +@SpringBootApplication +@EnableConfigurationProperties(ConfigProperties.class) +public class EnableConfigurationDemoApplication { + public static void main(String[] args) { + SpringApplication.run(EnableConfigurationDemoApplication.class, args); + } +} 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 1e5e88921a..c435f9e320 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 @@ -1,13 +1,10 @@ package com.baeldung.properties; -import com.baeldung.buildproperties.Application; +import com.baeldung.configurationproperties.ConfigProperties; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.context.annotation.ComponentScan; -import com.baeldung.configurationproperties.ConfigProperties; - @SpringBootApplication @ComponentScan(basePackageClasses = {ConfigProperties.class, AdditionalProperties.class}) public class ConfigPropertiesDemoApplication { diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/core/ComponentInXmlUsingProperties.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/core/ComponentInXmlUsingProperties.java deleted file mode 100644 index 675c72e642..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/core/ComponentInXmlUsingProperties.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.properties.core; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.env.Environment; - -public class ComponentInXmlUsingProperties implements InitializingBean { - - @Autowired - private Environment env; - - @Value("${key.something}") - private String injectedProperty; - - public ComponentInXmlUsingProperties(final String propertyValue) { - super(); - - System.out.println("Constructor Injection - Property Value resolved to: " + propertyValue); - } - - // - - @Override - public void afterPropertiesSet() throws Exception { - System.out.println("in afterPropertiesSet via @Value: " + injectedProperty); - System.out.println("in afterPropertiesSet Environment: " + env.getProperty("key.something")); - } - -} diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/external/ExternalPropertiesWithXmlConfig.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/external/ExternalPropertiesWithXmlConfig.java deleted file mode 100644 index 9080e3d0ba..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/external/ExternalPropertiesWithXmlConfig.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.baeldung.properties.external; - -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; - -@Configuration -@ImportResource("classpath:configForProperties.xml") -@ComponentScan("com.baeldung.core") -public class ExternalPropertiesWithXmlConfig { - - public ExternalPropertiesWithXmlConfig() { - super(); - } - -} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/external/ExternalPropertiesWithXmlConfigOne.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/external/ExternalPropertiesWithXmlConfigOne.java deleted file mode 100644 index f45f5b6a03..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/external/ExternalPropertiesWithXmlConfigOne.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.baeldung.properties.external; - -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; - -@Configuration -@ImportResource("classpath:configForPropertiesOne.xml") -@ComponentScan("com.baeldung.core") -public class ExternalPropertiesWithXmlConfigOne { - - public ExternalPropertiesWithXmlConfigOne() { - super(); - } - -} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/external/ExternalPropertiesWithXmlConfigTwo.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/external/ExternalPropertiesWithXmlConfigTwo.java deleted file mode 100644 index 38ecdd2aae..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/external/ExternalPropertiesWithXmlConfigTwo.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.baeldung.properties.external; - -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; - -@Configuration -@ImportResource("classpath:basicConfigForPropertiesTwo.xml") -public class ExternalPropertiesWithXmlConfigTwo { - - public ExternalPropertiesWithXmlConfigTwo() { - super(); - } - -} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/reloading/configs/ReloadablePropertySource.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/reloading/configs/ReloadablePropertySource.java index 6d76a2e1e2..e63dc1eb54 100644 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/reloading/configs/ReloadablePropertySource.java +++ b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/reloading/configs/ReloadablePropertySource.java @@ -15,7 +15,7 @@ public class ReloadablePropertySource extends PropertySource { } public ReloadablePropertySource(String name, String path) { - super(StringUtils.isEmpty(name) ? path : name); + super(!StringUtils.hasText(name) ? path : name); try { this.propertiesConfiguration = new PropertiesConfiguration(path); FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy(); diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/spring/PropertiesWithPlaceHolderConfigurer.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/spring/PropertiesWithPlaceHolderConfigurer.java deleted file mode 100644 index 512ecda266..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/spring/PropertiesWithPlaceHolderConfigurer.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.properties.spring; - -import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class PropertiesWithPlaceHolderConfigurer { - - public PropertiesWithPlaceHolderConfigurer() { - super(); - } - - @Bean - public PropertyPlaceholderConfigurer propertyConfigurer() { - final PropertyPlaceholderConfigurer props = new PropertyPlaceholderConfigurer(); - props.setSystemPropertiesMode(PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_FALLBACK); - return props; - } - -} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/spring/PropertyPlaceholderConfig.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/spring/PropertyPlaceholderConfig.java deleted file mode 100644 index 0d1eb4ccf7..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/properties/spring/PropertyPlaceholderConfig.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.baeldung.properties.spring; - -import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.*; - -@Configuration -public class PropertyPlaceholderConfig { - - public PropertyPlaceholderConfig(){ - super(); - } - - @Bean - public static PropertyPlaceholderConfigurer properties() { - PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer(); - Resource[] resources = new ClassPathResource[]{ new ClassPathResource("foo.properties") }; - ppc.setLocations( resources ); - ppc.setIgnoreUnresolvablePlaceholders( true ); - return ppc; - } -} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/MyApplication.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/MyApplication.java index f3cfff57b7..27195911bd 100644 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/MyApplication.java +++ b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/MyApplication.java @@ -5,15 +5,13 @@ */ package com.baeldung.yaml; -import java.util.Collections; +import com.baeldung.yaml.YAMLConfig.Idm; +import com.baeldung.yaml.YAMLConfig.Service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import com.baeldung.yaml.YAMLConfig.Idm; -import com.baeldung.yaml.YAMLConfig.Service; - @SpringBootApplication public class MyApplication implements CommandLineRunner { @@ -28,6 +26,7 @@ public class MyApplication implements CommandLineRunner { public void run(String... args) throws Exception { System.out.println("using environment:" + myConfig.getEnvironment()); System.out.println("name:" + myConfig.getName()); + System.out.println("enabled:" + myConfig.isEnabled()); System.out.println("servers:" + myConfig.getServers()); if ("testing".equalsIgnoreCase(myConfig.getEnvironment())) { diff --git a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/YAMLConfig.java b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/YAMLConfig.java index 83c083734c..4099ded1aa 100644 --- a/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/YAMLConfig.java +++ b/spring-boot-modules/spring-boot-properties/src/main/java/com/baeldung/yaml/YAMLConfig.java @@ -15,6 +15,7 @@ import org.springframework.context.annotation.Configuration; public class YAMLConfig { private String name; private String environment; + private boolean enabled; private List servers = new ArrayList(); private List external = new ArrayList(); private Map map = new HashMap(); @@ -43,7 +44,15 @@ public class YAMLConfig { public void setEnvironment(String environment) { this.environment = environment; } - + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + public Component getComponent() { return component; } diff --git a/spring-boot-modules/spring-boot-properties/src/main/resources/application.yml b/spring-boot-modules/spring-boot-properties/src/main/resources/application.yml index 30e64f9d35..61d462bb5a 100644 --- a/spring-boot-modules/spring-boot-properties/src/main/resources/application.yml +++ b/spring-boot-modules/spring-boot-properties/src/main/resources/application.yml @@ -6,9 +6,12 @@ spring: --- spring: - profiles: test + config: + activate: + on-profile: test name: test-YAML environment: testing +enabled: false servers: - www.abc.test.com - www.xyz.test.com @@ -36,9 +39,12 @@ component: --- spring: - profiles: prod + config: + activate: + on-profile: prod name: prod-YAML environment: production +enabled: true servers: - www.abc.com - www.xyz.com @@ -46,9 +52,12 @@ servers: --- spring: - profiles: dev + config: + activate: + on-profile: dev name: ${DEV_NAME:dev-YAML} environment: development +enabled: true servers: - www.abc.dev.com - www.xyz.dev.com diff --git a/spring-boot-modules/spring-boot-properties/src/main/resources/basicConfigForProperties.xml b/spring-boot-modules/spring-boot-properties/src/main/resources/basicConfigForProperties.xml deleted file mode 100644 index e50de084f0..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/main/resources/basicConfigForProperties.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/main/resources/basicConfigForPropertiesOne.xml b/spring-boot-modules/spring-boot-properties/src/main/resources/basicConfigForPropertiesOne.xml deleted file mode 100644 index 01b297d437..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/main/resources/basicConfigForPropertiesOne.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/main/resources/basicConfigForPropertiesTwo.xml b/spring-boot-modules/spring-boot-properties/src/main/resources/basicConfigForPropertiesTwo.xml deleted file mode 100644 index 1d470c4340..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/main/resources/basicConfigForPropertiesTwo.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/main/resources/configForDbProperties.xml b/spring-boot-modules/spring-boot-properties/src/main/resources/configForDbProperties.xml deleted file mode 100644 index 00fd5f0508..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/main/resources/configForDbProperties.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/main/resources/configForProperties.xml b/spring-boot-modules/spring-boot-properties/src/main/resources/configForProperties.xml deleted file mode 100644 index 16db00ace3..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/main/resources/configForProperties.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/main/resources/configForPropertiesOne.xml b/spring-boot-modules/spring-boot-properties/src/main/resources/configForPropertiesOne.xml deleted file mode 100644 index 53072d89bb..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/main/resources/configForPropertiesOne.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/main/resources/configForPropertyPlaceholderBeans.xml b/spring-boot-modules/spring-boot-properties/src/main/resources/configForPropertyPlaceholderBeans.xml deleted file mode 100644 index a296cf5169..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/main/resources/configForPropertyPlaceholderBeans.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - classpath:foo.properties - - - - - - - - - classpath:foo.properties - - - - - \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/configurationproperties/ConfigPropertiesIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/configurationproperties/ConfigPropertiesIntegrationTest.java index 3b80fa66fe..7f239cbcff 100644 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/configurationproperties/ConfigPropertiesIntegrationTest.java +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/configurationproperties/ConfigPropertiesIntegrationTest.java @@ -4,12 +4,10 @@ import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.configurationproperties.ConfigProperties; import com.baeldung.properties.AdditionalProperties; import com.baeldung.properties.ConfigPropertiesDemoApplication; @@ -19,34 +17,34 @@ import com.baeldung.properties.ConfigPropertiesDemoApplication; public class ConfigPropertiesIntegrationTest { @Autowired - private ConfigProperties properties; + private ConfigProperties configProperties; @Autowired private AdditionalProperties additionalProperties; @Test public void whenSimplePropertyQueriedthenReturnsProperty() throws Exception { - Assert.assertTrue("From address is read as null!", properties.getFrom() != null); + Assert.assertTrue("From address is read as null!", configProperties.getFrom() != null); } @Test public void whenListPropertyQueriedthenReturnsProperty() throws Exception { - Assert.assertTrue("Couldn't bind list property!", properties.getDefaultRecipients().size() == 2); - Assert.assertTrue("Incorrectly bound list property. Expected 2 entries!", properties.getDefaultRecipients().size() == 2); + Assert.assertTrue("Couldn't bind list property!", configProperties.getDefaultRecipients().size() == 2); + Assert.assertTrue("Incorrectly bound list property. Expected 2 entries!", configProperties.getDefaultRecipients().size() == 2); } @Test public void whenMapPropertyQueriedthenReturnsProperty() throws Exception { - Assert.assertTrue("Couldn't bind map property!", properties.getAdditionalHeaders() != null); - Assert.assertTrue("Incorrectly bound map property. Expected 3 Entries!", properties.getAdditionalHeaders().size() == 3); + Assert.assertTrue("Couldn't bind map property!", configProperties.getAdditionalHeaders() != null); + Assert.assertTrue("Incorrectly bound map property. Expected 3 Entries!", configProperties.getAdditionalHeaders().size() == 3); } @Test public void whenObjectPropertyQueriedthenReturnsProperty() throws Exception { - Assert.assertTrue("Couldn't bind map property!", properties.getCredentials() != null); - Assert.assertTrue("Incorrectly bound object property!", properties.getCredentials().getAuthMethod().equals("SHA1")); - Assert.assertTrue("Incorrectly bound object property!", properties.getCredentials().getUsername().equals("john")); - Assert.assertTrue("Incorrectly bound object property!", properties.getCredentials().getPassword().equals("password")); + Assert.assertTrue("Couldn't bind map property!", configProperties.getCredentials() != null); + Assert.assertTrue("Incorrectly bound object property!", configProperties.getCredentials().getAuthMethod().equals("SHA1")); + Assert.assertTrue("Incorrectly bound object property!", configProperties.getCredentials().getUsername().equals("john")); + Assert.assertTrue("Incorrectly bound object property!", configProperties.getCredentials().getPassword().equals("password")); } @Test diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/additionalproperties/AdditionalPropertiesFilesIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/additionalproperties/AdditionalPropertiesFilesIntegrationTest.java new file mode 100644 index 0000000000..0f1f4e0b13 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/additionalproperties/AdditionalPropertiesFilesIntegrationTest.java @@ -0,0 +1,29 @@ +package com.baeldung.properties.additionalproperties; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@ActiveProfiles("default") +@SpringBootTest(classes = { AdditionalPropertiesTestConfig.class }) +public class AdditionalPropertiesFilesIntegrationTest { + + Logger logger = LoggerFactory.getLogger(AdditionalPropertiesFilesIntegrationTest.class); + + @Value("${baeldung.additionalProperty}") + private String additionalProperty; + + @Value("${baeldung.otherProperty}") + private String otherProperty; + + @Test + public void givenMultidocumentPropertiesFileWhenBootContextLoadedThenDocumentProcessedCorrectly() { + assertThat(additionalProperty).isEqualTo("additionalValue2"); + assertThat(otherProperty).isEqualTo("latterValue"); + } +} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/additionalproperties/AdditionalPropertiesTestConfig.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/additionalproperties/AdditionalPropertiesTestConfig.java new file mode 100644 index 0000000000..9b3483a6c1 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/additionalproperties/AdditionalPropertiesTestConfig.java @@ -0,0 +1,10 @@ +package com.baeldung.properties.additionalproperties; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan("com.baeldung.properties.additionalproperties") +public class AdditionalPropertiesTestConfig { + +} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/basic/PropertiesWithMultipleXmlsIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/basic/PropertiesWithMultipleXmlsIntegrationTest.java deleted file mode 100644 index c3af2dc1d8..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/basic/PropertiesWithMultipleXmlsIntegrationTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.properties.basic; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.env.Environment; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = { "classpath:basicConfigForPropertiesOne.xml", "classpath:basicConfigForPropertiesTwo.xml" }) -public class PropertiesWithMultipleXmlsIntegrationTest { - - @Autowired - private Environment env; - - @Value("${key.something}") - private String injectedProperty; - - @Test - public final void givenContextIsInitialized_thenNoException() { - System.out.println("in test via @Value: " + injectedProperty); - System.out.println("in test Environment: " + env.getProperty("key.something")); - } - -} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/basic/PropertiesWithXmlIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/basic/PropertiesWithXmlIntegrationTest.java deleted file mode 100644 index 85c4ac34e2..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/basic/PropertiesWithXmlIntegrationTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.baeldung.properties.basic; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.env.Environment; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = "classpath:basicConfigForProperties.xml") -public class PropertiesWithXmlIntegrationTest { - - @Autowired - private Environment env; - - @Value("${key.something}") - private String injectedProperty; - - @Test - public final void givenContextIsInitialized_thenNoException() { - System.out.println("in test via @Value: " + injectedProperty); - System.out.println("in test Environment: " + env.getProperty("key.something")); - } - -} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/external/ExternalPropertiesWithMultipleXmlsIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/external/ExternalPropertiesWithMultipleXmlsIntegrationTest.java deleted file mode 100644 index 018c655ec2..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/external/ExternalPropertiesWithMultipleXmlsIntegrationTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.baeldung.properties.external; - -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.env.Environment; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.support.AnnotationConfigContextLoader; - -import com.baeldung.properties.external.ExternalPropertiesWithXmlConfigOne; -import com.baeldung.properties.external.ExternalPropertiesWithXmlConfigTwo; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { ExternalPropertiesWithXmlConfigOne.class, ExternalPropertiesWithXmlConfigTwo.class }, loader = AnnotationConfigContextLoader.class) -@Ignore("manual only") -public class ExternalPropertiesWithMultipleXmlsIntegrationTest { - - @Autowired - private Environment env; - - @Value("${key.something}") - private String injectedProperty; - - @Value("${external.something}") - private String injectedExternalProperty; - - @Test - public final void givenContextIsInitialized_thenNoException() { - System.out.println("in test via @Value: " + injectedProperty); - System.out.println("in test Environment: " + env.getProperty("key.something")); - - System.out.println("in test via @Value - external: " + injectedExternalProperty); - System.out.println("in test Environment - external: " + env.getProperty("external.something")); - } - -} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/external/ExternalPropertiesWithXmlManualTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/external/ExternalPropertiesWithXmlManualTest.java deleted file mode 100644 index 4f0abbc12c..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/external/ExternalPropertiesWithXmlManualTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.baeldung.properties.external; - -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.env.Environment; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.support.AnnotationConfigContextLoader; - -import com.baeldung.properties.external.ExternalPropertiesWithXmlConfig; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { ExternalPropertiesWithXmlConfig.class }, loader = AnnotationConfigContextLoader.class) -@Ignore("manual only") -public class ExternalPropertiesWithXmlManualTest { - - @Autowired - private Environment env; - - @Value("${key.something}") - private String injectedProperty; - - @Value("${external.something}") - private String injectedExternalProperty; - - @Test - public final void givenContextIsInitialized_thenNoException() { - System.out.println("in test via @Value: " + injectedProperty); - System.out.println("in test Environment: " + env.getProperty("key.something")); - - System.out.println("in test via @Value - external: " + injectedExternalProperty); - System.out.println("in test Environment - external: " + env.getProperty("external.something")); - } - -} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multidocument/MultidocumentPropertiesFileIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multidocument/MultidocumentPropertiesFileIntegrationTest.java new file mode 100644 index 0000000000..683b0b86ab --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multidocument/MultidocumentPropertiesFileIntegrationTest.java @@ -0,0 +1,25 @@ +package com.baeldung.properties.multidocument; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@ActiveProfiles("default") +@SpringBootTest(classes = { MultidocumentTestConfig.class }) +public class MultidocumentPropertiesFileIntegrationTest { + + Logger logger = LoggerFactory.getLogger(MultidocumentPropertiesFileIntegrationTest.class); + + @Value("${baeldung.customProperty}") + private String customProperty; + + @Test + public void givenMultidocumentPropertiesFileWhenBootContextLoadedThenDocumentProcessedCorrectly() { + assertThat(customProperty).isEqualTo("valueDefault"); + } +} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multidocument/MultidocumentPropertiesFileWithDevProfileIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multidocument/MultidocumentPropertiesFileWithDevProfileIntegrationTest.java new file mode 100644 index 0000000000..3771bdb1c7 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multidocument/MultidocumentPropertiesFileWithDevProfileIntegrationTest.java @@ -0,0 +1,25 @@ +package com.baeldung.properties.multidocument; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@ActiveProfiles("test") +@SpringBootTest(classes = { MultidocumentTestConfig.class }) +public class MultidocumentPropertiesFileWithDevProfileIntegrationTest { + + Logger logger = LoggerFactory.getLogger(MultidocumentPropertiesFileWithDevProfileIntegrationTest.class); + + @Value("${baeldung.customProperty}") + private String customProperty; + + @Test + public void givenMultidocumentPropertiesFileWhenBootContextLoadedThenDocumentProcessedCorrectly() { + assertThat(customProperty).isEqualTo("valueTest"); + } +} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multidocument/MultidocumentPropertiesFileWithTestProfileIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multidocument/MultidocumentPropertiesFileWithTestProfileIntegrationTest.java new file mode 100644 index 0000000000..b00dda19b7 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multidocument/MultidocumentPropertiesFileWithTestProfileIntegrationTest.java @@ -0,0 +1,25 @@ +package com.baeldung.properties.multidocument; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@ActiveProfiles("dev") +@SpringBootTest(classes = { MultidocumentTestConfig.class }) +public class MultidocumentPropertiesFileWithTestProfileIntegrationTest { + + Logger logger = LoggerFactory.getLogger(MultidocumentPropertiesFileWithTestProfileIntegrationTest.class); + + @Value("${baeldung.customProperty}") + private String customProperty; + + @Test + public void givenMultidocumentPropertiesFileWhenBootContextLoadedThenDocumentProcessedCorrectly() { + assertThat(customProperty).isEqualTo("valueDev"); + } +} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multidocument/MultidocumentTestConfig.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multidocument/MultidocumentTestConfig.java new file mode 100644 index 0000000000..6f80cb70e7 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multidocument/MultidocumentTestConfig.java @@ -0,0 +1,10 @@ +package com.baeldung.properties.multidocument; + +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ComponentScan("com.baeldung.properties.multidocument") +public class MultidocumentTestConfig { + +} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multiple/MultiplePlaceholdersJavaConfigIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multiple/MultiplePlaceholdersJavaConfigIntegrationTest.java index 8ebda90321..6c88623ab7 100644 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multiple/MultiplePlaceholdersJavaConfigIntegrationTest.java +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multiple/MultiplePlaceholdersJavaConfigIntegrationTest.java @@ -4,12 +4,11 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Value; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; -import com.baeldung.properties.spring.PropertyPlaceholderConfig; import com.baeldung.properties.spring.PropertySourcesPlaceholderConfig; import static org.assertj.core.api.Assertions.assertThat; -@SpringJUnitConfig({PropertyPlaceholderConfig.class, PropertySourcesPlaceholderConfig.class}) +@SpringJUnitConfig({PropertySourcesPlaceholderConfig.class}) public class MultiplePlaceholdersJavaConfigIntegrationTest { @Value("${key.something}") diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multiple/MultiplePlaceholdersXmlConfigIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multiple/MultiplePlaceholdersXmlConfigIntegrationTest.java deleted file mode 100644 index b863e2e080..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multiple/MultiplePlaceholdersXmlConfigIntegrationTest.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.baeldung.properties.multiple; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; - -import static org.assertj.core.api.Assertions.assertThat; - - -@SpringJUnitConfig(locations = "classpath:configForPropertyPlaceholderBeans.xml") -public class MultiplePlaceholdersXmlConfigIntegrationTest { - - @Value("${foo}") - private String something; - - @Value("${key.something}") - private String something2; - - - @Test - public void whenReadInjectedValues_thenGetCorrectValues() { - assertThat(something).isEqualTo("bar"); - assertThat(something2).isEqualTo("val"); - } -} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multiple/MultiplePropertiesXmlConfigIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multiple/MultiplePropertiesXmlConfigIntegrationTest.java deleted file mode 100644 index 2150d4b3ec..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/multiple/MultiplePropertiesXmlConfigIntegrationTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.properties.multiple; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; - -import static org.assertj.core.api.Assertions.assertThat; - -@SpringJUnitConfig(locations = {"classpath:configForProperties.xml", "classpath:configForDbProperties.xml"}) -public class MultiplePropertiesXmlConfigIntegrationTest { - - @Value("${key.something}") private String something; - - @Value("${key.something2}") private String something2; - - @Value("${jdbc.url}") private String jdbcUrl; - - @Test - public void whenReadInjectedValues_thenGetCorrectValues() { - assertThat(something).isEqualTo("val"); - assertThat(something2).isEqualTo("val2"); - assertThat(jdbcUrl).isEqualTo("jdbc:postgresql:/localhost:5432"); - } -} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/parentchild/ParentChildPropertyPlaceHolderPropertiesIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/parentchild/ParentChildPropertyPlaceHolderPropertiesIntegrationTest.java deleted file mode 100644 index 374a502e5c..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/parentchild/ParentChildPropertyPlaceHolderPropertiesIntegrationTest.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.baeldung.properties.parentchild; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.ContextHierarchy; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.web.WebAppConfiguration; -import org.springframework.web.context.WebApplicationContext; - -import com.baeldung.properties.parentchild.config.ChildConfig2; -import com.baeldung.properties.parentchild.config.ParentConfig2; - -@RunWith(SpringJUnit4ClassRunner.class) -@WebAppConfiguration -@ContextHierarchy({ @ContextConfiguration(classes = ParentConfig2.class), @ContextConfiguration(classes = ChildConfig2.class) }) -public class ParentChildPropertyPlaceHolderPropertiesIntegrationTest { - - @Autowired - private WebApplicationContext wac; - - @Test - public void givenPropertyPlaceHolder_whenGetPropertyUsingEnv_thenCorrect() { - final Environment childEnv = wac.getEnvironment(); - final Environment parentEnv = wac.getParent().getEnvironment(); - - assertNull(parentEnv.getProperty("parent.name")); - assertNull(parentEnv.getProperty("child.name")); - - assertNull(childEnv.getProperty("parent.name")); - assertNull(childEnv.getProperty("child.name")); - } - - @Test - public void givenPropertyPlaceHolder_whenGetPropertyUsingValueAnnotation_thenCorrect() { - final ChildValueHolder childValueHolder = wac.getBean(ChildValueHolder.class); - final ParentValueHolder parentValueHolder = wac.getParent().getBean(ParentValueHolder.class); - - assertEquals(parentValueHolder.getParentName(), "parent"); - assertEquals(parentValueHolder.getChildName(), "-"); - - assertEquals(childValueHolder.getParentName(), "-"); - assertEquals(childValueHolder.getChildName(), "child"); - } - -} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/parentchild/config/ChildConfig2.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/parentchild/config/ChildConfig2.java deleted file mode 100644 index a506060d1c..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/parentchild/config/ChildConfig2.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.properties.parentchild.config; - -import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.ClassPathResource; - -import com.baeldung.properties.parentchild.ChildValueHolder; - -@Configuration -public class ChildConfig2 { - - @Bean - public ChildValueHolder childValueHolder() { - return new ChildValueHolder(); - } - - @Bean - public static PropertyPlaceholderConfigurer properties() { - final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer(); - ppc.setLocations(new ClassPathResource("child.properties")); - return ppc; - } -} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/parentchild/config/ParentConfig2.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/parentchild/config/ParentConfig2.java deleted file mode 100644 index f5376e0c8e..0000000000 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/properties/parentchild/config/ParentConfig2.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.properties.parentchild.config; - -import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.ClassPathResource; - -import com.baeldung.properties.parentchild.ParentValueHolder; - -@Configuration -public class ParentConfig2 { - - @Bean - public ParentValueHolder parentValueHolder() { - return new ParentValueHolder(); - } - - @Bean - public static PropertyPlaceholderConfigurer properties() { - final PropertyPlaceholderConfigurer ppc = new PropertyPlaceholderConfigurer(); - ppc.setLocations(new ClassPathResource("parent.properties")); - return ppc; - } -} diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/test/IntegrationTestSuite.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/test/IntegrationTestSuite.java index 0e0f8f6230..9a1eccb439 100644 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/test/IntegrationTestSuite.java +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/test/IntegrationTestSuite.java @@ -5,22 +5,12 @@ import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; import com.baeldung.properties.basic.ExtendedPropertiesWithJavaIntegrationTest; -import com.baeldung.properties.basic.PropertiesWithMultipleXmlsIntegrationTest; -import com.baeldung.properties.basic.PropertiesWithXmlIntegrationTest; import com.baeldung.properties.external.ExternalPropertiesWithJavaIntegrationTest; -import com.baeldung.properties.external.ExternalPropertiesWithMultipleXmlsIntegrationTest; -import com.baeldung.properties.external.ExternalPropertiesWithXmlManualTest; -import com.baeldung.properties.multiple.MultiplePropertiesXmlConfigIntegrationTest; -import com.baeldung.properties.multiple.MultiplePlaceholdersXmlConfigIntegrationTest; @RunWith(Suite.class) @SuiteClasses({ //@formatter:off - PropertiesWithXmlIntegrationTest.class, ExternalPropertiesWithJavaIntegrationTest.class, - ExternalPropertiesWithMultipleXmlsIntegrationTest.class, - ExternalPropertiesWithXmlManualTest.class, - ExtendedPropertiesWithJavaIntegrationTest.class, MultiplePropertiesXmlConfigIntegrationTest.class, - PropertiesWithMultipleXmlsIntegrationTest.class, MultiplePlaceholdersXmlConfigIntegrationTest.class + ExtendedPropertiesWithJavaIntegrationTest.class, })// @formatter:on public final class IntegrationTestSuite { // diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/yaml/YAMLDevIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/yaml/YAMLDevIntegrationTest.java index 8dfc4c2208..5e6ebf6d81 100644 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/yaml/YAMLDevIntegrationTest.java +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/yaml/YAMLDevIntegrationTest.java @@ -21,5 +21,6 @@ class YAMLDevIntegrationTest { void whenProfileTest_thenNameTesting() { assertTrue("development".equalsIgnoreCase(config.getEnvironment())); assertTrue("dev-YAML".equalsIgnoreCase(config.getName())); + assertTrue(config.isEnabled()); } } diff --git a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/yaml/YAMLIntegrationTest.java b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/yaml/YAMLIntegrationTest.java index 19412c91f5..278307504b 100644 --- a/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/yaml/YAMLIntegrationTest.java +++ b/spring-boot-modules/spring-boot-properties/src/test/java/com/baeldung/yaml/YAMLIntegrationTest.java @@ -1,5 +1,6 @@ package com.baeldung.yaml; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.jupiter.api.Test; @@ -22,5 +23,6 @@ class YAMLIntegrationTest { assertTrue("testing".equalsIgnoreCase(config.getEnvironment())); assertTrue("test-YAML".equalsIgnoreCase(config.getName())); assertTrue("myurl".equalsIgnoreCase(config.getComponent().getIdm().getUrl())); + assertFalse(config.isEnabled()); } } diff --git a/spring-boot-modules/spring-boot-properties/src/test/resources/additional-application b/spring-boot-modules/spring-boot-properties/src/test/resources/additional-application new file mode 100644 index 0000000000..46f3c2b1a3 --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/resources/additional-application @@ -0,0 +1,7 @@ +baeldung: + additionalProperty: additionalValue + otherProperty: otherValue + +spring: + config: + import: classpath:additional-application2.properties \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/test/resources/additional-application-properties/application.properties b/spring-boot-modules/spring-boot-properties/src/test/resources/additional-application-properties/application.properties new file mode 100644 index 0000000000..b547d16eff --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/resources/additional-application-properties/application.properties @@ -0,0 +1 @@ +baeldung.otherProperty=latterValue diff --git a/spring-boot-modules/spring-boot-properties/src/test/resources/additional-application.properties b/spring-boot-modules/spring-boot-properties/src/test/resources/additional-application.properties new file mode 100644 index 0000000000..2edbe692de --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/resources/additional-application.properties @@ -0,0 +1,5 @@ +spring.config.activate.on-profile=test +baeldung.customProperty=valueTest +#--- +spring.config.activate.on-profile=prod +baeldung.customProperty=valueProd \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-properties/src/test/resources/additional-application2.properties b/spring-boot-modules/spring-boot-properties/src/test/resources/additional-application2.properties new file mode 100644 index 0000000000..c6cb95ec5b --- /dev/null +++ b/spring-boot-modules/spring-boot-properties/src/test/resources/additional-application2.properties @@ -0,0 +1 @@ +baeldung.additionalProperty=additionalValue2 \ No newline at end of file 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 af38556f81..3f6c678b97 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 @@ -2,4 +2,10 @@ management.endpoints.web.exposure.include=refresh spring.properties.refreshDelay=1000 spring.config.location=file:extra.properties spring.main.allow-bean-definition-overriding=true +spring.config.import=classpath:additional-application.properties,classpath:additional-application[.yml],optional:file:./external.properties,classpath:additional-application-properties/ +baeldung.customProperty=valueDefault +#--- +spring.config.activate.on-profile=dev +baeldung.customProperty=valueDev + diff --git a/spring-boot-modules/spring-boot-runtime-2/README.md b/spring-boot-modules/spring-boot-runtime-2/README.md new file mode 100644 index 0000000000..9f0d814d8d --- /dev/null +++ b/spring-boot-modules/spring-boot-runtime-2/README.md @@ -0,0 +1,6 @@ +## Spring Boot Runtime 2 + +This module contains articles about administering a Spring Boot runtime + +### Relevant Articles: + - [Configure the Heap Size When Starting a Spring Boot Application](https://www.baeldung.com/spring-boot-heap-size) diff --git a/spring-boot-modules/spring-boot-runtime-2/pom.xml b/spring-boot-modules/spring-boot-runtime-2/pom.xml new file mode 100644 index 0000000000..8f6351165a --- /dev/null +++ b/spring-boot-modules/spring-boot-runtime-2/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + ../ + + + spring-boot-runtime-2 + jar + + spring-boot-runtime-2 + Demo project for Spring Boot + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + ${project.artifactId} + + + src/main/resources/heap + ${project.build.directory} + true + + ${project.name}.conf + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + com.baeldung.heap.HeapSizeDemoApplication + + + + + true + + -Xms256m + -Xmx1g + + + + + + diff --git a/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/heap/HeapSizeDemoApplication.java b/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/heap/HeapSizeDemoApplication.java new file mode 100644 index 0000000000..60d4bf7bab --- /dev/null +++ b/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/heap/HeapSizeDemoApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.heap; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class HeapSizeDemoApplication { + + public static void main(String[] args) { + SpringApplication.run(HeapSizeDemoApplication.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/heap/MemoryStats.java b/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/heap/MemoryStats.java new file mode 100644 index 0000000000..0d2f471a12 --- /dev/null +++ b/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/heap/MemoryStats.java @@ -0,0 +1,31 @@ +package com.baeldung.heap; + +public class MemoryStats { + private long heapSize; + private long heapMaxSize; + private long heapFreeSize; + + public long getHeapSize() { + return heapSize; + } + + public void setHeapSize(long heapSize) { + this.heapSize = heapSize; + } + + public long getHeapMaxSize() { + return heapMaxSize; + } + + public void setHeapMaxSize(long heapMaxSize) { + this.heapMaxSize = heapMaxSize; + } + + public long getHeapFreeSize() { + return heapFreeSize; + } + + public void setHeapFreeSize(long heapFreeSize) { + this.heapFreeSize = heapFreeSize; + } +} diff --git a/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/heap/MemoryStatusController.java b/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/heap/MemoryStatusController.java new file mode 100644 index 0000000000..293747fbd1 --- /dev/null +++ b/spring-boot-modules/spring-boot-runtime-2/src/main/java/com/baeldung/heap/MemoryStatusController.java @@ -0,0 +1,20 @@ +package com.baeldung.heap; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class MemoryStatusController { + + @GetMapping("memory-status") + public MemoryStats getMemoryStatistics() { + MemoryStats stats = new MemoryStats(); + stats.setHeapSize(Runtime.getRuntime() + .totalMemory()); + stats.setHeapMaxSize(Runtime.getRuntime() + .maxMemory()); + stats.setHeapFreeSize(Runtime.getRuntime() + .freeMemory()); + return stats; + } +} diff --git a/spring-boot-modules/spring-boot-runtime-2/src/main/resources/heap/spring-boot-runtime-2.conf b/spring-boot-modules/spring-boot-runtime-2/src/main/resources/heap/spring-boot-runtime-2.conf new file mode 100644 index 0000000000..3bfde4e3d9 --- /dev/null +++ b/spring-boot-modules/spring-boot-runtime-2/src/main/resources/heap/spring-boot-runtime-2.conf @@ -0,0 +1 @@ +JAVA_OPTS="-Xms512m -Xmx1024m" \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-runtime-2/src/test/java/com/baeldung/heap/MemoryStatusControllerIntegrationTest.java b/spring-boot-modules/spring-boot-runtime-2/src/test/java/com/baeldung/heap/MemoryStatusControllerIntegrationTest.java new file mode 100644 index 0000000000..2e744285d8 --- /dev/null +++ b/spring-boot-modules/spring-boot-runtime-2/src/test/java/com/baeldung/heap/MemoryStatusControllerIntegrationTest.java @@ -0,0 +1,32 @@ +package com.baeldung.heap; + +import static org.hamcrest.Matchers.notANumber; +import static org.hamcrest.Matchers.not; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; + +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.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +@RunWith(SpringRunner.class) +@WebMvcTest(MemoryStatusController.class) +public class MemoryStatusControllerIntegrationTest { + + @Autowired + private MockMvc mvc; + + @Test + public void whenGetMemoryStatistics_thenReturnJsonArray() throws Exception { + mvc.perform(get("/memory-status").contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("heapSize", not(notANumber()))) + .andExpect(jsonPath("heapMaxSize", not(notANumber()))) + .andExpect(jsonPath("heapFreeSize", not(notANumber()))); + } +} diff --git a/spring-boot-modules/spring-boot-runtime/README.md b/spring-boot-modules/spring-boot-runtime/README.md index 62727ecc76..271093421c 100644 --- a/spring-boot-modules/spring-boot-runtime/README.md +++ b/spring-boot-modules/spring-boot-runtime/README.md @@ -10,4 +10,5 @@ This module contains articles about administering a Spring Boot runtime - [Spring Boot Embedded Tomcat Logs](https://www.baeldung.com/spring-boot-embedded-tomcat-logs) - [Project Configuration with Spring](https://www.baeldung.com/project-configuration-with-spring) - [CORS with Spring](https://www.baeldung.com/spring-cors) - - [Spring – Log Incoming Requests](https://www.baeldung.com/spring-http-logging) \ No newline at end of file + - [Spring – Log Incoming Requests](https://www.baeldung.com/spring-http-logging) + - [How to Configure Spring Boot Tomcat](https://www.baeldung.com/spring-boot-configure-tomcat) diff --git a/spring-boot-modules/spring-boot-runtime/src/main/resources/application-tomcat.properties b/spring-boot-modules/spring-boot-runtime/src/main/resources/application-tomcat.properties index 42d03a066e..ba91c5f3b2 100644 --- a/spring-boot-modules/spring-boot-runtime/src/main/resources/application-tomcat.properties +++ b/spring-boot-modules/spring-boot-runtime/src/main/resources/application-tomcat.properties @@ -9,7 +9,7 @@ server.error.include-exception=true server.error.include-stacktrace=always ## Server connections configuration -server.tomcat.max-threads=200 +server.tomcat.threads.max=200 server.connection-timeout=5s server.max-http-header-size=8KB server.tomcat.max-swallow-size=2MB diff --git a/spring-boot-modules/spring-boot-security/README.md b/spring-boot-modules/spring-boot-security/README.md index 7229ba0f4a..2c9d37eac0 100644 --- a/spring-boot-modules/spring-boot-security/README.md +++ b/spring-boot-modules/spring-boot-security/README.md @@ -8,6 +8,8 @@ This module contains articles about Spring Boot Security - [Spring Security for Spring Boot Integration Tests](https://www.baeldung.com/spring-security-integration-tests) - [Introduction to Spring Security Taglibs](https://www.baeldung.com/spring-security-taglibs) - [Guide to @CurrentSecurityContext in Spring Security](https://www.baeldung.com/spring-currentsecuritycontext) +- [Disable Security for a Profile in Spring Boot](https://www.baeldung.com/spring-security-disable-profile) + ### Spring Boot Security Auto-Configuration diff --git a/spring-5-security/src/main/java/com/baeldung/securityprofile/Application.java b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/securityprofile/Application.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/securityprofile/Application.java rename to spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/securityprofile/Application.java diff --git a/spring-5-security/src/main/java/com/baeldung/securityprofile/ApplicationNoSecurity.java b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/securityprofile/ApplicationNoSecurity.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/securityprofile/ApplicationNoSecurity.java rename to spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/securityprofile/ApplicationNoSecurity.java diff --git a/spring-5-security/src/main/java/com/baeldung/securityprofile/ApplicationSecurity.java b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/securityprofile/ApplicationSecurity.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/securityprofile/ApplicationSecurity.java rename to spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/securityprofile/ApplicationSecurity.java diff --git a/spring-5-security/src/main/java/com/baeldung/securityprofile/EmployeeController.java b/spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/securityprofile/EmployeeController.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/securityprofile/EmployeeController.java rename to spring-boot-modules/spring-boot-security/src/main/java/com/baeldung/securityprofile/EmployeeController.java diff --git a/spring-5-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerNoSecurityUnitTest.java b/spring-boot-modules/spring-boot-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerNoSecurityUnitTest.java similarity index 100% rename from spring-5-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerNoSecurityUnitTest.java rename to spring-boot-modules/spring-boot-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerNoSecurityUnitTest.java diff --git a/spring-5-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerUnitTest.java b/spring-boot-modules/spring-boot-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerUnitTest.java similarity index 100% rename from spring-5-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerUnitTest.java rename to spring-boot-modules/spring-boot-security/src/test/java/com/baeldung/securityprofile/EmployeeControllerUnitTest.java diff --git a/spring-boot-modules/spring-boot-springdoc/README.md b/spring-boot-modules/spring-boot-springdoc/README.md index 2447f30f6b..608e4afa2e 100644 --- a/spring-boot-modules/spring-boot-springdoc/README.md +++ b/spring-boot-modules/spring-boot-springdoc/README.md @@ -2,3 +2,4 @@ - [Documenting a Spring REST API Using OpenAPI 3.0](https://www.baeldung.com/spring-rest-openapi-documentation) - [Spring REST Docs vs OpenAPI](https://www.baeldung.com/spring-rest-docs-vs-openapi) +- [Hiding Endpoints From Swagger Documentation in Spring Boot](https://www.baeldung.com/spring-swagger-hiding-endpoints) diff --git a/spring-boot-modules/spring-boot-springdoc/pom.xml b/spring-boot-modules/spring-boot-springdoc/pom.xml index ed272200da..259383a1d2 100644 --- a/spring-boot-modules/spring-boot-springdoc/pom.xml +++ b/spring-boot-modules/spring-boot-springdoc/pom.xml @@ -81,7 +81,7 @@ org.jetbrains.kotlin - kotlin-stdlib-jre8 + kotlin-stdlib-jdk8 ${kotlin.version} @@ -171,9 +171,9 @@ 1.8 5.2.10.Final - 1.2.32 + 1.5.2 1.5.6 - 1.2.71 + 1.4.0 ${project.build.directory}/generated-snippets @@ -185,7 +185,7 @@ org.springframework.boot spring-boot-maven-plugin - 2.2.2.RELEASE + ${spring-boot.version} pre-integration-test diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/BookController.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/BookController.java index 326a97149b..f2355a2ec3 100644 --- a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/BookController.java +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/BookController.java @@ -5,6 +5,17 @@ import java.util.Collection; import javax.validation.Valid; import javax.validation.constraints.NotNull; +import com.baeldung.springdoc.exception.BookNotFoundException; +import com.baeldung.springdoc.model.Book; +import com.baeldung.springdoc.repository.BookRepository; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import org.springdoc.api.annotations.ParameterObject; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -21,17 +32,6 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; -import com.baeldung.springdoc.exception.BookNotFoundException; -import com.baeldung.springdoc.model.Book; -import com.baeldung.springdoc.repository.BookRepository; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.Schema; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; - @RestController @RequestMapping("/api/book") public class BookController { @@ -58,7 +58,7 @@ public class BookController { } @GetMapping("/filter") - public Page filterBooks(Pageable pageable) { + public Page filterBooks(@ParameterObject Pageable pageable) { return repository.getBooks(pageable); } diff --git a/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/RegularRestController.java b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/RegularRestController.java new file mode 100644 index 0000000000..f3135229d6 --- /dev/null +++ b/spring-boot-modules/spring-boot-springdoc/src/main/java/com/baeldung/springdoc/controller/RegularRestController.java @@ -0,0 +1,31 @@ +package com.baeldung.springdoc.controller; + +import java.time.LocalDate; +import java.time.LocalTime; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.v3.oas.annotations.Hidden; + +@Hidden +@RestController +public class RegularRestController { + + @Hidden + @GetMapping("/getAuthor") + public String getAuthor() { + return "Umang Budhwar"; + } + + @GetMapping("/getDate") + public LocalDate getDate() { + return LocalDate.now(); + } + + @GetMapping("/getTime") + public LocalTime getTime() { + return LocalTime.now(); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger-jwt/README.md b/spring-boot-modules/spring-boot-swagger-jwt/README.md new file mode 100644 index 0000000000..f04dd5957a --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-jwt/README.md @@ -0,0 +1,3 @@ +## Relevant Articles: + +- [Set JWT with Spring Boot and Swagger UI](https://www.baeldung.com/spring-boot-swagger-jwt) diff --git a/spring-boot-modules/spring-boot-swagger-jwt/pom.xml b/spring-boot-modules/spring-boot-swagger-jwt/pom.xml new file mode 100644 index 0000000000..d71d7342ce --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-jwt/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + + com.baeldung.spring-boot-modules + spring-boot-modules + 1.0.0-SNAPSHOT + ../ + + + spring-boot-swagger-jwt + 0.1.0-SNAPSHOT + spring-boot-swagger-jwt + jar + + Module For Spring Boot Swagger UI + + + org.springframework.boot + spring-boot-starter-web + + + io.springfox + springfox-boot-starter + 3.0.0 + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-boot-modules/spring-boot-swagger-jwt/src/main/java/com/baeldung/swaggerjwt/SpringBootSwaggerUIApplication.java b/spring-boot-modules/spring-boot-swagger-jwt/src/main/java/com/baeldung/swaggerjwt/SpringBootSwaggerUIApplication.java new file mode 100644 index 0000000000..e9e5d24b54 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-jwt/src/main/java/com/baeldung/swaggerjwt/SpringBootSwaggerUIApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.swaggerjwt; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SpringBootSwaggerUIApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringBootSwaggerUIApplication.class, args); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger-jwt/src/main/java/com/baeldung/swaggerjwt/configuration/SwaggerConfiguration.java b/spring-boot-modules/spring-boot-swagger-jwt/src/main/java/com/baeldung/swaggerjwt/configuration/SwaggerConfiguration.java new file mode 100644 index 0000000000..240a21cd21 --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-jwt/src/main/java/com/baeldung/swaggerjwt/configuration/SwaggerConfiguration.java @@ -0,0 +1,62 @@ +package com.baeldung.swaggerjwt.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.*; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spi.service.contexts.SecurityContext; +import springfox.documentation.spring.web.plugins.Docket; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@Configuration +public class SwaggerConfiguration { + + public static final String AUTHORIZATION_HEADER = "Authorization"; + + private ApiInfo apiInfo() { + return new ApiInfo("My REST API", + "Some custom description of API.", + "1.0", + "Terms of service", + new Contact("Sallo Szrajbman", "www.baeldung.com", "salloszraj@gmail.com"), + "License of API", + "API license URL", + Collections.emptyList()); + } + + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2) + .apiInfo(apiInfo()) + .securityContexts(Arrays.asList(securityContext())) + .securitySchemes(Arrays.asList(apiKey())) + .select() + .apis(RequestHandlerSelectors.any()) + .paths(PathSelectors.any()) + .build(); + } + + private ApiKey apiKey() { + return new ApiKey("JWT", AUTHORIZATION_HEADER, "header"); + } + + private SecurityContext securityContext() { + return SecurityContext.builder() + .securityReferences(defaultAuth()) + .build(); + } + + List defaultAuth() { + AuthorizationScope authorizationScope + = new AuthorizationScope("global", "accessEverything"); + AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; + authorizationScopes[0] = authorizationScope; + return Arrays.asList(new SecurityReference("JWT", authorizationScopes)); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger-jwt/src/main/java/com/baeldung/swaggerjwt/controller/ClientsRestController.java b/spring-boot-modules/spring-boot-swagger-jwt/src/main/java/com/baeldung/swaggerjwt/controller/ClientsRestController.java new file mode 100644 index 0000000000..f60ba2448a --- /dev/null +++ b/spring-boot-modules/spring-boot-swagger-jwt/src/main/java/com/baeldung/swaggerjwt/controller/ClientsRestController.java @@ -0,0 +1,25 @@ +package com.baeldung.swaggerjwt.controller; + +import java.util.Arrays; +import java.util.List; + +import com.baeldung.swaggerjwt.configuration.SwaggerConfiguration; +import io.swagger.annotations.Api; +import org.springframework.http.HttpHeaders; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RestController; + +import io.swagger.annotations.ApiOperation; + +@RestController(value = "/clients") +@Api( tags = "Clients") +public class ClientsRestController { + + @ApiOperation(value = "This method is used to get the clients.") + @GetMapping + public List getClients() { + return Arrays.asList("First Client", "Second Client"); + } + +} diff --git a/spring-boot-modules/spring-boot-swagger-jwt/src/main/resources/application.properties b/spring-boot-modules/spring-boot-swagger-jwt/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-boot-modules/spring-boot-testing/pom.xml b/spring-boot-modules/spring-boot-testing/pom.xml index 5bf626f165..50a1ace2fa 100644 --- a/spring-boot-modules/spring-boot-testing/pom.xml +++ b/spring-boot-modules/spring-boot-testing/pom.xml @@ -51,6 +51,17 @@ spring-boot-starter-test test + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + diff --git a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/boot/configurationproperties/BindingYMLPropertiesUnitTest.java b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/boot/configurationproperties/BindingYMLPropertiesUnitTest.java index 5543f5e9e8..99c128997e 100644 --- a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/boot/configurationproperties/BindingYMLPropertiesUnitTest.java +++ b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/boot/configurationproperties/BindingYMLPropertiesUnitTest.java @@ -7,13 +7,13 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; @ExtendWith(SpringExtension.class) -@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class) +@ContextConfiguration(initializers = ConfigDataApplicationContextInitializer.class) @EnableConfigurationProperties(value = ServerConfig.class) @ActiveProfiles("test") public class BindingYMLPropertiesUnitTest { diff --git a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/LoadSpringContextIntegrationTest.java b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/LoadSpringContextIntegrationTest.java index 6698094550..483c67b7a2 100644 --- a/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/LoadSpringContextIntegrationTest.java +++ b/spring-boot-modules/spring-boot-testing/src/test/java/com/baeldung/prevent/commandline/application/runner/execution/LoadSpringContextIntegrationTest.java @@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer; +import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer; import org.springframework.boot.test.mock.mockito.SpyBean; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -19,7 +19,7 @@ import static org.mockito.Mockito.verify; @ExtendWith(SpringExtension.class) @ContextConfiguration(classes = { ApplicationCommandLineRunnerApp.class }, - initializers = ConfigFileApplicationContextInitializer.class) + initializers = ConfigDataApplicationContextInitializer.class) public class LoadSpringContextIntegrationTest { @SpyBean TaskService taskService; diff --git a/spring-boot-modules/spring-boot-testing/src/test/resources/application.yml b/spring-boot-modules/spring-boot-testing/src/test/resources/application.yml index 1b46b0f1ff..056b5baffc 100644 --- a/spring-boot-modules/spring-boot-testing/src/test/resources/application.yml +++ b/spring-boot-modules/spring-boot-testing/src/test/resources/application.yml @@ -1,5 +1,7 @@ spring: - profiles: test + config: + activate: + on-profile: test server: address: ip: 192.168.0.4 @@ -7,7 +9,9 @@ server: imgs: /etc/test/imgs --- spring: - profiles: dev + config: + activate: + on-profile: dev server: address: ip: 192.168.0.5 diff --git a/spring-boot-modules/spring-boot-vue/src/test/java/org/baeldung/SpringContextTest.java b/spring-boot-modules/spring-boot-vue/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-boot-modules/spring-boot-vue/src/test/java/org/baeldung/SpringContextTest.java rename to spring-boot-modules/spring-boot-vue/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-boot-modules/spring-boot/pom.xml b/spring-boot-modules/spring-boot/pom.xml index c1f1ea3072..9023ae92f3 100644 --- a/spring-boot-modules/spring-boot/pom.xml +++ b/spring-boot-modules/spring-boot/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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 @@ -58,6 +58,17 @@ spring-boot-starter-test test + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + io.dropwizard.metrics 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 deleted file mode 100644 index f19bc1febb..0000000000 --- a/spring-boot-modules/spring-boot/src/test/resources/GraphQL collection.postman_collection.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "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 diff --git a/spring-cloud-bus/pom.xml b/spring-cloud-bus/pom.xml index ec56e23ac7..15eed8dcf0 100644 --- a/spring-cloud-bus/pom.xml +++ b/spring-cloud-bus/pom.xml @@ -35,6 +35,7 @@ Hoxton.SR4 + 2.3.3.RELEASE diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml index ee7b80ffc1..c0e452afaf 100644 --- a/spring-cloud/pom.xml +++ b/spring-cloud/pom.xml @@ -52,12 +52,30 @@ org.springframework.boot spring-boot-maven-plugin - ${spring-boot-maven-plugin.version} + + + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + Hoxton.SR4 2.2.3.RELEASE @@ -66,8 +84,7 @@ 1.4.7.RELEASE 1.4.7.RELEASE 3.0.6.RELEASE - 2.3.1.RELEASE - 2.3.1.RELEASE + diff --git a/spring-cloud/spring-cloud-aws/pom.xml b/spring-cloud/spring-cloud-aws/pom.xml index 2b05020888..f65db6a2fe 100644 --- a/spring-cloud/spring-cloud-aws/pom.xml +++ b/spring-cloud/spring-cloud-aws/pom.xml @@ -67,6 +67,7 @@ com.baeldung.spring.cloud.aws.SpringCloudAwsApplication Dalston.SR4 2.2.1.RELEASE + diff --git a/spring-cloud/spring-cloud-bootstrap/config/pom.xml b/spring-cloud/spring-cloud-bootstrap/config/pom.xml index 67831d0c7f..6ebf23637e 100644 --- a/spring-cloud/spring-cloud-bootstrap/config/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/config/pom.xml @@ -42,6 +42,7 @@ Brixton.SR7 + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/customer-service/pom.xml b/spring-cloud/spring-cloud-bootstrap/customer-service/pom.xml index 8fcf4adadb..729abb4f05 100644 --- a/spring-cloud/spring-cloud-bootstrap/customer-service/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/customer-service/pom.xml @@ -17,13 +17,6 @@ - - org.springframework.boot - spring-boot-dependencies - ${spring-boot.version} - pom - import - org.springframework.boot spring-boot-starter-web diff --git a/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml b/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml index 46550031e1..d77e29768f 100644 --- a/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/discovery/pom.xml @@ -51,6 +51,7 @@ Edgware.SR5 + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml index 10a04db197..34b7af7c0a 100644 --- a/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/gateway/pom.xml @@ -100,6 +100,7 @@ Dalston.RELEASE + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/order-service/order-client/pom.xml b/spring-cloud/spring-cloud-bootstrap/order-service/order-client/pom.xml index 4c8cf742b1..01e8afeec3 100644 --- a/spring-cloud/spring-cloud-bootstrap/order-service/order-client/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/order-service/order-client/pom.xml @@ -14,5 +14,4 @@ order-service 1.0.0-SNAPSHOT - diff --git a/spring-cloud/spring-cloud-bootstrap/order-service/pom.xml b/spring-cloud/spring-cloud-bootstrap/order-service/pom.xml index a1c6c1c39f..a32bd5a2d3 100644 --- a/spring-cloud/spring-cloud-bootstrap/order-service/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/order-service/pom.xml @@ -118,5 +118,6 @@ 1.8 1.8 com.baeldung.orderservice.OrderApplication + diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml b/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml index 36227f93c6..de0785bd45 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/pom.xml @@ -73,6 +73,7 @@ Dalston.RELEASE + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml b/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml index 0a01488628..0cce78276a 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/pom.xml @@ -82,6 +82,7 @@ Dalston.RELEASE + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/zipkin/pom.xml b/spring-cloud/spring-cloud-bootstrap/zipkin/pom.xml index bf7525a8e4..b83c5a2aaa 100644 --- a/spring-cloud/spring-cloud-bootstrap/zipkin/pom.xml +++ b/spring-cloud/spring-cloud-bootstrap/zipkin/pom.xml @@ -50,6 +50,7 @@ Brixton.SR7 + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-config/client/pom.xml b/spring-cloud/spring-cloud-config/client/pom.xml index 4f4a420238..2400520d2b 100644 --- a/spring-cloud/spring-cloud-config/client/pom.xml +++ b/spring-cloud/spring-cloud-config/client/pom.xml @@ -1,7 +1,7 @@ + xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 client client @@ -26,6 +26,17 @@ spring-boot-starter-test test + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + @@ -36,5 +47,4 @@ - diff --git a/spring-cloud/spring-cloud-config/pom.xml b/spring-cloud/spring-cloud-config/pom.xml index 8411a65500..bfe17044e0 100644 --- a/spring-cloud/spring-cloud-config/pom.xml +++ b/spring-cloud/spring-cloud-config/pom.xml @@ -33,7 +33,7 @@
- Hoxton.SR4 + 2020.0.0 diff --git a/spring-cloud/spring-cloud-config/server/pom.xml b/spring-cloud/spring-cloud-config/server/pom.xml index 9574834457..f0f1e43612 100644 --- a/spring-cloud/spring-cloud-config/server/pom.xml +++ b/spring-cloud/spring-cloud-config/server/pom.xml @@ -1,11 +1,11 @@ + xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 server server - + com.baeldung.spring.cloud spring-cloud-config @@ -30,6 +30,17 @@ spring-boot-starter-test test
+ + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + @@ -40,5 +51,4 @@ - diff --git a/spring-cloud/spring-cloud-connectors-heroku/pom.xml b/spring-cloud/spring-cloud-connectors-heroku/pom.xml index 7d85e07bb8..e71e1350a2 100644 --- a/spring-cloud/spring-cloud-connectors-heroku/pom.xml +++ b/spring-cloud/spring-cloud-connectors-heroku/pom.xml @@ -64,6 +64,7 @@ Hoxton.SR4 42.2.10 1.10.10 + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-eureka/README.md b/spring-cloud/spring-cloud-eureka/README.md index badf4c8d50..5fc96256f4 100644 --- a/spring-cloud/spring-cloud-eureka/README.md +++ b/spring-cloud/spring-cloud-eureka/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Introduction to Spring Cloud Netflix – Eureka](http://www.baeldung.com/spring-cloud-netflix-eureka) +- [Integration Tests With Spring Cloud Netflix and Feign](https://www.baeldung.com/spring-cloud-feign-integration-tests) diff --git a/spring-cloud/spring-cloud-eureka/pom.xml b/spring-cloud/spring-cloud-eureka/pom.xml index 7af0c15352..9d7350e774 100644 --- a/spring-cloud/spring-cloud-eureka/pom.xml +++ b/spring-cloud/spring-cloud-eureka/pom.xml @@ -19,6 +19,7 @@ spring-cloud-eureka-server spring-cloud-eureka-client spring-cloud-eureka-feign-client + spring-cloud-eureka-feign-client-integration-test diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml index d82ee6566d..dc6a1ae236 100644 --- a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-client/pom.xml @@ -17,6 +17,13 @@ + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-starter-parent diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml new file mode 100644 index 0000000000..95b1275e2c --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/pom.xml @@ -0,0 +1,97 @@ + + + 4.0.0 + spring-cloud-eureka-feign-client-integration-test + 1.0.0-SNAPSHOT + spring-cloud-eureka-feign-client-integration-test + jar + Spring Cloud Eureka - Feign Client Integration Tests + + + com.baeldung.spring.cloud + spring-cloud-eureka + 1.0.0-SNAPSHOT + + + + + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + + + org.springframework.cloud + spring-cloud-starter-parent + ${spring-cloud-dependencies.version} + pom + import + + + + + + + org.springframework.cloud + spring-cloud-starter-openfeign + + + + org.springframework.cloud + spring-cloud-starter-netflix-ribbon + + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + + org.springframework.boot + spring-boot-starter-web + + + + com.github.tomakehurst + wiremock + 2.27.2 + test + + + + org.projectlombok + lombok + + + + org.testcontainers + testcontainers + 1.14.3 + test + + + + org.awaitility + awaitility + 4.0.3 + test + + + + + + + + maven-surefire-plugin + + 1 + false + + + + + + diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/main/java/com/baeldung/spring/cloud/Application.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/main/java/com/baeldung/spring/cloud/Application.java new file mode 100644 index 0000000000..342e7e163b --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/main/java/com/baeldung/spring/cloud/Application.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.cloud; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.openfeign.EnableFeignClients; + +@EnableFeignClients +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/main/java/com/baeldung/spring/cloud/client/BooksClient.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/main/java/com/baeldung/spring/cloud/client/BooksClient.java new file mode 100644 index 0000000000..a263624b28 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/main/java/com/baeldung/spring/cloud/client/BooksClient.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.cloud.client; + +import com.baeldung.spring.cloud.model.Book; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.RequestMapping; + +import java.util.List; + +@FeignClient("books-service") +//@FeignClient(value="simple-books-client", url="${book.service.url}") +public interface BooksClient { + + @RequestMapping("/books") + List getBooks(); + +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/main/java/com/baeldung/spring/cloud/model/Book.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/main/java/com/baeldung/spring/cloud/model/Book.java new file mode 100644 index 0000000000..64492f678d --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/main/java/com/baeldung/spring/cloud/model/Book.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.cloud.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Book { + + private String title; + private String author; + +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/BookMocks.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/BookMocks.java new file mode 100644 index 0000000000..2cce72e6cb --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/BookMocks.java @@ -0,0 +1,27 @@ +package com.baeldung.spring.cloud.client; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; + +import java.io.IOException; + +import static java.nio.charset.Charset.defaultCharset; +import static org.springframework.util.StreamUtils.copyToString; + +public class BookMocks { + + public static void setupMockBooksResponse(WireMockServer mockService) throws IOException { + mockService.stubFor(WireMock.get(WireMock.urlEqualTo("/books")) + .willReturn( + WireMock.aResponse() + .withStatus(HttpStatus.OK.value()) + .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE) + .withBody( + copyToString( + BookMocks.class.getClassLoader().getResourceAsStream("payload/get-books-response.json"), + defaultCharset())))); + } + +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/BooksClientIntegrationTest.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/BooksClientIntegrationTest.java new file mode 100644 index 0000000000..2842eef435 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/BooksClientIntegrationTest.java @@ -0,0 +1,53 @@ +package com.baeldung.spring.cloud.client; + +import com.baeldung.spring.cloud.model.Book; +import com.github.tomakehurst.wiremock.WireMockServer; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.io.IOException; + +import static com.baeldung.spring.cloud.client.BookMocks.setupMockBooksResponse; +import static java.util.Arrays.asList; +import static org.junit.Assert.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@SpringBootTest +@ActiveProfiles("test") +@EnableConfigurationProperties +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { WireMockConfig.class }) +class BooksClientIntegrationTest { + + @Autowired + private WireMockServer mockBooksService; + + @Autowired + private BooksClient booksClient; + + @BeforeEach + void setUp() throws IOException { + setupMockBooksResponse(mockBooksService); + } + + @Test + public void whenGetBooks_thenBooksShouldBeReturned() { + assertFalse(booksClient.getBooks().isEmpty()); + } + + @Test + public void whenGetBooks_thenTheCorrectBooksShouldBeReturned() { + assertTrue(booksClient.getBooks() + .containsAll(asList( + new Book("Dune", "Frank Herbert"), + new Book("Foundation", "Isaac Asimov")))); + } + +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/EurekaContainerConfig.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/EurekaContainerConfig.java new file mode 100644 index 0000000000..6747d14b88 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/EurekaContainerConfig.java @@ -0,0 +1,39 @@ +package com.baeldung.spring.cloud.client; + +import org.jetbrains.annotations.NotNull; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.test.context.ActiveProfiles; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.lifecycle.Startables; + +import java.util.stream.Stream; + +@TestConfiguration +@ActiveProfiles("eureka-test") +public class EurekaContainerConfig { + + public static class Initializer implements ApplicationContextInitializer { + + public static GenericContainer eurekaServer + = new GenericContainer("springcloud/eureka") + .withExposedPorts(8761); + + @Override + public void initialize(@NotNull ConfigurableApplicationContext configurableApplicationContext) { + + Startables.deepStart(Stream.of(eurekaServer)).join(); + + TestPropertyValues + .of("eureka.client.serviceUrl.defaultZone=http://localhost:" + + eurekaServer.getFirstMappedPort().toString() + + "/eureka") + .applyTo(configurableApplicationContext); + + } + + } + +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/LoadBalancerBooksClientIntegrationTest.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/LoadBalancerBooksClientIntegrationTest.java new file mode 100644 index 0000000000..f05df11ba3 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/LoadBalancerBooksClientIntegrationTest.java @@ -0,0 +1,65 @@ +package com.baeldung.spring.cloud.client; + +import com.baeldung.spring.cloud.model.Book; +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.io.IOException; + +import static com.baeldung.spring.cloud.client.BookMocks.setupMockBooksResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.moreThan; +import static java.util.Arrays.asList; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@SpringBootTest +@ActiveProfiles("ribbon-test") +@EnableConfigurationProperties +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = { RibbonTestConfig.class }) +class LoadBalancerBooksClientIntegrationTest { + + @Autowired + private WireMockServer mockBooksService; + + @Autowired + private WireMockServer secondMockBooksService; + + @Autowired + private BooksClient booksClient; + + @BeforeEach + void setUp() throws IOException { + setupMockBooksResponse(mockBooksService); + setupMockBooksResponse(secondMockBooksService); + } + + @Test + void whenGetBooks_thenRequestsAreLoadBalanced() { + for (int k = 0; k < 10; k++) { + booksClient.getBooks(); + } + + mockBooksService.verify( + moreThan(0), getRequestedFor(WireMock.urlEqualTo("/books"))); + secondMockBooksService.verify( + moreThan(0), getRequestedFor(WireMock.urlEqualTo("/books"))); + } + + @Test + public void whenGetBooks_thenTheCorrectBooksShouldBeReturned() { + assertTrue(booksClient.getBooks() + .containsAll(asList( + new Book("Dune", "Frank Herbert"), + new Book("Foundation", "Isaac Asimov")))); + } +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/MockBookServiceConfig.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/MockBookServiceConfig.java new file mode 100644 index 0000000000..1fff2ec9c0 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/MockBookServiceConfig.java @@ -0,0 +1,22 @@ +package com.baeldung.spring.cloud.client; + +import com.baeldung.spring.cloud.model.Book; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Collections; +import java.util.List; + +@Configuration +@RestController +@ActiveProfiles("eureka-test") +public class MockBookServiceConfig { + + @RequestMapping("/books") + public List getBooks() { + return Collections.singletonList(new Book("Hitchhiker's guide to the galaxy", "Douglas Adams")); + } + +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/RibbonTestConfig.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/RibbonTestConfig.java new file mode 100644 index 0000000000..273ba182b1 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/RibbonTestConfig.java @@ -0,0 +1,41 @@ +package com.baeldung.spring.cloud.client; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.netflix.loadbalancer.Server; +import com.netflix.loadbalancer.ServerList; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.cloud.netflix.ribbon.StaticServerList; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.ActiveProfiles; + +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; + +@TestConfiguration +@ActiveProfiles("ribbon-test") +public class RibbonTestConfig { + + @Autowired + private WireMockServer mockBooksService; + + @Autowired + private WireMockServer secondMockBooksService; + + @Bean(initMethod = "start", destroyMethod = "stop") + public WireMockServer mockBooksService() { + return new WireMockServer(options().dynamicPort()); + } + + @Bean(name="secondMockBooksService", initMethod = "start", destroyMethod = "stop") + public WireMockServer secondBooksMockService() { + return new WireMockServer(options().dynamicPort()); + } + + @Bean + public ServerList ribbonServerList() { + return new StaticServerList<>( + new Server("localhost", mockBooksService.port()), + new Server("localhost", secondMockBooksService.port())); + } + +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/ServiceDiscoveryBooksClientLiveTest.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/ServiceDiscoveryBooksClientLiveTest.java new file mode 100644 index 0000000000..3ac067b8f8 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/ServiceDiscoveryBooksClientLiveTest.java @@ -0,0 +1,52 @@ +package com.baeldung.spring.cloud.client; + +import com.baeldung.spring.cloud.Application; +import com.baeldung.spring.cloud.model.Book; +import com.netflix.discovery.EurekaClient; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Lazy; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.List; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; +import static org.junit.jupiter.api.Assertions.assertEquals; + +@ActiveProfiles("eureka-test") +@EnableConfigurationProperties +@ExtendWith(SpringExtension.class) +@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@ContextConfiguration(classes = { MockBookServiceConfig.class }, initializers = { EurekaContainerConfig.Initializer.class }) +class ServiceDiscoveryBooksClientLiveTest { + + @Autowired + private BooksClient booksClient; + + @Lazy + @Autowired + private EurekaClient eurekaClient; + + @BeforeEach + void setUp() { + await().atMost(60, SECONDS).until(() -> eurekaClient.getApplications().size() > 0); + } + + @Test + public void whenGetBooks_thenTheCorrectBooksAreReturned() { + List books = booksClient.getBooks(); + + assertEquals(1, books.size()); + assertEquals( + new Book("Hitchhiker's guide to the galaxy", "Douglas Adams"), + books.stream().findFirst().get()); + } + +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/WireMockConfig.java b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/WireMockConfig.java new file mode 100644 index 0000000000..82b7cddede --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/java/com/baeldung/spring/cloud/client/WireMockConfig.java @@ -0,0 +1,17 @@ +package com.baeldung.spring.cloud.client; + +import com.github.tomakehurst.wiremock.WireMockServer; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.ActiveProfiles; + +@TestConfiguration +@ActiveProfiles("test") +public class WireMockConfig { + + @Bean(initMethod = "start", destroyMethod = "stop") + public WireMockServer mockBooksService() { + return new WireMockServer(9561); + } + +} diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-eureka-test.yml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-eureka-test.yml new file mode 100644 index 0000000000..6f6af6a080 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-eureka-test.yml @@ -0,0 +1,3 @@ +spring: + application: + name: books-service diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-ribbon-test.yml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-ribbon-test.yml new file mode 100644 index 0000000000..84a78d0ec7 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-ribbon-test.yml @@ -0,0 +1,3 @@ +eureka: + client: + enabled: false diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-test.yml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-test.yml new file mode 100644 index 0000000000..dce11adf69 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/application-test.yml @@ -0,0 +1,11 @@ +#book: +# service: +# url: http://localhost:9561 + +books-service: + ribbon: + listOfServers: http://localhost:9561 + +eureka: + client: + enabled: false diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/payload/get-books-response.json b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/payload/get-books-response.json new file mode 100644 index 0000000000..b4223ff8f2 --- /dev/null +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/payload/get-books-response.json @@ -0,0 +1,10 @@ +[ + { + "title": "Dune", + "author": "Frank Herbert" + }, + { + "title": "Foundation", + "author": "Isaac Asimov" + } +] diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml index 1ecc50a81f..e0d63dc15d 100644 --- a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-feign-client/pom.xml @@ -17,6 +17,13 @@ + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-starter-parent diff --git a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml index 627be513ba..9c0a933753 100644 --- a/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml +++ b/spring-cloud/spring-cloud-eureka/spring-cloud-eureka-server/pom.xml @@ -17,6 +17,13 @@ + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-starter-parent diff --git a/spring-cloud/spring-cloud-functions/pom.xml b/spring-cloud/spring-cloud-functions/pom.xml index 7e6f5dfbdc..0be3941db1 100644 --- a/spring-cloud/spring-cloud-functions/pom.xml +++ b/spring-cloud/spring-cloud-functions/pom.xml @@ -86,6 +86,7 @@ 2.0.2 1.1.0 1.0.10.RELEASE + diff --git a/spring-cloud/spring-cloud-functions/src/main/java/com/baeldung/spring/cloudfunction/aws/functions/Greeter.java b/spring-cloud/spring-cloud-functions/src/main/java/com/baeldung/spring/cloudfunction/aws/functions/Greeter.java index c443b98c18..bbc87a4ae2 100644 --- a/spring-cloud/spring-cloud-functions/src/main/java/com/baeldung/spring/cloudfunction/aws/functions/Greeter.java +++ b/spring-cloud/spring-cloud-functions/src/main/java/com/baeldung/spring/cloudfunction/aws/functions/Greeter.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.cloudfunction.functions.aws; +package com.baeldung.spring.cloudfunction.aws.functions; import java.util.function.Function; diff --git a/spring-cloud/spring-cloud-functions/src/main/resources/application.properties b/spring-cloud/spring-cloud-functions/src/main/resources/application.properties index b445bfa4ed..2cb479879c 100644 --- a/spring-cloud/spring-cloud-functions/src/main/resources/application.properties +++ b/spring-cloud/spring-cloud-functions/src/main/resources/application.properties @@ -1 +1 @@ -spring.cloud.function.scan.packages: com.baeldung.spring.cloudfunction.functions.aws \ No newline at end of file +spring.cloud.function.scan.packages: com.baeldung.spring.cloudfunction.aws.functions \ No newline at end of file diff --git a/spring-cloud/spring-cloud-gateway/pom.xml b/spring-cloud/spring-cloud-gateway/pom.xml index bbacf7a8ce..c9c087d738 100644 --- a/spring-cloud/spring-cloud-gateway/pom.xml +++ b/spring-cloud/spring-cloud-gateway/pom.xml @@ -17,19 +17,16 @@ - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud-dependencies.version} + org.junit + junit-bom + ${junit-jupiter.version} pom import - - - org.junit - junit-bom - ${junit-bom.version} + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud-dependencies.version} pom import diff --git a/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/pom.xml b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/pom.xml index acb9993881..204cb8765c 100644 --- a/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/pom.xml +++ b/spring-cloud/spring-cloud-hystrix/feign-rest-consumer/pom.xml @@ -17,6 +17,13 @@ + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-starter-parent @@ -51,7 +58,6 @@ org.springframework.boot spring-boot-starter-web - ${spring-boot-starter-web.version} org.springframework.boot diff --git a/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml b/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml index ba03ad3348..44e5bf2501 100644 --- a/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml +++ b/spring-cloud/spring-cloud-hystrix/rest-consumer/pom.xml @@ -16,6 +16,13 @@ + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-starter-parent @@ -40,24 +47,20 @@ org.springframework.boot spring-boot-starter-web - ${spring-boot-starter-web.version} org.springframework.boot spring-boot-starter-thymeleaf - ${spring-boot-starter-web.version} org.springframework.boot spring-boot-starter-actuator - ${spring-boot-starter-web.version} org.springframework.boot spring-boot-starter-test test - ${spring-boot-starter-web.version} diff --git a/spring-cloud/spring-cloud-hystrix/rest-producer/pom.xml b/spring-cloud/spring-cloud-hystrix/rest-producer/pom.xml index cb7377d705..e7be8f2c58 100644 --- a/spring-cloud/spring-cloud-hystrix/rest-producer/pom.xml +++ b/spring-cloud/spring-cloud-hystrix/rest-producer/pom.xml @@ -18,13 +18,11 @@ org.springframework.boot spring-boot-starter-web - ${spring-boot-starter-web.version} org.springframework.boot spring-boot-starter-test - ${spring-boot-starter-web.version} test diff --git a/spring-cloud/spring-cloud-kubernetes/kubernetes-minikube/demo-frontend/pom.xml b/spring-cloud/spring-cloud-kubernetes/kubernetes-minikube/demo-frontend/pom.xml index 9a4924b903..004fabeb09 100644 --- a/spring-cloud/spring-cloud-kubernetes/kubernetes-minikube/demo-frontend/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/kubernetes-minikube/demo-frontend/pom.xml @@ -33,5 +33,4 @@ - diff --git a/spring-cloud/spring-cloud-kubernetes/pom.xml b/spring-cloud/spring-cloud-kubernetes/pom.xml index ed4bccbf78..44c429d8f5 100644 --- a/spring-cloud/spring-cloud-kubernetes/pom.xml +++ b/spring-cloud/spring-cloud-kubernetes/pom.xml @@ -24,4 +24,7 @@ kubernetes-guide/travel-agency-service + + 2.3.3.RELEASE + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-netflix-feign/README.md b/spring-cloud/spring-cloud-netflix-feign/README.md new file mode 100644 index 0000000000..2e96a0045d --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [Differences Between Netflix Feign and OpenFeign](https://www.baeldung.com/netflix-feign-vs-openfeign) diff --git a/spring-cloud/spring-cloud-netflix-feign/pom.xml b/spring-cloud/spring-cloud-netflix-feign/pom.xml new file mode 100644 index 0000000000..aa5ba5dbdb --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/pom.xml @@ -0,0 +1,71 @@ + + + 4.0.0 + com.baeldung.cloud + spring-cloud-netlix-feign + 0.0.1-SNAPSHOT + spring-cloud-netflix-feign + Netflix Feign project for Spring Boot + + + com.baeldung + parent-boot-1 + 0.0.1-SNAPSHOT + ../../parent-boot-1 + + + + + + org.springframework.cloud + spring-cloud-dependencies + ${spring-cloud.version} + pom + import + + + + + + + org.springframework.cloud + spring-cloud-starter-feign + + + + com.netflix.feign + feign-okhttp + ${feign-ok.version} + + + + org.springframework.boot + spring-boot-starter-web + + + + org.apache.httpcomponents + httpcore + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + Camden.SR7 + 8.18.0 + + + + + diff --git a/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/ExampleApplication.java b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/ExampleApplication.java new file mode 100644 index 0000000000..e5ed9cbecf --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/ExampleApplication.java @@ -0,0 +1,16 @@ +package com.baeldung.cloud.netflix.feign; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.netflix.feign.EnableFeignClients; + +@SpringBootApplication +@EnableFeignClients +public class ExampleApplication { + + public static void main(String[] args) { + SpringApplication.run(ExampleApplication.class, args); + } + +} + diff --git a/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/client/JSONPlaceHolderClient.java b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/client/JSONPlaceHolderClient.java new file mode 100644 index 0000000000..80a455a4c4 --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/client/JSONPlaceHolderClient.java @@ -0,0 +1,25 @@ +package com.baeldung.cloud.netflix.feign.client; + +import com.baeldung.cloud.netflix.feign.config.ClientConfiguration; +import com.baeldung.cloud.netflix.feign.hystrix.JSONPlaceHolderFallback; +import com.baeldung.cloud.netflix.feign.model.Post; +import org.springframework.cloud.netflix.feign.FeignClient; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.util.List; + +@FeignClient(value = "jplaceholder", + url = "https://jsonplaceholder.typicode.com/", + configuration = ClientConfiguration.class, + fallback = JSONPlaceHolderFallback.class) +public interface JSONPlaceHolderClient { + + @RequestMapping(method = RequestMethod.GET, value = "/posts") + List getPosts(); + + + @RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json") + Post getPostById(@PathVariable("postId") Long postId); +} diff --git a/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/config/ClientConfiguration.java b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/config/ClientConfiguration.java new file mode 100644 index 0000000000..bc211b181e --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/config/ClientConfiguration.java @@ -0,0 +1,38 @@ +package com.baeldung.cloud.netflix.feign.config; + +import feign.Logger; +import feign.RequestInterceptor; +import feign.codec.ErrorDecoder; +import feign.okhttp.OkHttpClient; + +import org.apache.http.entity.ContentType; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ClientConfiguration { + + @Bean + public Logger.Level feignLoggerLevel() { + return Logger.Level.FULL; + } + + @Bean + public ErrorDecoder errorDecoder() { + return new ErrorDecoder.Default(); + } + + @Bean + public OkHttpClient client() { + return new OkHttpClient(); + } + + @Bean + public RequestInterceptor requestInterceptor() { + return requestTemplate -> { + requestTemplate.header("user", "ajeje"); + requestTemplate.header("password", "brazof"); + requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType()); + }; + } +} diff --git a/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/config/CustomErrorDecoder.java b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/config/CustomErrorDecoder.java new file mode 100644 index 0000000000..3e0e80f6d5 --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/config/CustomErrorDecoder.java @@ -0,0 +1,21 @@ +package com.baeldung.cloud.netflix.feign.config; + +import com.baeldung.cloud.netflix.feign.exception.BadRequestException; +import com.baeldung.cloud.netflix.feign.exception.NotFoundException; +import feign.Response; +import feign.codec.ErrorDecoder; + +public class CustomErrorDecoder implements ErrorDecoder { + @Override + public Exception decode(String methodKey, Response response) { + + switch (response.status()){ + case 400: + return new BadRequestException(); + case 404: + return new NotFoundException(); + default: + return new Exception("Generic error"); + } + } +} diff --git a/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/exception/BadRequestException.java b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/exception/BadRequestException.java new file mode 100644 index 0000000000..6a5f60f7c0 --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/exception/BadRequestException.java @@ -0,0 +1,21 @@ +package com.baeldung.cloud.netflix.feign.exception; + +public class BadRequestException extends Exception { + + public BadRequestException() { + } + + public BadRequestException(String message) { + super(message); + } + + public BadRequestException(Throwable cause) { + super(cause); + } + + @Override + public String toString() { + return "BadRequestException: "+getMessage(); + } + +} diff --git a/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/exception/NotFoundException.java b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/exception/NotFoundException.java new file mode 100644 index 0000000000..a8d89049fd --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/exception/NotFoundException.java @@ -0,0 +1,21 @@ +package com.baeldung.cloud.netflix.feign.exception; + +public class NotFoundException extends Exception { + + public NotFoundException() { + } + + public NotFoundException(String message) { + super(message); + } + + public NotFoundException(Throwable cause) { + super(cause); + } + + @Override + public String toString() { + return "NotFoundException: "+getMessage(); + } + +} diff --git a/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/hystrix/JSONPlaceHolderFallback.java b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/hystrix/JSONPlaceHolderFallback.java new file mode 100644 index 0000000000..ab1aa6bf50 --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/hystrix/JSONPlaceHolderFallback.java @@ -0,0 +1,22 @@ +package com.baeldung.cloud.netflix.feign.hystrix; + +import com.baeldung.cloud.netflix.feign.client.JSONPlaceHolderClient; +import com.baeldung.cloud.netflix.feign.model.Post; +import org.springframework.stereotype.Component; + +import java.util.Collections; +import java.util.List; + +@Component +public class JSONPlaceHolderFallback implements JSONPlaceHolderClient { + + @Override + public List getPosts() { + return Collections.emptyList(); + } + + @Override + public Post getPostById(Long postId) { + return null; + } +} diff --git a/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/model/Post.java b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/model/Post.java new file mode 100644 index 0000000000..73dd2bc198 --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/model/Post.java @@ -0,0 +1,41 @@ +package com.baeldung.cloud.netflix.feign.model; + +public class Post { + + private String userId; + private Long id; + private String title; + private String body; + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getBody() { + return body; + } + + public void setBody(String body) { + this.body = body; + } +} diff --git a/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/service/JSONPlaceHolderService.java b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/service/JSONPlaceHolderService.java new file mode 100644 index 0000000000..d2e174a1f0 --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/service/JSONPlaceHolderService.java @@ -0,0 +1,12 @@ +package com.baeldung.cloud.netflix.feign.service; + +import com.baeldung.cloud.netflix.feign.model.Post; + +import java.util.List; + +public interface JSONPlaceHolderService { + + List getPosts(); + + Post getPostById(Long id); +} diff --git a/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/service/impl/JSONPlaceHolderServiceImpl.java b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/service/impl/JSONPlaceHolderServiceImpl.java new file mode 100644 index 0000000000..0cc8d296f0 --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/src/main/java/com/baeldung/cloud/netflix/feign/service/impl/JSONPlaceHolderServiceImpl.java @@ -0,0 +1,26 @@ +package com.baeldung.cloud.netflix.feign.service.impl; + +import com.baeldung.cloud.netflix.feign.client.JSONPlaceHolderClient; +import com.baeldung.cloud.netflix.feign.model.Post; +import com.baeldung.cloud.netflix.feign.service.JSONPlaceHolderService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class JSONPlaceHolderServiceImpl implements JSONPlaceHolderService { + + @Autowired + private JSONPlaceHolderClient jsonPlaceHolderClient; + + @Override + public List getPosts() { + return jsonPlaceHolderClient.getPosts(); + } + + @Override + public Post getPostById(Long id) { + return jsonPlaceHolderClient.getPostById(id); + } +} diff --git a/spring-cloud/spring-cloud-netflix-feign/src/main/resources/application.properties b/spring-cloud/spring-cloud-netflix-feign/src/main/resources/application.properties new file mode 100644 index 0000000000..5927ccb9c1 --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/src/main/resources/application.properties @@ -0,0 +1,3 @@ +spring.application.name=netflix-feign +logging.level.com.baeldung.cloud.netflix.feign.client=DEBUG +feign.hystrix.enabled=true diff --git a/spring-cloud/spring-cloud-netflix-feign/src/test/java/com/baeldung/cloud/netflix/feign/ExampleTestApplication.java b/spring-cloud/spring-cloud-netflix-feign/src/test/java/com/baeldung/cloud/netflix/feign/ExampleTestApplication.java new file mode 100644 index 0000000000..f3c8459f87 --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/src/test/java/com/baeldung/cloud/netflix/feign/ExampleTestApplication.java @@ -0,0 +1,21 @@ +package com.baeldung.cloud.netflix.feign; + +import com.baeldung.cloud.netflix.feign.config.ClientConfiguration; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest +@EnableAutoConfiguration +@ContextConfiguration(classes = { ClientConfiguration.class }) +public class ExampleTestApplication { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } +} diff --git a/spring-cloud/spring-cloud-netflix-feign/src/test/java/com/baeldung/cloud/netflix/feign/NetflixFeignUnitTest.java b/spring-cloud/spring-cloud-netflix-feign/src/test/java/com/baeldung/cloud/netflix/feign/NetflixFeignUnitTest.java new file mode 100644 index 0000000000..880948d6d1 --- /dev/null +++ b/spring-cloud/spring-cloud-netflix-feign/src/test/java/com/baeldung/cloud/netflix/feign/NetflixFeignUnitTest.java @@ -0,0 +1,43 @@ +package com.baeldung.cloud.netflix.feign; + +import com.baeldung.cloud.netflix.feign.model.Post; +import com.baeldung.cloud.netflix.feign.service.JSONPlaceHolderService; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class NetflixFeignUnitTest { + + @Autowired + private JSONPlaceHolderService jsonPlaceHolderService; + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } + + @Test + public void whenGetPosts_thenListPostSizeGreaterThanZero() { + + List posts = jsonPlaceHolderService.getPosts(); + + assertFalse(posts.isEmpty()); + } + + @Test + public void whenGetPostWithId_thenPostExist() { + + Post post = jsonPlaceHolderService.getPostById(1L); + + assertNotNull(post); + } + +} diff --git a/spring-cloud/spring-cloud-openfeign/README.md b/spring-cloud/spring-cloud-openfeign/README.md index e5777732e4..bcfd769d0c 100644 --- a/spring-cloud/spring-cloud-openfeign/README.md +++ b/spring-cloud/spring-cloud-openfeign/README.md @@ -1,4 +1,5 @@ ### Relevant Articles: - [Introduction to Spring Cloud OpenFeign](https://www.baeldung.com/spring-cloud-openfeign) - +- [Differences Between Netflix Feign and OpenFeign](https://www.baeldung.com/netflix-feign-vs-openfeign) +- [File Upload With Open Feign](https://www.baeldung.com/java-feign-file-upload) diff --git a/spring-cloud/spring-cloud-openfeign/pom.xml b/spring-cloud/spring-cloud-openfeign/pom.xml index c1f3f2dc30..bdde46fe96 100644 --- a/spring-cloud/spring-cloud-openfeign/pom.xml +++ b/spring-cloud/spring-cloud-openfeign/pom.xml @@ -37,12 +37,24 @@ io.github.openfeign feign-okhttp - + org.springframework.boot spring-boot-starter-web + + + io.github.openfeign.form + feign-form + 3.8.0 + + + io.github.openfeign.form + feign-form-spring + 3.8.0 + + org.springframework.boot spring-boot-starter-test diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/ClientConfiguration.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/ClientConfiguration.java index 0b16134e92..55c27dde2f 100644 --- a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/ClientConfiguration.java +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/config/ClientConfiguration.java @@ -2,6 +2,7 @@ package com.baeldung.cloud.openfeign.config; import feign.Logger; import feign.RequestInterceptor; +import feign.auth.BasicAuthRequestInterceptor; import feign.codec.ErrorDecoder; import feign.okhttp.OkHttpClient; import org.apache.http.entity.ContentType; @@ -34,4 +35,9 @@ public class ClientConfiguration { requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType()); }; } + + // @Bean - uncomment to use this interceptor and remove @Bean from the requestInterceptor() + public BasicAuthRequestInterceptor basicAuthRequestInterceptor() { + return new BasicAuthRequestInterceptor("ajeje", "brazof"); + } } diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/config/FeignSupportConfig.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/config/FeignSupportConfig.java new file mode 100644 index 0000000000..943134213a --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/config/FeignSupportConfig.java @@ -0,0 +1,22 @@ +package com.baeldung.cloud.openfeign.fileupload.config; + +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.boot.autoconfigure.http.HttpMessageConverters; +import org.springframework.cloud.openfeign.support.SpringEncoder; +import org.springframework.context.annotation.Bean; +import org.springframework.web.client.RestTemplate; + +import feign.codec.Encoder; +import feign.form.spring.SpringFormEncoder; + +public class FeignSupportConfig { + @Bean + public Encoder multipartFormEncoder() { + return new SpringFormEncoder(new SpringEncoder(new ObjectFactory() { + @Override + public HttpMessageConverters getObject() { + return new HttpMessageConverters(new RestTemplate().getMessageConverters()); + } + })); + } +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/controller/FileController.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/controller/FileController.java new file mode 100644 index 0000000000..ebdf7ff6c8 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/controller/FileController.java @@ -0,0 +1,28 @@ +package com.baeldung.cloud.openfeign.fileupload.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import com.baeldung.cloud.openfeign.fileupload.service.UploadService; + +@RestController +public class FileController { + + @Autowired + private UploadService service; + + @PostMapping(value = "/upload") + public String handleFileUpload(@RequestPart(value = "file") MultipartFile file) { + return service.uploadFile(file); + } + + @PostMapping(value = "/upload-mannual-client") + public boolean handleFileUploadWithManualClient( + @RequestPart(value = "file") MultipartFile file) { + return service.uploadFileWithManualClient(file); + } + +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/service/UploadClient.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/service/UploadClient.java new file mode 100644 index 0000000000..63d17130e9 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/service/UploadClient.java @@ -0,0 +1,15 @@ +package com.baeldung.cloud.openfeign.fileupload.service; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; + +import com.baeldung.cloud.openfeign.fileupload.config.FeignSupportConfig; + +@FeignClient(name = "file", url = "http://localhost:8081", configuration = FeignSupportConfig.class) +public interface UploadClient { + @PostMapping(value = "/upload-file", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + String fileUpload(@RequestPart(value = "file") MultipartFile file); +} diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/service/UploadResource.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/service/UploadResource.java new file mode 100644 index 0000000000..26e658a7f0 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/service/UploadResource.java @@ -0,0 +1,16 @@ +package com.baeldung.cloud.openfeign.fileupload.service; + +import org.springframework.web.multipart.MultipartFile; + +import feign.Headers; +import feign.Param; +import feign.RequestLine; +import feign.Response; + +public interface UploadResource { + + @RequestLine("POST /upload-file") + @Headers("Content-Type: multipart/form-data") + Response uploadFile(@Param("file") MultipartFile file); + +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/service/UploadService.java b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/service/UploadService.java new file mode 100644 index 0000000000..7dd7f5a89c --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/main/java/com/baeldung/cloud/openfeign/fileupload/service/UploadService.java @@ -0,0 +1,29 @@ +package com.baeldung.cloud.openfeign.fileupload.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import feign.Feign; +import feign.Response; +import feign.form.spring.SpringFormEncoder; + +@Service +public class UploadService { + private static final String HTTP_FILE_UPLOAD_URL = "http://localhost:8081"; + + @Autowired + private UploadClient client; + + public boolean uploadFileWithManualClient(MultipartFile file) { + UploadResource fileUploadResource = Feign.builder().encoder(new SpringFormEncoder()) + .target(UploadResource.class, HTTP_FILE_UPLOAD_URL); + Response response = fileUploadResource.uploadFile(file); + return response.status() == 200; + } + + public String uploadFile(MultipartFile file) { + return client.fileUpload(file); + } + +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-openfeign/src/main/resources/fileupload.txt b/spring-cloud/spring-cloud-openfeign/src/main/resources/fileupload.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenFeignFileUploadLiveTest.java b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenFeignFileUploadLiveTest.java new file mode 100644 index 0000000000..f558e07491 --- /dev/null +++ b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenFeignFileUploadLiveTest.java @@ -0,0 +1,50 @@ +package com.baeldung.cloud.openfeign; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import org.apache.commons.io.IOUtils; +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.mock.web.MockMultipartFile; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.multipart.MultipartFile; + +import com.baeldung.cloud.openfeign.fileupload.service.UploadService; + +@RunWith(SpringRunner.class) +@SpringBootTest +public class OpenFeignFileUploadLiveTest { + + @Autowired + private UploadService uploadService; + + private static String FILE_NAME = "fileupload.txt"; + + @Test + public void whenFeignBuilder_thenFileUploadSuccess() throws IOException { + ClassLoader classloader = Thread.currentThread().getContextClassLoader(); + File file = new File(classloader.getResource(FILE_NAME).getFile()); + Assert.assertTrue(file.exists()); + FileInputStream input = new FileInputStream(file); + MultipartFile multipartFile = new MockMultipartFile("file", file.getName(), "text/plain", + IOUtils.toByteArray(input)); + Assert.assertTrue(uploadService.uploadFileWithManualClient(multipartFile)); + } + + @Test + public void whenAnnotatedFeignClient_thenFileUploadSuccess() throws IOException { + ClassLoader classloader = Thread.currentThread().getContextClassLoader(); + File file = new File(classloader.getResource(FILE_NAME).getFile()); + Assert.assertTrue(file.exists()); + FileInputStream input = new FileInputStream(file); + MultipartFile multipartFile = new MockMultipartFile("file", file.getName(), "text/plain", + IOUtils.toByteArray(input)); + String uploadFile = uploadService.uploadFile(multipartFile); + Assert.assertNotNull(uploadFile); + } +} diff --git a/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignUnitTest.java b/spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignManualTest.java similarity index 100% rename from spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignUnitTest.java rename to spring-cloud/spring-cloud-openfeign/src/test/java/com/baeldung/cloud/openfeign/OpenfeignManualTest.java diff --git a/spring-cloud/spring-cloud-rest/spring-cloud-rest-books-api/pom.xml b/spring-cloud/spring-cloud-rest/spring-cloud-rest-books-api/pom.xml index 042f7657ab..8ba0fc5cad 100644 --- a/spring-cloud/spring-cloud-rest/spring-cloud-rest-books-api/pom.xml +++ b/spring-cloud/spring-cloud-rest/spring-cloud-rest-books-api/pom.xml @@ -18,6 +18,13 @@ + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-dependencies @@ -65,7 +72,8 @@ org.springframework.boot spring-boot-starter-data-redis - + + diff --git a/spring-cloud/spring-cloud-rest/spring-cloud-rest-config-server/pom.xml b/spring-cloud/spring-cloud-rest/spring-cloud-rest-config-server/pom.xml index 5fb9364752..c64341f652 100644 --- a/spring-cloud/spring-cloud-rest/spring-cloud-rest-config-server/pom.xml +++ b/spring-cloud/spring-cloud-rest/spring-cloud-rest-config-server/pom.xml @@ -18,6 +18,13 @@ + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-dependencies @@ -45,6 +52,7 @@ Camden.SR4 + diff --git a/spring-cloud/spring-cloud-rest/spring-cloud-rest-discovery-server/pom.xml b/spring-cloud/spring-cloud-rest/spring-cloud-rest-discovery-server/pom.xml index 5e35a7c0f5..85790bf895 100644 --- a/spring-cloud/spring-cloud-rest/spring-cloud-rest-discovery-server/pom.xml +++ b/spring-cloud/spring-cloud-rest/spring-cloud-rest-discovery-server/pom.xml @@ -18,6 +18,13 @@ + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-dependencies @@ -53,6 +60,7 @@ Edgware.SR4 + diff --git a/spring-cloud/spring-cloud-rest/spring-cloud-rest-reviews-api/pom.xml b/spring-cloud/spring-cloud-rest/spring-cloud-rest-reviews-api/pom.xml index 7503418ad2..35d0e79543 100644 --- a/spring-cloud/spring-cloud-rest/spring-cloud-rest-reviews-api/pom.xml +++ b/spring-cloud/spring-cloud-rest/spring-cloud-rest-reviews-api/pom.xml @@ -18,6 +18,13 @@ + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-dependencies @@ -75,6 +82,7 @@ 3.0.1 0.6 + diff --git a/spring-cloud/spring-cloud-ribbon-client/pom.xml b/spring-cloud/spring-cloud-ribbon-client/pom.xml index e19d3beaad..7bc7b51d51 100644 --- a/spring-cloud/spring-cloud-ribbon-client/pom.xml +++ b/spring-cloud/spring-cloud-ribbon-client/pom.xml @@ -16,6 +16,13 @@ + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-dependencies @@ -39,6 +46,7 @@ Hoxton.SR4 + 2.3.3.RELEASE \ No newline at end of file diff --git a/spring-cloud/spring-cloud-ribbon-retry/pom.xml b/spring-cloud/spring-cloud-ribbon-retry/pom.xml index 27037d6710..99eb882421 100644 --- a/spring-cloud/spring-cloud-ribbon-retry/pom.xml +++ b/spring-cloud/spring-cloud-ribbon-retry/pom.xml @@ -23,6 +23,13 @@ + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-starter-parent @@ -48,5 +55,6 @@ Hoxton.SR3 + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-security/pom.xml b/spring-cloud/spring-cloud-security/pom.xml index 498c88ac48..f861b892c0 100644 --- a/spring-cloud/spring-cloud-security/pom.xml +++ b/spring-cloud/spring-cloud-security/pom.xml @@ -20,4 +20,7 @@ auth-server + + 2.3.3.RELEASE + diff --git a/spring-cloud/spring-cloud-stream/spring-cloud-stream-kafka/pom.xml b/spring-cloud/spring-cloud-stream/spring-cloud-stream-kafka/pom.xml index 669499efb7..52230dd1c1 100644 --- a/spring-cloud/spring-cloud-stream/spring-cloud-stream-kafka/pom.xml +++ b/spring-cloud/spring-cloud-stream/spring-cloud-stream-kafka/pom.xml @@ -105,6 +105,7 @@ Greenwich.SR1 4.0.0 1.8.2 + diff --git a/spring-cloud/spring-cloud-task/pom.xml b/spring-cloud/spring-cloud-task/pom.xml index e2006ee9d3..21d8a4e42b 100644 --- a/spring-cloud/spring-cloud-task/pom.xml +++ b/spring-cloud/spring-cloud-task/pom.xml @@ -22,6 +22,13 @@ + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-task-dependencies @@ -42,6 +49,7 @@ Hoxton.SR4 2.2.3.RELEASE + diff --git a/spring-cloud/spring-cloud-zookeeper/pom.xml b/spring-cloud/spring-cloud-zookeeper/pom.xml index 244ccbd957..e3241da02c 100644 --- a/spring-cloud/spring-cloud-zookeeper/pom.xml +++ b/spring-cloud/spring-cloud-zookeeper/pom.xml @@ -20,6 +20,7 @@ 5.2.7.RELEASE 1.0.3.RELEASE + 2.3.3.RELEASE \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zuul-eureka-integration/bin/eureka-client/pom.xml b/spring-cloud/spring-cloud-zuul-eureka-integration/bin/eureka-client/pom.xml index 118a9e2c11..321da7527a 100644 --- a/spring-cloud/spring-cloud-zuul-eureka-integration/bin/eureka-client/pom.xml +++ b/spring-cloud/spring-cloud-zuul-eureka-integration/bin/eureka-client/pom.xml @@ -35,7 +35,6 @@ org.springframework.boot spring-boot-starter-web - ${spring-boot-starter-web.version} diff --git a/spring-cloud/spring-cloud-zuul-eureka-integration/eureka-client/pom.xml b/spring-cloud/spring-cloud-zuul-eureka-integration/eureka-client/pom.xml index 9cf96df60e..77e8ef7c20 100644 --- a/spring-cloud/spring-cloud-zuul-eureka-integration/eureka-client/pom.xml +++ b/spring-cloud/spring-cloud-zuul-eureka-integration/eureka-client/pom.xml @@ -35,13 +35,13 @@ org.springframework.boot spring-boot-starter-web - ${spring-boot-starter-web.version} + ${spring-boot.version} org.springframework.boot spring-boot-starter-test - ${spring-boot-starter-web.version} + ${spring-boot.version} test diff --git a/spring-cloud/spring-cloud-zuul-eureka-integration/eureka-server/pom.xml b/spring-cloud/spring-cloud-zuul-eureka-integration/eureka-server/pom.xml index cd25f5f294..c3f6642351 100644 --- a/spring-cloud/spring-cloud-zuul-eureka-integration/eureka-server/pom.xml +++ b/spring-cloud/spring-cloud-zuul-eureka-integration/eureka-server/pom.xml @@ -41,7 +41,7 @@ org.springframework.boot spring-boot-starter-test - ${spring-boot-starter-web.version} + ${spring-boot.version} test diff --git a/spring-cloud/spring-cloud-zuul-eureka-integration/zuul-server/pom.xml b/spring-cloud/spring-cloud-zuul-eureka-integration/zuul-server/pom.xml index 3d238d5d5f..ddffe540c5 100644 --- a/spring-cloud/spring-cloud-zuul-eureka-integration/zuul-server/pom.xml +++ b/spring-cloud/spring-cloud-zuul-eureka-integration/zuul-server/pom.xml @@ -50,7 +50,6 @@ org.springframework.boot spring-boot-starter-test - ${spring-boot-starter-web.version} test diff --git a/spring-cloud/spring-cloud-zuul-fallback/api-gateway/pom.xml b/spring-cloud/spring-cloud-zuul-fallback/api-gateway/pom.xml index 136461ccb9..4e092736a5 100644 --- a/spring-cloud/spring-cloud-zuul-fallback/api-gateway/pom.xml +++ b/spring-cloud/spring-cloud-zuul-fallback/api-gateway/pom.xml @@ -12,10 +12,18 @@ com.baeldung.spring.cloud spring-cloud-zuul-fallback 1.0.0-SNAPSHOT + ../pom.xml + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-starter-parent diff --git a/spring-cloud/spring-cloud-zuul-fallback/weather-service/pom.xml b/spring-cloud/spring-cloud-zuul-fallback/weather-service/pom.xml index bafd4ffcd1..d2914b48bf 100644 --- a/spring-cloud/spring-cloud-zuul-fallback/weather-service/pom.xml +++ b/spring-cloud/spring-cloud-zuul-fallback/weather-service/pom.xml @@ -15,6 +15,13 @@ + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-starter-parent diff --git a/spring-cloud/spring-cloud-zuul/pom.xml b/spring-cloud/spring-cloud-zuul/pom.xml index b3c66dd1c6..6035ba7e59 100644 --- a/spring-cloud/spring-cloud-zuul/pom.xml +++ b/spring-cloud/spring-cloud-zuul/pom.xml @@ -24,6 +24,13 @@ + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + org.springframework.cloud spring-cloud-dependencies @@ -73,6 +80,7 @@ Hoxton.SR4 + 2.3.3.RELEASE diff --git a/spring-cloud/spring-cloud-zuul/spring-zuul-rate-limiting/pom.xml b/spring-cloud/spring-cloud-zuul/spring-zuul-rate-limiting/pom.xml index 8873282d1e..b42d32b6b3 100644 --- a/spring-cloud/spring-cloud-zuul/spring-zuul-rate-limiting/pom.xml +++ b/spring-cloud/spring-cloud-zuul/spring-zuul-rate-limiting/pom.xml @@ -13,18 +13,6 @@ 0.0.1-SNAPSHOT - - - - org.springframework.cloud - spring-cloud-dependencies - ${spring-cloud.version} - pom - import - - - - com.marcosbarbero.cloud diff --git a/spring-cloud/spring-cloud-zuul/spring-zuul-rate-limiting/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerUnitTest.java b/spring-cloud/spring-cloud-zuul/spring-zuul-rate-limiting/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerIntegrationTest.java similarity index 88% rename from spring-cloud/spring-cloud-zuul/spring-zuul-rate-limiting/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerUnitTest.java rename to spring-cloud/spring-cloud-zuul/spring-zuul-rate-limiting/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerIntegrationTest.java index d23ec836f9..7fdc723305 100644 --- a/spring-cloud/spring-cloud-zuul/spring-zuul-rate-limiting/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerUnitTest.java +++ b/spring-cloud/spring-cloud-zuul/spring-zuul-rate-limiting/src/test/java/com/baeldung/spring/cloud/zuulratelimitdemo/controller/GreetingControllerIntegrationTest.java @@ -5,14 +5,21 @@ import static com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.support.RateL import static com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.support.RateLimitConstants.HEADER_REMAINING; import static com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.support.RateLimitConstants.HEADER_REMAINING_QUOTA; import static com.marcosbarbero.cloud.autoconfigure.zuul.ratelimit.support.RateLimitConstants.HEADER_RESET; +import static java.lang.Integer.parseInt; +import static org.hamcrest.Matchers.both; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.lessThanOrEqualTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; import static org.springframework.http.HttpStatus.OK; import static org.springframework.http.HttpStatus.TOO_MANY_REQUESTS; import java.util.concurrent.TimeUnit; + import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -26,7 +33,7 @@ import org.springframework.test.context.junit4.SpringRunner; @AutoConfigureTestDatabase @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class GreetingControllerUnitTest { +public class GreetingControllerIntegrationTest { private static final String SIMPLE_GREETING = "/greeting/simple"; private static final String ADVANCED_GREETING = "/greeting/advanced"; @@ -44,9 +51,13 @@ public class GreetingControllerUnitTest { String remaining = headers.getFirst(HEADER_REMAINING + key); String reset = headers.getFirst(HEADER_RESET + key); - assertEquals(limit, "5"); - assertEquals(remaining, "4"); - assertEquals(reset, "60000"); + assertEquals("5", limit); + assertEquals(remaining, "4", remaining); + assertNotNull(reset); + assertThat( + parseInt(reset), + is(both(greaterThanOrEqualTo(0)).and(lessThanOrEqualTo(60000))) + ); assertEquals(OK, response.getStatusCode()); } diff --git a/spring-core-2/pom.xml b/spring-core-2/pom.xml index edbb351bd0..3f8e84e13d 100644 --- a/spring-core-2/pom.xml +++ b/spring-core-2/pom.xml @@ -198,7 +198,7 @@ com.baeldung.sample.App - 5.2.2.RELEASE + 5.3.0 1.3.2 5.2.5.Final diff --git a/spring-core-3/README.md b/spring-core-3/README.md index b6257cb9a4..7232ad71a1 100644 --- a/spring-core-3/README.md +++ b/spring-core-3/README.md @@ -11,4 +11,4 @@ This module contains articles about core Spring functionality - [Difference Between BeanFactory and ApplicationContext](https://www.baeldung.com/spring-beanfactory-vs-applicationcontext) - [A Spring Custom Annotation for a Better DAO](http://www.baeldung.com/spring-annotation-bean-pre-processor) - [Custom Scope in Spring](http://www.baeldung.com/spring-custom-scope) -- More articles: [[<-- prev]](/spring-core-2) +- More articles: [[<-- prev]](/spring-core-2) [[next -->]](/spring-core-4) diff --git a/spring-core-4/README.md b/spring-core-4/README.md index 03a6747c1d..3b2c3d4764 100644 --- a/spring-core-4/README.md +++ b/spring-core-4/README.md @@ -11,4 +11,4 @@ This module contains articles about core Spring functionality - [Using @Autowired in Abstract Classes](https://www.baeldung.com/spring-autowired-abstract-class) - [Constructor Injection in Spring with Lombok](https://www.baeldung.com/spring-injection-lombok) - [The Spring ApplicationContext](https://www.baeldung.com/spring-application-context) -- More articles: [[<-- prev]](/spring-core-3) +- More articles: [[<-- prev]](/spring-core-3) [[next -->]](/spring-core-5) diff --git a/spring-core-5/README.md b/spring-core-5/README.md new file mode 100644 index 0000000000..4109faca67 --- /dev/null +++ b/spring-core-5/README.md @@ -0,0 +1,8 @@ +## Spring Core + +This module contains articles about core Spring functionality + +## Relevant Articles: + +- [Spring @Component Annotation](https://www.baeldung.com/spring-component-annotation) +- More articles: [[<-- prev]](/spring-core-4) diff --git a/spring-core-5/pom.xml b/spring-core-5/pom.xml new file mode 100644 index 0000000000..743002c137 --- /dev/null +++ b/spring-core-5/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + spring-core-5 + spring-core-5 + + + com.baeldung + parent-spring-5 + 0.0.1-SNAPSHOT + ../parent-spring-5 + + + + + org.springframework.boot + spring-boot-starter + ${spring-boot-starter.version} + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot-starter.version} + test + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven.surefire.version} + + + + + + 5.3.3 + 2.4.2 + 2.22.1 + + + diff --git a/spring-core-5/src/main/java/com/baeldung/component/inscope/AmbiguousBean.java b/spring-core-5/src/main/java/com/baeldung/component/inscope/AmbiguousBean.java new file mode 100644 index 0000000000..70e1f0a79a --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/component/inscope/AmbiguousBean.java @@ -0,0 +1,4 @@ +package com.baeldung.component.inscope; + +public interface AmbiguousBean { +} diff --git a/spring-core-5/src/main/java/com/baeldung/component/inscope/BeanExample.java b/spring-core-5/src/main/java/com/baeldung/component/inscope/BeanExample.java new file mode 100644 index 0000000000..d1b4cd34f1 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/component/inscope/BeanExample.java @@ -0,0 +1,4 @@ +package com.baeldung.component.inscope; + +public class BeanExample { +} diff --git a/spring-core-5/src/main/java/com/baeldung/component/inscope/BeanImplA.java b/spring-core-5/src/main/java/com/baeldung/component/inscope/BeanImplA.java new file mode 100644 index 0000000000..08e1661499 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/component/inscope/BeanImplA.java @@ -0,0 +1,4 @@ +package com.baeldung.component.inscope; + +public class BeanImplA implements AmbiguousBean { +} diff --git a/spring-core-5/src/main/java/com/baeldung/component/inscope/BeanImplB.java b/spring-core-5/src/main/java/com/baeldung/component/inscope/BeanImplB.java new file mode 100644 index 0000000000..8a45581532 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/component/inscope/BeanImplB.java @@ -0,0 +1,4 @@ +package com.baeldung.component.inscope; + +public class BeanImplB implements AmbiguousBean { +} diff --git a/spring-core-5/src/main/java/com/baeldung/component/inscope/ComponentApplication.java b/spring-core-5/src/main/java/com/baeldung/component/inscope/ComponentApplication.java new file mode 100644 index 0000000000..604e7d6632 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/component/inscope/ComponentApplication.java @@ -0,0 +1,42 @@ +package com.baeldung.component.inscope; + +import com.baeldung.component.outsidescope.OutsideScopeBeanExample; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +@SpringBootApplication +@ComponentScan({"com.baeldung.component.inscope", "com.baeldung.component.scannedscope"}) +@Configuration +public class ComponentApplication { + + @Value( "${ambiguous-bean}" ) + public String ambiguousBean; + + public static void main(String[] args) { + SpringApplication.run( ComponentApplication.class, args ); + } + + @Bean + public BeanExample beanExample() { + return new BeanExample(); + } + + @Bean + public OutsideScopeBeanExample outsideScopeBeanExample() { + return new OutsideScopeBeanExample(); + } + + @Bean + public AmbiguousBean ambiguousBean() { + if (ambiguousBean.equals("A")) { + return new BeanImplA(); + } + else { + return new BeanImplB(); + } + } +} \ No newline at end of file diff --git a/spring-core-5/src/main/java/com/baeldung/component/inscope/ComponentExample.java b/spring-core-5/src/main/java/com/baeldung/component/inscope/ComponentExample.java new file mode 100644 index 0000000000..66d3e20d34 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/component/inscope/ComponentExample.java @@ -0,0 +1,7 @@ +package com.baeldung.component.inscope; + +import org.springframework.stereotype.Component; + +@Component +public class ComponentExample { +} diff --git a/spring-core-5/src/main/java/com/baeldung/component/inscope/ControllerExample.java b/spring-core-5/src/main/java/com/baeldung/component/inscope/ControllerExample.java new file mode 100644 index 0000000000..773af2a113 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/component/inscope/ControllerExample.java @@ -0,0 +1,7 @@ +package com.baeldung.component.inscope; + +import org.springframework.stereotype.Controller; + +@Controller +public class ControllerExample { +} diff --git a/spring-core-5/src/main/java/com/baeldung/component/inscope/CustomComponent.java b/spring-core-5/src/main/java/com/baeldung/component/inscope/CustomComponent.java new file mode 100644 index 0000000000..795a1b23fa --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/component/inscope/CustomComponent.java @@ -0,0 +1,14 @@ +package com.baeldung.component.inscope; + +import org.springframework.stereotype.Component; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@Component +public @interface CustomComponent { +} diff --git a/spring-core-5/src/main/java/com/baeldung/component/inscope/CustomComponentExample.java b/spring-core-5/src/main/java/com/baeldung/component/inscope/CustomComponentExample.java new file mode 100644 index 0000000000..8009f8ec20 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/component/inscope/CustomComponentExample.java @@ -0,0 +1,5 @@ +package com.baeldung.component.inscope; + +@CustomComponent +public class CustomComponentExample { +} diff --git a/spring-core-5/src/main/java/com/baeldung/component/inscope/RepositoryExample.java b/spring-core-5/src/main/java/com/baeldung/component/inscope/RepositoryExample.java new file mode 100644 index 0000000000..9297992904 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/component/inscope/RepositoryExample.java @@ -0,0 +1,7 @@ +package com.baeldung.component.inscope; + +import org.springframework.stereotype.Repository; + +@Repository +public class RepositoryExample { +} diff --git a/spring-core-5/src/main/java/com/baeldung/component/inscope/ServiceExample.java b/spring-core-5/src/main/java/com/baeldung/component/inscope/ServiceExample.java new file mode 100644 index 0000000000..e2db60504a --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/component/inscope/ServiceExample.java @@ -0,0 +1,7 @@ +package com.baeldung.component.inscope; + +import org.springframework.stereotype.Service; + +@Service +public class ServiceExample { +} diff --git a/spring-core-5/src/main/java/com/baeldung/component/outsidescope/OutsideScopeBeanExample.java b/spring-core-5/src/main/java/com/baeldung/component/outsidescope/OutsideScopeBeanExample.java new file mode 100644 index 0000000000..079c012862 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/component/outsidescope/OutsideScopeBeanExample.java @@ -0,0 +1,4 @@ +package com.baeldung.component.outsidescope; + +public class OutsideScopeBeanExample { +} diff --git a/spring-core-5/src/main/java/com/baeldung/component/outsidescope/OutsideScopeExample.java b/spring-core-5/src/main/java/com/baeldung/component/outsidescope/OutsideScopeExample.java new file mode 100644 index 0000000000..5c7fff959d --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/component/outsidescope/OutsideScopeExample.java @@ -0,0 +1,7 @@ +package com.baeldung.component.outsidescope; + +import org.springframework.stereotype.Component; + +@Component +public class OutsideScopeExample { +} diff --git a/spring-core-5/src/main/java/com/baeldung/component/scannedscope/ScannedScopeExample.java b/spring-core-5/src/main/java/com/baeldung/component/scannedscope/ScannedScopeExample.java new file mode 100644 index 0000000000..59873634d6 --- /dev/null +++ b/spring-core-5/src/main/java/com/baeldung/component/scannedscope/ScannedScopeExample.java @@ -0,0 +1,7 @@ +package com.baeldung.component.scannedscope; + +import org.springframework.stereotype.Component; + +@Component +public class ScannedScopeExample { +} diff --git a/spring-core-5/src/main/resources/application.yml b/spring-core-5/src/main/resources/application.yml new file mode 100644 index 0000000000..5c09fdb8b0 --- /dev/null +++ b/spring-core-5/src/main/resources/application.yml @@ -0,0 +1 @@ +ambiguous-bean: 'A' \ No newline at end of file diff --git a/spring-core-5/src/test/java/com/baeldung/component/inscope/ComponentUnitTest.java b/spring-core-5/src/test/java/com/baeldung/component/inscope/ComponentUnitTest.java new file mode 100644 index 0000000000..09ce604d40 --- /dev/null +++ b/spring-core-5/src/test/java/com/baeldung/component/inscope/ComponentUnitTest.java @@ -0,0 +1,54 @@ +package com.baeldung.component.inscope; + +import com.baeldung.component.outsidescope.OutsideScopeBeanExample; +import com.baeldung.component.outsidescope.OutsideScopeExample; +import com.baeldung.component.scannedscope.ScannedScopeExample; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@ExtendWith(SpringExtension.class) +public class ComponentUnitTest { + + @Autowired + private ApplicationContext applicationContext; + + @Test + public void givenInScopeComponents_whenSearchingInApplicationContext_thenFindThem() { + assertNotNull(applicationContext.getBean(ControllerExample.class)); + assertNotNull(applicationContext.getBean(ServiceExample.class)); + assertNotNull(applicationContext.getBean(RepositoryExample.class)); + assertNotNull(applicationContext.getBean(ComponentExample.class)); + assertNotNull(applicationContext.getBean(CustomComponentExample.class)); + } + + @Test + public void givenOutsideScopeComponent_whenSearchingInApplicationContext_thenFail() { + assertThrows(NoSuchBeanDefinitionException.class, () -> applicationContext.getBean(OutsideScopeExample.class)); + } + + @Test + public void givenScannedScopeComponent_whenSearchingInApplicationContext_thenFindIt() { + assertNotNull(applicationContext.getBean(ScannedScopeExample.class)); + } + + @Test + public void givenBeanComponents_whenSearchingInApplicationContext_thenFindThem() { + assertNotNull(applicationContext.getBean(BeanExample.class)); + assertNotNull(applicationContext.getBean(OutsideScopeBeanExample.class)); + } + + @Test + public void givenAmbiguousBeanSetToB_whenSearchingInApplicationContext_thenFindImplB() { + AmbiguousBean ambiguousBean = applicationContext.getBean(AmbiguousBean.class); + assertNotNull(ambiguousBean); + assertTrue(ambiguousBean instanceof BeanImplB); + } +} \ No newline at end of file diff --git a/spring-core-5/src/test/resources/application.yml b/spring-core-5/src/test/resources/application.yml new file mode 100644 index 0000000000..da23e59c24 --- /dev/null +++ b/spring-core-5/src/test/resources/application.yml @@ -0,0 +1 @@ +ambiguous-bean: 'B' \ No newline at end of file diff --git a/spring-core/pom.xml b/spring-core/pom.xml index eb25bcd517..7d83fc198c 100644 --- a/spring-core/pom.xml +++ b/spring-core/pom.xml @@ -65,7 +65,7 @@ commons-io commons-io - ${commons.io.version} + ${commons-io.version} @@ -86,7 +86,6 @@ 1.4.4.RELEASE 1 20.0 - 2.5 1.5.2.RELEASE 1.10.19 3.12.2 diff --git a/spring-core/src/test/java/com/baeldung/classpathfileaccess/SpringResourceIntegrationTest.java b/spring-core/src/test/java/com/baeldung/classpathfileaccess/SpringResourceIntegrationTest.java index b57a64a8c6..38f857b42e 100644 --- a/spring-core/src/test/java/com/baeldung/classpathfileaccess/SpringResourceIntegrationTest.java +++ b/spring-core/src/test/java/com/baeldung/classpathfileaccess/SpringResourceIntegrationTest.java @@ -1,16 +1,5 @@ package com.baeldung.classpathfileaccess; -import static org.junit.Assert.assertEquals; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.file.Files; -import java.util.stream.Collectors; - import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; @@ -24,6 +13,17 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; import org.springframework.util.ResourceUtils; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; + /** * Test class illustrating various methods of accessing a file from the classpath using Resource. * @author tritty @@ -55,7 +55,7 @@ public class SpringResourceIntegrationTest { @Test public void whenResourceLoader_thenReadSuccessful() throws IOException { - final Resource resource = resourceLoader.getResource("classpath:data/employees.dat"); + final Resource resource = loadEmployeesWithResourceLoader(); final String employees = new String(Files.readAllBytes(resource.getFile() .toPath())); assertEquals(EMPLOYEES_EXPECTED, employees); @@ -63,7 +63,7 @@ public class SpringResourceIntegrationTest { @Test public void whenApplicationContext_thenReadSuccessful() throws IOException { - final Resource resource = appContext.getResource("classpath:data/employees.dat"); + final Resource resource = loadEmployeesWithApplicationContext(); final String employees = new String(Files.readAllBytes(resource.getFile() .toPath())); assertEquals(EMPLOYEES_EXPECTED, employees); @@ -85,7 +85,7 @@ public class SpringResourceIntegrationTest { @Test public void whenResourceAsStream_thenReadSuccessful() throws IOException { - final InputStream resource = new ClassPathResource("data/employees.dat").getInputStream(); + final InputStream resource = loadEmployeesWithClassPathResource().getInputStream(); try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource))) { final String employees = reader.lines() .collect(Collectors.joining("\n")); @@ -95,7 +95,7 @@ public class SpringResourceIntegrationTest { @Test public void whenResourceAsFile_thenReadSuccessful() throws IOException { - final File resource = new ClassPathResource("data/employees.dat").getFile(); + final File resource = loadEmployeesWithClassPathResource().getFile(); final String employees = new String(Files.readAllBytes(resource.toPath())); assertEquals(EMPLOYEES_EXPECTED, employees); } @@ -114,7 +114,19 @@ public class SpringResourceIntegrationTest { assertEquals(EMPLOYEES_EXPECTED, employees); } - public File loadEmployeesWithSpringInternalClass() throws FileNotFoundException { + private File loadEmployeesWithSpringInternalClass() throws FileNotFoundException { return ResourceUtils.getFile("classpath:data/employees.dat"); } + + private Resource loadEmployeesWithClassPathResource(){ + return new ClassPathResource("data/employees.dat"); + } + + private Resource loadEmployeesWithResourceLoader(){ + return resourceLoader.getResource("classpath:data/employees.dat"); + } + + private Resource loadEmployeesWithApplicationContext(){ + return appContext.getResource("classpath:data/employees.dat"); + } } diff --git a/spring-cucumber/pom.xml b/spring-cucumber/pom.xml index 245d10e77b..a945797ee1 100644 --- a/spring-cucumber/pom.xml +++ b/spring-cucumber/pom.xml @@ -21,27 +21,27 @@ spring-boot-starter-web - info.cukes + io.cucumber cucumber-core - ${cucumber.java.version} + ${cucumber.version} test - info.cukes + io.cucumber cucumber-java - ${cucumber.java.version} + ${cucumber.version} test - info.cukes + io.cucumber cucumber-junit - ${cucumber.java.version} + ${cucumber.version} test - info.cukes + io.cucumber cucumber-spring - ${cucumber.java.version} + ${cucumber.version} test @@ -53,7 +53,7 @@ - 1.2.5 + 6.8.0 1.3.2 diff --git a/spring-cucumber/src/main/java/com/baeldung/BaeldungController.java b/spring-cucumber/src/main/java/com/baeldung/BaeldungController.java index e74e773106..713c1022c5 100644 --- a/spring-cucumber/src/main/java/com/baeldung/BaeldungController.java +++ b/spring-cucumber/src/main/java/com/baeldung/BaeldungController.java @@ -4,18 +4,16 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; -import javax.servlet.http.HttpServletResponse; - @RestController public class BaeldungController { @GetMapping("/hello") - public String sayHello(HttpServletResponse response) { + public String sayHello() { return "hello"; } @PostMapping("/baeldung") - public String sayHelloPost(HttpServletResponse response) { + public String sayHelloPost() { return "hello"; } } diff --git a/spring-cucumber/src/main/java/com/baeldung/VersionController.java b/spring-cucumber/src/main/java/com/baeldung/VersionController.java index f673f0e31f..e46ca64a01 100644 --- a/spring-cucumber/src/main/java/com/baeldung/VersionController.java +++ b/spring-cucumber/src/main/java/com/baeldung/VersionController.java @@ -1,13 +1,12 @@ package com.baeldung; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class VersionController { - @RequestMapping(method = { RequestMethod.GET }, value = { "/version" }) + @GetMapping("/version") public String getVersion() { return "1.0"; } diff --git a/spring-cucumber/src/test/java/com/baeldung/CucumberIntegrationTest.java b/spring-cucumber/src/test/java/com/baeldung/CucumberIntegrationTest.java index f48ab410ca..2077a28146 100644 --- a/spring-cucumber/src/test/java/com/baeldung/CucumberIntegrationTest.java +++ b/spring-cucumber/src/test/java/com/baeldung/CucumberIntegrationTest.java @@ -1,11 +1,11 @@ package com.baeldung; +import io.cucumber.junit.Cucumber; +import io.cucumber.junit.CucumberOptions; import org.junit.runner.RunWith; -import cucumber.api.CucumberOptions; -import cucumber.api.junit.Cucumber; @RunWith(Cucumber.class) @CucumberOptions(features = "src/test/resources") -public class CucumberIntegrationTest extends SpringIntegrationTest{ +public class CucumberIntegrationTest extends SpringIntegrationTest { } \ No newline at end of file diff --git a/spring-cucumber/src/test/java/com/baeldung/SpringIntegrationTest.java b/spring-cucumber/src/test/java/com/baeldung/SpringIntegrationTest.java index 8655a02469..7b5c4e21ff 100644 --- a/spring-cucumber/src/test/java/com/baeldung/SpringIntegrationTest.java +++ b/spring-cucumber/src/test/java/com/baeldung/SpringIntegrationTest.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.util.HashMap; import java.util.Map; +import io.cucumber.spring.CucumberContextConfiguration; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; @@ -13,9 +14,8 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.web.client.ResponseErrorHandler; import org.springframework.web.client.RestTemplate; -//@RunWith(SpringJUnit4ClassRunner.class) +@CucumberContextConfiguration @SpringBootTest(classes = SpringDemoApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT) -@ContextConfiguration public class SpringIntegrationTest { static ResponseResults latestResponse = null; diff --git a/spring-cucumber/src/test/java/com/baeldung/StepDefsIntegrationTest.java b/spring-cucumber/src/test/java/com/baeldung/StepDefsIntegrationTest.java index e1b6e370c7..9611e95dcf 100644 --- a/spring-cucumber/src/test/java/com/baeldung/StepDefsIntegrationTest.java +++ b/spring-cucumber/src/test/java/com/baeldung/StepDefsIntegrationTest.java @@ -1,14 +1,14 @@ package com.baeldung; +import io.cucumber.java.en.And; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import org.springframework.http.HttpStatus; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import cucumber.api.java.en.Given; -import org.springframework.http.HttpStatus; - -import cucumber.api.java.en.And; -import cucumber.api.java.en.Then; -import cucumber.api.java.en.When; public class StepDefsIntegrationTest extends SpringIntegrationTest { diff --git a/spring-data-rest/pom.xml b/spring-data-rest/pom.xml index 63a42857f4..dd96182264 100644 --- a/spring-data-rest/pom.xml +++ b/spring-data-rest/pom.xml @@ -99,6 +99,7 @@ com.baeldung.books.SpringDataRestApplication 1.0 + 2.3.3.RELEASE \ No newline at end of file diff --git a/spring-di/pom.xml b/spring-di/pom.xml index 48cdf60673..df0b685ae2 100644 --- a/spring-di/pom.xml +++ b/spring-di/pom.xml @@ -83,7 +83,7 @@ commons-io commons-io - ${commons.io.version} + ${commons-io.version} org.aspectj @@ -159,7 +159,6 @@ 1.4.4.RELEASE 1 20.0 - 2.5 1.5.2.RELEASE 1.10.19 3.12.2 diff --git a/spring-dispatcher-servlet/README.md b/spring-dispatcher-servlet/README.md deleted file mode 100644 index 3027546152..0000000000 --- a/spring-dispatcher-servlet/README.md +++ /dev/null @@ -1,7 +0,0 @@ -## Spring DispatcherServlet - -This module contains articles about Spring DispatcherServlet - -## Relevant articles: - -- [An Intro to the Spring DispatcherServlet](https://www.baeldung.com/spring-dispatcherservlet) diff --git a/spring-dispatcher-servlet/pom.xml b/spring-dispatcher-servlet/pom.xml deleted file mode 100644 index 46e40722f1..0000000000 --- a/spring-dispatcher-servlet/pom.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - 4.0.0 - spring-dispatcher-servlet - 1.0.0 - spring-dispatcher-servlet - war - - - com.baeldung - parent-spring-5 - 0.0.1-SNAPSHOT - ../parent-spring-5 - - - - - org.springframework - spring-web - ${spring.version} - - - org.springframework - spring-webmvc - ${spring.version} - - - javax.servlet - javax.servlet-api - ${javax.servlet-api.version} - - - javax.servlet.jsp.jstl - jstl-api - ${jstl-api.version} - - - javax.servlet.jsp - javax.servlet.jsp-api - ${javax.servlet.jsp-api.version} - - - org.codehaus.jackson - jackson-mapper-asl - ${jackson-mapper-asl.version} - - - javax.servlet - jstl - ${jstl.version} - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - - - commons-fileupload - commons-fileupload - ${commons-fileupload.version} - - - org.springframework.boot - spring-boot-starter-test - ${spring-boot-starter-test.version} - test - - - - - spring-dispatcher-servlet - - - - org.apache.tomcat.maven - tomcat8-maven-plugin - ${tomcat8-maven-plugin.version} - - /springdispatcherservlet - - - - org.apache.maven.plugins - maven-war-plugin - ${maven-war-plugin.version} - - src/main/webapp - false - - - - - - - - 3.0-r1655215 - - - \ No newline at end of file diff --git a/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/configuration/AppConfig.java b/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/configuration/AppConfig.java deleted file mode 100644 index c8a6cf06a6..0000000000 --- a/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/configuration/AppConfig.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.baeldung.springdispatcherservlet.configuration; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.ui.context.support.ResourceBundleThemeSource; -import org.springframework.web.multipart.commons.CommonsMultipartResolver; -import org.springframework.web.servlet.config.annotation.*; -import org.springframework.web.servlet.resource.PathResourceResolver; -import org.springframework.web.servlet.theme.CookieThemeResolver; -import org.springframework.web.servlet.theme.ThemeChangeInterceptor; -import org.springframework.web.servlet.view.JstlView; -import org.springframework.web.servlet.view.UrlBasedViewResolver; - -import java.io.IOException; - -@Configuration -@EnableWebMvc -@ComponentScan("com.baeldung.springdispatcherservlet") -public class AppConfig implements WebMvcConfigurer { - - public void addViewControllers(ViewControllerRegistry registry) { - registry.addViewController("/").setViewName("index"); - } - - /** Multipart file uploading configuratioin */ - @Bean - public CommonsMultipartResolver multipartResolver() throws IOException { - CommonsMultipartResolver resolver = new CommonsMultipartResolver(); - resolver.setMaxUploadSize(10000000); - return resolver; - } - - /** View resolver for JSP */ - @Bean - public UrlBasedViewResolver viewResolver() { - UrlBasedViewResolver resolver = new UrlBasedViewResolver(); - resolver.setPrefix("/WEB-INF/jsp/"); - resolver.setSuffix(".jsp"); - resolver.setViewClass(JstlView.class); - return resolver; - } - - /** Static resource locations including themes*/ - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/resources/**/*") - .addResourceLocations("/", "/resources/") - .setCachePeriod(3600) - .resourceChain(true) - .addResolver(new PathResourceResolver()); - } - - /** BEGIN theme configuration */ - @Bean - public ResourceBundleThemeSource themeSource(){ - ResourceBundleThemeSource themeSource = new ResourceBundleThemeSource(); - themeSource.setDefaultEncoding("UTF-8"); - themeSource.setBasenamePrefix("themes."); - return themeSource; - } - - @Bean - public CookieThemeResolver themeResolver(){ - CookieThemeResolver resolver = new CookieThemeResolver(); - resolver.setDefaultThemeName("default"); - resolver.setCookieName("example-theme-cookie"); - return resolver; - } - - @Bean - public ThemeChangeInterceptor themeChangeInterceptor(){ - ThemeChangeInterceptor interceptor = new ThemeChangeInterceptor(); - interceptor.setParamName("theme"); - return interceptor; - } - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(themeChangeInterceptor()); - } - /** END theme configuration */ -} \ No newline at end of file diff --git a/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/configuration/WebAppInitializer.java b/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/configuration/WebAppInitializer.java deleted file mode 100644 index 0c6c7141a7..0000000000 --- a/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/configuration/WebAppInitializer.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.baeldung.springdispatcherservlet.configuration; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRegistration; - -import org.springframework.web.WebApplicationInitializer; -import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; -import org.springframework.web.servlet.DispatcherServlet; - -public class WebAppInitializer implements WebApplicationInitializer { - - @Override - public void onStartup(ServletContext container) throws ServletException { - AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); - context.register(AppConfig.class); - context.setServletContext(container); - - ServletRegistration.Dynamic servlet = container.addServlet("dispatcher", new DispatcherServlet(context)); - servlet.setLoadOnStartup(1); - servlet.addMapping("/"); - } -} diff --git a/spring-dispatcher-servlet/src/main/webapp/WEB-INF/jsp/index.jsp b/spring-dispatcher-servlet/src/main/webapp/WEB-INF/jsp/index.jsp deleted file mode 100644 index c482eac361..0000000000 --- a/spring-dispatcher-servlet/src/main/webapp/WEB-INF/jsp/index.jsp +++ /dev/null @@ -1,30 +0,0 @@ -<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> -<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %> -<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> -<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" %> - - - - - - - Spring Dispatcher - - - -

Hello World!

-
- Switch Theme! - Switch Theme! -
-
-
-
- - -
-
-
- ${message} - - diff --git a/spring-dispatcher-servlet/src/main/webapp/resources/css/default.css b/spring-dispatcher-servlet/src/main/webapp/resources/css/default.css deleted file mode 100644 index 7f20f36d96..0000000000 --- a/spring-dispatcher-servlet/src/main/webapp/resources/css/default.css +++ /dev/null @@ -1,4 +0,0 @@ -h2 { - color: green; - font-weight: 400; -} \ No newline at end of file diff --git a/spring-dispatcher-servlet/src/main/webapp/resources/css/example.css b/spring-dispatcher-servlet/src/main/webapp/resources/css/example.css deleted file mode 100644 index fe31b0396a..0000000000 --- a/spring-dispatcher-servlet/src/main/webapp/resources/css/example.css +++ /dev/null @@ -1,4 +0,0 @@ -h2 { - color: red; - font-weight: 700; -} \ No newline at end of file diff --git a/spring-dispatcher-servlet/src/test/java/com/baeldung/SpringContextTest.java b/spring-dispatcher-servlet/src/test/java/com/baeldung/SpringContextTest.java deleted file mode 100644 index ba8040f81d..0000000000 --- a/spring-dispatcher-servlet/src/test/java/com/baeldung/SpringContextTest.java +++ /dev/null @@ -1,19 +0,0 @@ -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.springdispatcherservlet.configuration.AppConfig; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = AppConfig.class) -@WebAppConfiguration -public class SpringContextTest { - - @Test - public void whenSpringContextIsBootstrapped_thenNoExceptions() { - } -} diff --git a/spring-jersey/pom.xml b/spring-jersey/pom.xml index 3c84e9c11e..50d377b73f 100644 --- a/spring-jersey/pom.xml +++ b/spring-jersey/pom.xml @@ -226,7 +226,7 @@ 4.4.9 4.5.5 4.0.0 - 2.25.1 + 2.27.2 3.10.0 1.5.10.RELEASE diff --git a/spring-jinq/pom.xml b/spring-jinq/pom.xml index 647c0907a7..1f5d8cd915 100644 --- a/spring-jinq/pom.xml +++ b/spring-jinq/pom.xml @@ -27,11 +27,6 @@ h2
- - org.hibernate - hibernate-entitymanager - - org.springframework.boot spring-boot-starter-data-jpa diff --git a/spring-kafka/README.md b/spring-kafka/README.md index f2fecde894..ddb086c3bd 100644 --- a/spring-kafka/README.md +++ b/spring-kafka/README.md @@ -5,6 +5,7 @@ This module contains articles about Spring with Kafka ### Relevant articles - [Intro to Apache Kafka with Spring](https://www.baeldung.com/spring-kafka) +- [Testing Kafka and Spring Boot](https://www.baeldung.com/spring-boot-kafka-testing) ### Intro diff --git a/spring-kafka/pom.xml b/spring-kafka/pom.xml index 2b4a0914e6..235dd75966 100644 --- a/spring-kafka/pom.xml +++ b/spring-kafka/pom.xml @@ -1,9 +1,9 @@ - + 4.0.0 spring-kafka - 0.0.1-SNAPSHOT spring-kafka Intro to Kafka with Spring @@ -15,25 +15,36 @@ - org.springframework.boot spring-boot-starter - org.springframework.kafka spring-kafka + ${spring-kafka.version} - com.fasterxml.jackson.core jackson-databind + + org.springframework.kafka + spring-kafka-test + ${spring-kafka.version} + test + + + org.testcontainers + kafka + ${testcontainers-kafka.version} + test + - 2.3.7.RELEASE + 2.5.8.RELEASE + 1.15.0 \ No newline at end of file diff --git a/spring-kafka/src/main/java/com/baeldung/kafka/embedded/KafkaConsumer.java b/spring-kafka/src/main/java/com/baeldung/kafka/embedded/KafkaConsumer.java new file mode 100644 index 0000000000..48a194b4e3 --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/kafka/embedded/KafkaConsumer.java @@ -0,0 +1,39 @@ +package com.baeldung.kafka.embedded; + +import java.util.concurrent.CountDownLatch; + +import org.apache.kafka.clients.consumer.ConsumerRecord; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.stereotype.Component; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@Component +public class KafkaConsumer { + + private static final Logger LOGGER = LoggerFactory.getLogger(KafkaConsumer.class); + + private CountDownLatch latch = new CountDownLatch(1); + private String payload = null; + + @KafkaListener(topics = "${test.topic}") + public void receive(ConsumerRecord consumerRecord) { + LOGGER.info("received payload='{}'", consumerRecord.toString()); + setPayload(consumerRecord.toString()); + latch.countDown(); + } + + public CountDownLatch getLatch() { + return latch; + } + + public String getPayload() { + return payload; + } + + private void setPayload(String payload) { + this.payload = payload; + } + +} diff --git a/spring-kafka/src/main/java/com/baeldung/kafka/embedded/KafkaProducer.java b/spring-kafka/src/main/java/com/baeldung/kafka/embedded/KafkaProducer.java new file mode 100644 index 0000000000..d7cbd35011 --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/kafka/embedded/KafkaProducer.java @@ -0,0 +1,22 @@ +package com.baeldung.kafka.embedded; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.stereotype.Component; + +@Component +public class KafkaProducer { + + private static final Logger LOGGER = LoggerFactory.getLogger(KafkaProducer.class); + + @Autowired + private KafkaTemplate kafkaTemplate; + + public void send(String topic, String payload) { + LOGGER.info("sending payload='{}' to topic='{}'", payload, topic); + kafkaTemplate.send(topic, payload); + } + +} diff --git a/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/logging/RestTemplateConfigurationApplication.java b/spring-kafka/src/main/java/com/baeldung/kafka/embedded/KafkaProducerConsumerApplication.java similarity index 62% rename from spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/logging/RestTemplateConfigurationApplication.java rename to spring-kafka/src/main/java/com/baeldung/kafka/embedded/KafkaProducerConsumerApplication.java index 4fa14edda1..bf14251d75 100644 --- a/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/logging/RestTemplateConfigurationApplication.java +++ b/spring-kafka/src/main/java/com/baeldung/kafka/embedded/KafkaProducerConsumerApplication.java @@ -1,4 +1,4 @@ -package com.baeldung.resttemplate.logging; +package com.baeldung.kafka.embedded; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; @@ -6,9 +6,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @EnableAutoConfiguration -public class RestTemplateConfigurationApplication { +public class KafkaProducerConsumerApplication { public static void main(String[] args) { - SpringApplication.run(RestTemplateConfigurationApplication.class, args); + SpringApplication.run(KafkaProducerConsumerApplication.class, args); } + } diff --git a/spring-kafka/src/test/java/com/baeldung/kafka/embedded/EmbeddedKafkaIntegrationTest.java b/spring-kafka/src/test/java/com/baeldung/kafka/embedded/EmbeddedKafkaIntegrationTest.java new file mode 100644 index 0000000000..4c727795c4 --- /dev/null +++ b/spring-kafka/src/test/java/com/baeldung/kafka/embedded/EmbeddedKafkaIntegrationTest.java @@ -0,0 +1,52 @@ +package com.baeldung.kafka.embedded; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.util.concurrent.TimeUnit; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.test.context.EmbeddedKafka; +import org.springframework.test.annotation.DirtiesContext; + +@SpringBootTest +@DirtiesContext +@EmbeddedKafka(partitions = 1, brokerProperties = { "listeners=PLAINTEXT://localhost:9092", "port=9092" }) +class EmbeddedKafkaIntegrationTest { + + @Autowired + public KafkaTemplate template; + + @Autowired + private KafkaConsumer consumer; + + @Autowired + private KafkaProducer producer; + + @Value("${test.topic}") + private String topic; + + @Test + public void givenEmbeddedKafkaBroker_whenSendingtoDefaultTemplate_thenMessageReceived() throws Exception { + template.send(topic, "Sending with default template"); + consumer.getLatch().await(10000, TimeUnit.MILLISECONDS); + assertThat(consumer.getLatch().getCount(), equalTo(0L)); + + assertThat(consumer.getPayload(), containsString("embedded-test-topic")); + } + + @Test + public void givenEmbeddedKafkaBroker_whenSendingtoSimpleProducer_thenMessageReceived() throws Exception { + producer.send(topic, "Sending with our own simple KafkaProducer"); + consumer.getLatch().await(10000, TimeUnit.MILLISECONDS); + + assertThat(consumer.getLatch().getCount(), equalTo(0L)); + assertThat(consumer.getPayload(), containsString("embedded-test-topic")); + } + +} diff --git a/spring-kafka/src/test/java/com/baeldung/kafka/testcontainers/KafkaTestContainersLiveTest.java b/spring-kafka/src/test/java/com/baeldung/kafka/testcontainers/KafkaTestContainersLiveTest.java new file mode 100644 index 0000000000..74d6f824b1 --- /dev/null +++ b/spring-kafka/src/test/java/com/baeldung/kafka/testcontainers/KafkaTestContainersLiveTest.java @@ -0,0 +1,127 @@ +package com.baeldung.kafka.testcontainers; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.apache.kafka.common.serialization.StringSerializer; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaProducerFactory; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.core.ProducerFactory; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.junit4.SpringRunner; +import org.testcontainers.containers.KafkaContainer; +import org.testcontainers.utility.DockerImageName; + +import com.baeldung.kafka.embedded.KafkaConsumer; +import com.baeldung.kafka.embedded.KafkaProducer; +import com.baeldung.kafka.embedded.KafkaProducerConsumerApplication; + +/** + * This test class uses Testcontainers to instantiate and manage an external Apache + * Kafka broker hosted inside a Docker container. + * + * Therefore, one of the prerequisites for using Testcontainers is that Docker is installed on the host running this test + * + */ +@RunWith(SpringRunner.class) +@Import(com.baeldung.kafka.testcontainers.KafkaTestContainersLiveTest.KafkaTestContainersConfiguration.class) +@SpringBootTest(classes = KafkaProducerConsumerApplication.class) +@DirtiesContext +public class KafkaTestContainersLiveTest { + + @ClassRule + public static KafkaContainer kafka = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:5.4.3")); + + @Autowired + public KafkaTemplate template; + + @Autowired + private KafkaConsumer consumer; + + @Autowired + private KafkaProducer producer; + + @Value("${test.topic}") + private String topic; + + @Test + public void givenKafkaDockerContainer_whenSendingtoDefaultTemplate_thenMessageReceived() throws Exception { + template.send(topic, "Sending with default template"); + consumer.getLatch().await(10000, TimeUnit.MILLISECONDS); + + assertThat(consumer.getLatch().getCount(), equalTo(0L)); + assertThat(consumer.getPayload(), containsString("embedded-test-topic")); + } + + @Test + public void givenKafkaDockerContainer_whenSendingtoSimpleProducer_thenMessageReceived() throws Exception { + producer.send(topic, "Sending with own controller"); + consumer.getLatch().await(10000, TimeUnit.MILLISECONDS); + + assertThat(consumer.getLatch().getCount(), equalTo(0L)); + assertThat(consumer.getPayload(), containsString("embedded-test-topic")); + } + + @TestConfiguration + static class KafkaTestContainersConfiguration { + + @Bean + ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory() { + ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); + factory.setConsumerFactory(consumerFactory()); + return factory; + } + + @Bean + public ConsumerFactory consumerFactory() { + return new DefaultKafkaConsumerFactory<>(consumerConfigs()); + } + + @Bean + public Map consumerConfigs() { + Map props = new HashMap<>(); + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, kafka.getBootstrapServers()); + props.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest"); + props.put(ConsumerConfig.GROUP_ID_CONFIG, "baeldung"); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + return props; + } + + @Bean + public ProducerFactory producerFactory() { + Map configProps = new HashMap<>(); + configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, kafka.getBootstrapServers()); + configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + return new DefaultKafkaProducerFactory<>(configProps); + } + + @Bean + public KafkaTemplate kafkaTemplate() { + return new KafkaTemplate<>(producerFactory()); + } + + } + +} diff --git a/spring-kafka/src/test/resources/application.yml b/spring-kafka/src/test/resources/application.yml new file mode 100644 index 0000000000..7d7997c6fd --- /dev/null +++ b/spring-kafka/src/test/resources/application.yml @@ -0,0 +1,7 @@ +spring: + kafka: + consumer: + auto-offset-reset: earliest + group-id: baeldung +test: + topic: embedded-test-topic \ No newline at end of file diff --git a/spring-5-security-oauth/src/main/resources/logback.xml b/spring-kafka/src/test/resources/logback.xml similarity index 100% rename from spring-5-security-oauth/src/main/resources/logback.xml rename to spring-kafka/src/test/resources/logback.xml 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 deleted file mode 100644 index 4bd692f609..0000000000 --- a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/EmailConfiguration.java +++ /dev/null @@ -1,89 +0,0 @@ -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.spring5.SpringTemplateEngine; -import org.thymeleaf.spring5.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-3/src/main/java/com/baeldung/exclude_urls_filter/filter/HeaderValidatorFilter.java b/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/HeaderValidatorFilter.java deleted file mode 100644 index 2af90badae..0000000000 --- a/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/HeaderValidatorFilter.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.exclude_urls_filter.filter; - -import org.springframework.core.annotation.Order; -import org.springframework.http.HttpStatus; -import org.springframework.web.filter.OncePerRequestFilter; - -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; - -@Order(1) -public class HeaderValidatorFilter extends OncePerRequestFilter { - @Override - protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) - throws ServletException, IOException { - String path = request.getRequestURI(); - if ("/health".equals(path)) { - filterChain.doFilter(request, response); - return; - } - String countryCode = request.getHeader("X-Country-Code"); - if (!"US".equals(countryCode)) { - response.sendError(HttpStatus.BAD_REQUEST.value(), "Invalid Locale"); - return; - } - - filterChain.doFilter(request, response); - } -} \ No newline at end of file diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/datetime/DateTimeConfig.java b/spring-mvc-java-2/src/main/java/com/baeldung/datetime/DateTimeConfig.java deleted file mode 100644 index 8a5d1c71af..0000000000 --- a/spring-mvc-java-2/src/main/java/com/baeldung/datetime/DateTimeConfig.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.baeldung.datetime; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar; -import org.springframework.format.number.NumberFormatAnnotationFormatterFactory; -import org.springframework.format.support.DefaultFormattingConversionService; -import org.springframework.format.support.FormattingConversionService; - -import java.time.format.DateTimeFormatter; - -@Configuration -class DateTimeConfig { - - @Bean - public FormattingConversionService conversionService() { - DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false); - - conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory()); - - DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar(); - registrar.setDateFormatter(DateTimeFormatter.ofPattern("dd.MM.yyyy")); - registrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss")); - registrar.registerFormatters(conversionService); - - return conversionService; - } - -} \ No newline at end of file diff --git a/spring-mvc-kotlin/.gitignore b/spring-mvc-kotlin/.gitignore deleted file mode 100644 index 416395ffea..0000000000 --- a/spring-mvc-kotlin/.gitignore +++ /dev/null @@ -1 +0,0 @@ -transaction.log \ No newline at end of file diff --git a/spring-mvc-kotlin/README.md b/spring-mvc-kotlin/README.md deleted file mode 100644 index 590c627cb6..0000000000 --- a/spring-mvc-kotlin/README.md +++ /dev/null @@ -1,9 +0,0 @@ -## Spring MVC with Kotlin - -This module contains articles about Spring MVC with Kotlin - -### Relevant articles -- [Spring MVC Setup with Kotlin](https://www.baeldung.com/spring-mvc-kotlin) -- [Working with Kotlin and JPA](https://www.baeldung.com/kotlin-jpa) -- [Kotlin-allopen and Spring](https://www.baeldung.com/kotlin-allopen-spring) -- [MockMvc Kotlin DSL](https://www.baeldung.com/mockmvc-kotlin-dsl) diff --git a/spring-mvc-kotlin/pom.xml b/spring-mvc-kotlin/pom.xml deleted file mode 100644 index 30d2c32ecf..0000000000 --- a/spring-mvc-kotlin/pom.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - 4.0.0 - spring-mvc-kotlin - spring-mvc-kotlin - war - - - com.baeldung - parent-kotlin - 1.0.0-SNAPSHOT - ../parent-kotlin - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-json - - - org.thymeleaf - thymeleaf - - - org.thymeleaf - thymeleaf-spring4 - ${thymeleaf.version} - - - org.hibernate - hibernate-core - - - org.hibernate - hibernate-testing - test - - - com.h2database - h2 - test - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - kotlin-maven-plugin - org.jetbrains.kotlin - ${kotlin.version} - - - spring - jpa - - - - - org.jetbrains.kotlin - kotlin-maven-noarg - ${kotlin.version} - - - - - - - - 3.0.7.RELEASE - - - \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/allopen/SimpleConfiguration.kt b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/allopen/SimpleConfiguration.kt deleted file mode 100644 index 5d0a3e13bf..0000000000 --- a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/allopen/SimpleConfiguration.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.baeldung.kotlin.allopen - -import org.springframework.context.annotation.Configuration - -@Configuration -class SimpleConfiguration { -} \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/jpa/Person.kt b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/jpa/Person.kt deleted file mode 100644 index 2b2a2bd6d9..0000000000 --- a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/jpa/Person.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.kotlin.jpa - -import javax.persistence.CascadeType -import javax.persistence.Column -import javax.persistence.Entity -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id -import javax.persistence.OneToMany - -@Entity -data class Person @JvmOverloads constructor( - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - val id: Int, - @Column(nullable = false) - val name: String, - @Column(nullable = true) - val email: String? = null, - @OneToMany(cascade = [CascadeType.ALL]) - val phoneNumbers: List? = null) diff --git a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/jpa/PhoneNumber.kt b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/jpa/PhoneNumber.kt deleted file mode 100644 index 734e8b4cc4..0000000000 --- a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/jpa/PhoneNumber.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.kotlin.jpa - -import javax.persistence.Column -import javax.persistence.Entity -import javax.persistence.GeneratedValue -import javax.persistence.GenerationType -import javax.persistence.Id - -@Entity -data class PhoneNumber( - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - val id: Int, - @Column(nullable = false) - val number: String) \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mockmvc/MockMvcController.kt b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mockmvc/MockMvcController.kt deleted file mode 100644 index 68ab5f31a6..0000000000 --- a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mockmvc/MockMvcController.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.baeldung.kotlin.mockmvc - -import org.springframework.http.MediaType -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 - -@RestController -@RequestMapping("/mockmvc") -class MockMvcController { - - @RequestMapping(value = ["/validate"], method = [RequestMethod.POST], produces = [MediaType.APPLICATION_JSON_VALUE]) - fun validate(@RequestBody request: Request): Response { - val error = if (request.name.first == "admin") { - null - } else { - ERROR - } - return Response(error) - } - - companion object { - const val ERROR = "invalid user" - } -} \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mockmvc/MockMvcModel.kt b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mockmvc/MockMvcModel.kt deleted file mode 100644 index 3231b6f186..0000000000 --- a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mockmvc/MockMvcModel.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.baeldung.kotlin.mockmvc - -import com.fasterxml.jackson.annotation.JsonInclude - -data class Name(val first: String, val last: String) - -data class Request(val name: Name) - -@JsonInclude(JsonInclude.Include.NON_NULL) -data class Response(val error: String?) \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebConfig.kt b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebConfig.kt deleted file mode 100644 index 23aadf282a..0000000000 --- a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebConfig.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.baeldung.kotlin.mvc - -import org.springframework.context.ApplicationContext -import org.springframework.context.ApplicationContextAware -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.web.servlet.config.annotation.EnableWebMvc -import org.springframework.web.servlet.config.annotation.ViewControllerRegistry -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter -import org.thymeleaf.spring4.SpringTemplateEngine -import org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver -import org.thymeleaf.spring4.view.ThymeleafViewResolver -import org.thymeleaf.templatemode.TemplateMode - -@EnableWebMvc -@Configuration -open class ApplicationWebConfig : WebMvcConfigurerAdapter(), ApplicationContextAware { - - private var applicationContext: ApplicationContext? = null - - override fun setApplicationContext(applicationContext: ApplicationContext?) { - this.applicationContext = applicationContext - } - - override fun addViewControllers(registry: ViewControllerRegistry?) { - super.addViewControllers(registry) - - registry!!.addViewController("/welcome.html") - } - - @Bean - open fun templateResolver(): SpringResourceTemplateResolver { - return SpringResourceTemplateResolver() - .apply { prefix = "/WEB-INF/view/" } - .apply { suffix = ".html"} - .apply { templateMode = TemplateMode.HTML } - .apply { setApplicationContext(applicationContext) } - } - - @Bean - open fun templateEngine(): SpringTemplateEngine { - return SpringTemplateEngine() - .apply { setTemplateResolver(templateResolver()) } - } - - @Bean - open fun viewResolver(): ThymeleafViewResolver { - return ThymeleafViewResolver() - .apply { templateEngine = templateEngine() } - .apply { order = 1 } - } -} \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebInitializer.kt b/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebInitializer.kt deleted file mode 100644 index 4c1a35823c..0000000000 --- a/spring-mvc-kotlin/src/main/kotlin/com/baeldung/kotlin/mvc/ApplicationWebInitializer.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.baeldung.kotlin.mvc - -import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer - -class ApplicationWebInitializer : AbstractAnnotationConfigDispatcherServletInitializer() { - - override fun getRootConfigClasses(): Array>? { - return null - } - - override fun getServletMappings(): Array { - return arrayOf("/") - } - - override fun getServletConfigClasses(): Array> { - return arrayOf(ApplicationWebConfig::class.java) - } -} \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/webapp/WEB-INF/spring-web-config.xml b/spring-mvc-kotlin/src/main/webapp/WEB-INF/spring-web-config.xml deleted file mode 100644 index c7f110ea94..0000000000 --- a/spring-mvc-kotlin/src/main/webapp/WEB-INF/spring-web-config.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/webapp/WEB-INF/view/welcome.jsp b/spring-mvc-kotlin/src/main/webapp/WEB-INF/view/welcome.jsp deleted file mode 100644 index 3f68f128bc..0000000000 --- a/spring-mvc-kotlin/src/main/webapp/WEB-INF/view/welcome.jsp +++ /dev/null @@ -1,7 +0,0 @@ - - Welcome - - -

This is the body of the welcome view

- - \ No newline at end of file diff --git a/spring-mvc-kotlin/src/main/webapp/WEB-INF/web.xml b/spring-mvc-kotlin/src/main/webapp/WEB-INF/web.xml deleted file mode 100755 index cbee6a1b11..0000000000 --- a/spring-mvc-kotlin/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - Spring Kotlin MVC Application - - - spring-web-mvc - org.springframework.web.servlet.DispatcherServlet - 1 - - contextConfigLocation - /WEB-INF/spring-web-config.xml - - - - - spring-web-mvc - / - - - \ No newline at end of file diff --git a/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/allopen/SimpleConfigurationTest.kt b/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/allopen/SimpleConfigurationTest.kt deleted file mode 100644 index 65a60c7157..0000000000 --- a/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/allopen/SimpleConfigurationTest.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung.kotlin.allopen - -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.support.AnnotationConfigContextLoader - -@RunWith(SpringJUnit4ClassRunner::class) -@ContextConfiguration( - loader = AnnotationConfigContextLoader::class, - classes = arrayOf(SimpleConfiguration::class)) -class SimpleConfigurationTest { - - @Test - fun contextLoads() { - } - -} \ No newline at end of file diff --git a/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/jpa/HibernateKotlinIntegrationTest.kt b/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/jpa/HibernateKotlinIntegrationTest.kt deleted file mode 100644 index adac9d0cbf..0000000000 --- a/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/jpa/HibernateKotlinIntegrationTest.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.baeldung.kotlin.jpa - -import org.hibernate.cfg.Configuration -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase -import org.hibernate.testing.transaction.TransactionUtil.doInHibernate -import org.junit.Assert.assertTrue -import org.junit.Test -import java.io.IOException -import java.util.* - - -class HibernateKotlinIntegrationTest : BaseCoreFunctionalTestCase() { - - private val properties: Properties - @Throws(IOException::class) - get() { - val properties = Properties() - properties.load(javaClass.classLoader.getResourceAsStream("hibernate.properties")) - return properties - } - - override fun getAnnotatedClasses(): Array> { - return arrayOf(Person::class.java, PhoneNumber::class.java) - } - - override fun configure(configuration: Configuration) { - super.configure(configuration) - configuration.properties = properties - } - - @Test - fun givenPersonWithFullData_whenSaved_thenFound() { - doInHibernate(({ this.sessionFactory() }), { session -> - val personToSave = Person(0, "John", "jhon@test.com", Arrays.asList(PhoneNumber(0, "202-555-0171"), PhoneNumber(0, "202-555-0102"))) - session.persist(personToSave) - val personFound = session.find(Person::class.java, personToSave.id) - session.refresh(personFound) - - assertTrue(personToSave == personFound) - }) - } - - @Test - fun givenPerson_whenSaved_thenFound() { - doInHibernate(({ this.sessionFactory() }), { session -> - val personToSave = Person(0, "John") - session.persist(personToSave) - val personFound = session.find(Person::class.java, personToSave.id) - session.refresh(personFound) - - assertTrue(personToSave == personFound) - }) - } - - @Test - fun givenPersonWithNullFields_whenSaved_thenFound() { - doInHibernate(({ this.sessionFactory() }), { session -> - val personToSave = Person(0, "John", null, null) - session.persist(personToSave) - val personFound = session.find(Person::class.java, personToSave.id) - session.refresh(personFound) - - assertTrue(personToSave == personFound) - }) - } -} \ No newline at end of file diff --git a/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/mockmvc/MockMvcControllerTest.kt b/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/mockmvc/MockMvcControllerTest.kt deleted file mode 100644 index 802cd4c1e7..0000000000 --- a/spring-mvc-kotlin/src/test/kotlin/com/baeldung/kotlin/mockmvc/MockMvcControllerTest.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.baeldung.kotlin.mockmvc - -import com.fasterxml.jackson.databind.ObjectMapper -import org.junit.Test -import org.junit.runner.RunWith -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest -import org.springframework.http.MediaType -import org.springframework.http.ResponseEntity.status -import org.springframework.test.context.junit4.SpringRunner -import org.springframework.test.web.servlet.MockMvc -import org.springframework.test.web.servlet.post -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders -import org.springframework.test.web.servlet.result.MockMvcResultHandlers -import org.springframework.test.web.servlet.result.MockMvcResultMatchers - -@RunWith(SpringRunner::class) -@WebMvcTest -class MockMvcControllerTest { - - @Autowired lateinit var mockMvc: MockMvc - @Autowired lateinit var mapper: ObjectMapper - - @Test - fun `when supported user is given then raw MockMvc-based validation is successful`() { - mockMvc.perform(MockMvcRequestBuilders - .post("/mockmvc/validate") - .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(mapper.writeValueAsString(Request(Name("admin", ""))))) - .andExpect(MockMvcResultMatchers.status().isOk) - .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.content().string("{}")) - } - - @Test - fun `when supported user is given then kotlin DSL-based validation is successful`() { - doTest(Request(Name("admin", "")), Response(null)) - } - - @Test - fun `when unsupported user is given then validation is failed`() { - doTest(Request(Name("some-name", "some-surname")), Response(MockMvcController.ERROR)) - } - - private fun doTest(input: Request, expectation: Response) { - mockMvc.post("/mockmvc/validate") { - contentType = MediaType.APPLICATION_JSON - content = mapper.writeValueAsString(input) - accept = MediaType.APPLICATION_JSON - }.andExpect { - status { isOk } - content { contentType(MediaType.APPLICATION_JSON) } - content { json(mapper.writeValueAsString(expectation)) } - } - } -} - -@SpringBootApplication -class MockMvcApplication \ No newline at end of file diff --git a/spring-mvc-kotlin/src/test/resources/hibernate.properties b/spring-mvc-kotlin/src/test/resources/hibernate.properties deleted file mode 100644 index 7b8764637b..0000000000 --- a/spring-mvc-kotlin/src/test/resources/hibernate.properties +++ /dev/null @@ -1,9 +0,0 @@ -hibernate.connection.driver_class=org.h2.Driver -hibernate.connection.url=jdbc:h2:mem:mydb1;DB_CLOSE_DELAY=-1 -hibernate.connection.username=sa -hibernate.connection.autocommit=true -jdbc.password= - -hibernate.dialect=org.hibernate.dialect.H2Dialect -hibernate.show_sql=true -hibernate.hbm2ddl.auto=create-drop \ No newline at end of file diff --git a/spring-mvc-xml/src/main/resources/messages.properties b/spring-mvc-xml/src/main/resources/messages.properties deleted file mode 100644 index 2a3cccf76c..0000000000 --- a/spring-mvc-xml/src/main/resources/messages.properties +++ /dev/null @@ -1,2 +0,0 @@ -required.name = Name is required! -NotEmpty.person.password = Password is required! \ No newline at end of file diff --git a/spring-reactive-kotlin/README.md b/spring-reactive-kotlin/README.md deleted file mode 100644 index d6ce3b7645..0000000000 --- a/spring-reactive-kotlin/README.md +++ /dev/null @@ -1,7 +0,0 @@ -## Spring Reactive Kotlin - -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) diff --git a/spring-reactive-kotlin/pom.xml b/spring-reactive-kotlin/pom.xml deleted file mode 100644 index cbb143f6ec..0000000000 --- a/spring-reactive-kotlin/pom.xml +++ /dev/null @@ -1,145 +0,0 @@ - - - 4.0.0 - spring-reactive-kotlin - spring-reactive-kotlin - Demo project for Spring Boot - - jar - - - com.baeldung - parent-kotlin - 1.0.0-SNAPSHOT - ../parent-kotlin - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-webflux - - - org.springframework.boot.experimental - spring-boot-starter-data-r2dbc - - - org.springframework.boot - spring-boot-starter-actuator - - - io.r2dbc - r2dbc-h2 - - - com.fasterxml.jackson.module - jackson-module-kotlin - - - - org.springframework.boot - spring-boot-starter-test - test - - - io.projectreactor - reactor-test - test - - - - org.springframework.boot.experimental - spring-boot-test-autoconfigure-r2dbc - test - - - io.projectreactor - reactor-test - test - - - - - - - - org.springframework.boot.experimental - spring-boot-bom-r2dbc - 0.1.0.M3 - pom - import - - - - - - src/main/kotlin - src/test/kotlin - - - kotlin-maven-plugin - - - compile - compile - - compile - - - - test-compile - test-compile - - test-compile - - - - org.jetbrains.kotlin - ${kotlin.version} - - - -Xjsr305=strict - - 1.8 - - spring - jpa - - - - - org.jetbrains.kotlin - kotlin-maven-allopen - ${kotlin.version} - - - org.jetbrains.kotlin - kotlin-maven-noarg - ${kotlin.version} - - - - - - - - 1.8 - 1.3.70 - 2.2.5.RELEASE - - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - - - - diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/HealthTrackerApplication.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/HealthTrackerApplication.kt deleted file mode 100644 index c70057b5de..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/HealthTrackerApplication.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.bootmicroservice - -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication - -@SpringBootApplication -class HealthTrackerApplication - -fun main(args: Array) { - runApplication(*args) -} diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/config/DBConfiguration.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/config/DBConfiguration.kt deleted file mode 100644 index b14682cc5c..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/config/DBConfiguration.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.baeldung.bootmicroservice.config; - -import org.springframework.context.annotation.Configuration -import org.springframework.data.r2dbc.core.DatabaseClient - -@Configuration -class DBConfiguration(db: DatabaseClient) { - init { - val initDb = db.execute { - """ CREATE TABLE IF NOT EXISTS profile ( - id SERIAL PRIMARY KEY, - first_name VARCHAR(20) NOT NULL, - last_name VARCHAR(20) NOT NULL, - birth_date DATE NOT NULL - ); - CREATE TABLE IF NOT EXISTS health_record( - id SERIAL PRIMARY KEY, - profile_id LONG NOT NULL, - temperature DECIMAL NOT NULL, - blood_pressure DECIMAL NOT NULL, - heart_rate DECIMAL, - date DATE NOT NULL - ); - """ - } - initDb.then().subscribe() - } -} diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/controller/HealthRecordController.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/controller/HealthRecordController.kt deleted file mode 100644 index 620f187b7b..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/controller/HealthRecordController.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.baeldung.bootmicroservice.controller - -import com.baeldung.bootmicroservice.model.AverageHealthStatus -import com.baeldung.bootmicroservice.model.HealthRecord -import com.baeldung.bootmicroservice.repository.HealthRecordRepository -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.RestController -import reactor.core.publisher.Mono - -@RestController -class HealthRecordController(val repository: HealthRecordRepository) { - - @PostMapping("/health/{profileId}/record") - fun storeHealthRecord(@PathVariable("profileId") profileId: Long, @RequestBody record: HealthRecord): Mono = - repository.save(HealthRecord(null - , profileId - , record.temperature - , record.bloodPressure - , record.heartRate - , record.date)) - - @GetMapping("/health/{profileId}/avg") - fun fetchHealthRecordAverage(@PathVariable("profileId") profileId: Long): Mono = - repository.findByProfileId(profileId) - .reduce( - AverageHealthStatus(0, 0.0, 0.0, 0.0) - , { s, r -> - AverageHealthStatus(s.cnt + 1 - , s.temperature + r.temperature - , s.bloodPressure + r.bloodPressure - , s.heartRate + r.heartRate - ) - } - ).map { s -> - AverageHealthStatus(s.cnt - , if (s.cnt != 0) s.temperature / s.cnt else 0.0 - , if (s.cnt != 0) s.bloodPressure / s.cnt else 0.0 - , if (s.cnt != 0) s.heartRate / s.cnt else 0.0) - } - -} \ No newline at end of file diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/controller/ProfileController.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/controller/ProfileController.kt deleted file mode 100644 index 1dc3bcdc50..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/controller/ProfileController.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.bootmicroservice.controller - -import com.baeldung.bootmicroservice.model.Profile -import com.baeldung.bootmicroservice.repository.ProfileRepository -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RestController -import reactor.core.publisher.Mono - -@RestController -class ProfileController(val repository: ProfileRepository) { - - @PostMapping("/profile") - fun save(@RequestBody profile: Profile): Mono = repository.save(profile) -} \ No newline at end of file diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/model/AverageHealthStatus.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/model/AverageHealthStatus.kt deleted file mode 100644 index 3141146b9c..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/model/AverageHealthStatus.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.baeldung.bootmicroservice.model; - -class AverageHealthStatus(var cnt: Int, var temperature: Double, var bloodPressure: Double, var heartRate: Double) diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/model/HealthRecord.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/model/HealthRecord.kt deleted file mode 100644 index 71c534027f..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/model/HealthRecord.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.bootmicroservice.model - -import org.springframework.data.annotation.Id -import org.springframework.data.relational.core.mapping.Table -import java.time.LocalDate - -@Table -data class HealthRecord(@Id var id: Long?, var profileId: Long?, var temperature: Double, var bloodPressure: Double, var heartRate: Double, var date: LocalDate) \ No newline at end of file diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/model/Profile.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/model/Profile.kt deleted file mode 100644 index cbb7e675ea..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/model/Profile.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.bootmicroservice.model - -import org.springframework.data.annotation.Id -import org.springframework.data.relational.core.mapping.Table -import java.time.LocalDateTime - -@Table -data class Profile(@Id var id:Long?, var firstName : String, var lastName : String, var birthDate: LocalDateTime) \ No newline at end of file diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/repository/HealthRecordRepository.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/repository/HealthRecordRepository.kt deleted file mode 100644 index 8cc91f06e4..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/repository/HealthRecordRepository.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.baeldung.bootmicroservice.repository - -import com.baeldung.bootmicroservice.model.HealthRecord -import org.springframework.data.r2dbc.repository.Query -import org.springframework.data.repository.reactive.ReactiveCrudRepository -import org.springframework.stereotype.Repository -import reactor.core.publisher.Flux - -@Repository -interface HealthRecordRepository: ReactiveCrudRepository { - @Query("select p.* from health_record p where p.profile_id = :profileId ") - fun findByProfileId(profileId: Long): Flux -} \ No newline at end of file diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/repository/ProfileRepository.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/repository/ProfileRepository.kt deleted file mode 100644 index eee8c5fcbe..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/bootmicroservice/repository/ProfileRepository.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.baeldung.bootmicroservice.repository - -import com.baeldung.bootmicroservice.model.Profile -import org.springframework.data.repository.reactive.ReactiveCrudRepository -import org.springframework.stereotype.Repository - -@Repository -interface ProfileRepository: ReactiveCrudRepository \ No newline at end of file diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Application.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Application.kt deleted file mode 100644 index 87ac7417b7..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Application.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.springreactivekotlin - -import org.springframework.boot.SpringApplication -import org.springframework.boot.autoconfigure.SpringBootApplication - -@SpringBootApplication -class Application - -fun main(args: Array) { - SpringApplication.run(Application::class.java, *args) -} diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Controller.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Controller.kt deleted file mode 100644 index 76f8a62b85..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Controller.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.baeldung.springreactivekotlin - -import org.springframework.http.MediaType -import org.springframework.stereotype.Controller -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.ResponseBody -import reactor.core.publisher.Flux - -@Controller -class Controller { - - @GetMapping(path = ["/numbers"], produces = [MediaType.APPLICATION_STREAM_JSON_VALUE]) - @ResponseBody - fun getNumbers(): Flux { - return Flux.range(1, 100) - } - -} diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Device.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Device.kt deleted file mode 100644 index 9eb6eb8488..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Device.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.baeldung.springreactivekotlin - -class Device(val name: String, val reading: Double) { - -} diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/HomeSensorsHandler.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/HomeSensorsHandler.kt deleted file mode 100644 index 0ef9f37f1b..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/HomeSensorsHandler.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.baeldung.springreactivekotlin - -import org.springframework.stereotype.Component -import org.springframework.web.reactive.function.BodyInserters.fromObject -import org.springframework.web.reactive.function.server.ServerRequest -import org.springframework.web.reactive.function.server.ServerResponse -import reactor.core.publisher.Mono - -@Component -class HomeSensorsHandler { - - var data = mapOf("lamp" to arrayOf(0.7, 0.65, 0.67), "fridge" to arrayOf(12.0, 11.9, 12.5)) - - fun setLight(request: ServerRequest): Mono = ServerResponse.ok().build() - - fun getLightReading(request: ServerRequest): Mono = - ServerResponse.ok().body(fromObject(data["lamp"]!!)) - - fun getDeviceReadings(request: ServerRequest): Mono { - val id = request.pathVariable("id") - return ServerResponse.ok().body(fromObject(Device(id, 1.0))) - } - - fun getAllDevices(request: ServerRequest): Mono = - ServerResponse.ok().body(fromObject(arrayOf("lamp", "tv"))) - - fun getAllDeviceApi(request: ServerRequest): Mono = - ServerResponse.ok().body(fromObject(arrayListOf("kettle", "fridge"))) - - fun setDeviceReadingApi(request: ServerRequest): Mono { - return request.bodyToMono(Device::class.java).flatMap { it -> - ServerResponse.ok().body(fromObject(Device(it.name.toUpperCase(), it.reading))) - } - } - -} \ No newline at end of file diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/HomeSensorsRouters.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/HomeSensorsRouters.kt deleted file mode 100644 index 27d87afd89..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/HomeSensorsRouters.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.baeldung.springreactivekotlin - -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.http.MediaType.APPLICATION_JSON -import org.springframework.http.MediaType.TEXT_HTML -import org.springframework.web.reactive.function.server.router - -@Configuration -class HomeSensorsRouters(private val handler: HomeSensorsHandler) { - - @Bean - fun roomsRouter() = router { - (accept(TEXT_HTML) and "/room").nest { - GET("/light", handler::getLightReading) - POST("/light", handler::setLight) - } - } - - @Bean - fun deviceRouter() = router { - accept(TEXT_HTML).nest { - (GET("/device/") or GET("/devices/")).invoke(handler::getAllDevices) - GET("/device/{id}", handler::getDeviceReadings) - } - (accept(APPLICATION_JSON) and "/api").nest { - (GET("/device/") or GET("/devices/")).invoke(handler::getAllDeviceApi) - POST("/device/", handler::setDeviceReadingApi) - } - } - -} diff --git a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Routes.kt b/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Routes.kt deleted file mode 100644 index 9015fc5df8..0000000000 --- a/spring-reactive-kotlin/src/main/kotlin/com/baeldung/springreactivekotlin/Routes.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.baeldung.springreactivekotlin - -import org.springframework.context.annotation.Bean -import org.springframework.context.annotation.Configuration -import org.springframework.web.reactive.function.server.ServerResponse -import org.springframework.web.reactive.function.server.router - -import org.springframework.web.reactive.function.BodyInserters.fromObject - -@Configuration -class SimpleRoute { - @Bean - fun route() = router { - GET("/route") { _ -> ServerResponse.ok().body(fromObject(arrayOf(1, 2, 3))) } - } -} \ No newline at end of file diff --git a/spring-reactive-kotlin/src/main/resources/application.yml b/spring-reactive-kotlin/src/main/resources/application.yml deleted file mode 100644 index d75683f905..0000000000 --- a/spring-reactive-kotlin/src/main/resources/application.yml +++ /dev/null @@ -1 +0,0 @@ -management.endpoints.web.exposure.include: health,metrics \ No newline at end of file diff --git a/spring-reactive-kotlin/src/test/kotlin/RoutesTest.kt b/spring-reactive-kotlin/src/test/kotlin/RoutesTest.kt deleted file mode 100644 index ba640070e3..0000000000 --- a/spring-reactive-kotlin/src/test/kotlin/RoutesTest.kt +++ /dev/null @@ -1,35 +0,0 @@ -package veontomo - -import com.baeldung.springreactivekotlin.SimpleRoute -import org.junit.Before -import org.junit.Test -import org.springframework.test.web.reactive.server.WebTestClient - -class RoutesTest { - - lateinit var client: WebTestClient - - @Before - fun init() { - this.client = WebTestClient.bindToRouterFunction(SimpleRoute().route()).build() - } - - - @Test - fun whenRequestToRoute_thenStatusShouldBeOk() { - client.get() - .uri("/route") - .exchange() - .expectStatus().isOk - } - - - @Test - fun whenRequestToRoute_thenBodyShouldContainArray123() { - client.get() - .uri("/route") - .exchange() - .expectBody() - .json("[1, 2, 3]") - } -} \ No newline at end of file diff --git a/spring-reactive-kotlin/src/test/kotlin/com/baeldung/bootmicroservice/controller/ProfileControllerTest.kt b/spring-reactive-kotlin/src/test/kotlin/com/baeldung/bootmicroservice/controller/ProfileControllerTest.kt deleted file mode 100644 index 51481af3d7..0000000000 --- a/spring-reactive-kotlin/src/test/kotlin/com/baeldung/bootmicroservice/controller/ProfileControllerTest.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.baeldung.bootmicroservice.controller; - -import com.baeldung.bootmicroservice.model.Profile -import com.fasterxml.jackson.databind.ObjectMapper -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.http.MediaType -import org.springframework.test.web.reactive.server.WebTestClient -import java.time.LocalDateTime - -@SpringBootTest -class ProfileControllerTest { - @Autowired - lateinit var controller: ProfileController - - @Autowired - lateinit var mapper: ObjectMapper ; - - lateinit var client: WebTestClient - lateinit var profile: String - - @BeforeEach - fun setup() { - client = WebTestClient.bindToController(controller).build() - profile = mapper.writeValueAsString(Profile(null, "kotlin", "reactive", LocalDateTime.now())) - } - - @Test - fun whenRequestProfile_thenStatusShouldBeOk() { - client.post() - .uri("/profile") - .contentType(MediaType.APPLICATION_JSON) - .bodyValue(profile) - .exchange() - .expectStatus().isOk - } - - @Test - fun whenRequestProfile_thenIdShouldBeNotNull() { - client.post() - .uri("/profile") - .contentType(MediaType.APPLICATION_JSON) - .bodyValue(profile) - .exchange() - .expectBody() - .jsonPath("$.id") - .isNotEmpty - } -} diff --git a/spring-rest-compress/README.md b/spring-rest-compress/README.md deleted file mode 100644 index ce627d8595..0000000000 --- a/spring-rest-compress/README.md +++ /dev/null @@ -1,6 +0,0 @@ -## Spring REST Compress - -This module contains articles about request compression with Spring - -### Relevant Articles: -- [How to compress requests using the Spring RestTemplate](https://www.baeldung.com/spring-resttemplate-compressing-requests) diff --git a/spring-rest-compress/pom.xml b/spring-rest-compress/pom.xml deleted file mode 100644 index 9ff0be9682..0000000000 --- a/spring-rest-compress/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - 4.0.0 - spring-rest-compress - 0.0.1-SNAPSHOT - spring-rest-compress - - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../parent-boot-2 - - - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.boot - spring-boot-starter-tomcat - - - - - - org.springframework.boot - spring-boot-starter-jetty - - - - org.apache.httpcomponents - httpclient - - - - commons-io - commons-io - ${commons-io.version} - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - - 1.8 - 2.6 - - - diff --git a/spring-security-modules/pom.xml b/spring-security-modules/pom.xml index d5c0c0dd6e..99dea4bc67 100644 --- a/spring-security-modules/pom.xml +++ b/spring-security-modules/pom.xml @@ -14,6 +14,10 @@ + spring-ldap + spring-5-security + spring-5-security-cognito + spring-5-security-oauth spring-security-acl spring-security-auth0 spring-security-web-angular/server @@ -28,6 +32,7 @@ spring-security-web-login spring-security-web-persisted-remember-me spring-security-web-sockets + spring-security-legacy-oidc spring-security-oidc spring-security-okta spring-security-web-react @@ -37,7 +42,8 @@ spring-security-oauth2-sso spring-security-web-thymeleaf spring-security-web-x509 - spring-security-kotlin-dsl + spring-session + spring-social-login
diff --git a/spring-5-security-cognito/README.md b/spring-security-modules/spring-5-security-cognito/README.md similarity index 100% rename from spring-5-security-cognito/README.md rename to spring-security-modules/spring-5-security-cognito/README.md diff --git a/spring-5-security-cognito/pom.xml b/spring-security-modules/spring-5-security-cognito/pom.xml similarity index 97% rename from spring-5-security-cognito/pom.xml rename to spring-security-modules/spring-5-security-cognito/pom.xml index 5f8f328086..877dbd52fa 100644 --- a/spring-5-security-cognito/pom.xml +++ b/spring-security-modules/spring-5-security-cognito/pom.xml @@ -12,7 +12,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 diff --git a/spring-5-security-cognito/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java b/spring-security-modules/spring-5-security-cognito/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java similarity index 100% rename from spring-5-security-cognito/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java rename to spring-security-modules/spring-5-security-cognito/src/main/java/com/baeldung/cognito/CognitoWebConfiguration.java diff --git a/spring-5-security-cognito/src/main/java/com/baeldung/cognito/SecurityConfiguration.java b/spring-security-modules/spring-5-security-cognito/src/main/java/com/baeldung/cognito/SecurityConfiguration.java similarity index 100% rename from spring-5-security-cognito/src/main/java/com/baeldung/cognito/SecurityConfiguration.java rename to spring-security-modules/spring-5-security-cognito/src/main/java/com/baeldung/cognito/SecurityConfiguration.java diff --git a/spring-5-security-cognito/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java b/spring-security-modules/spring-5-security-cognito/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java similarity index 100% rename from spring-5-security-cognito/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java rename to spring-security-modules/spring-5-security-cognito/src/main/java/com/baeldung/cognito/SpringCognitoApplication.java diff --git a/spring-5-security-cognito/src/main/resources/application.yml b/spring-security-modules/spring-5-security-cognito/src/main/resources/application.yml similarity index 100% rename from spring-5-security-cognito/src/main/resources/application.yml rename to spring-security-modules/spring-5-security-cognito/src/main/resources/application.yml diff --git a/spring-5-security/src/main/resources/logback.xml b/spring-security-modules/spring-5-security-cognito/src/main/resources/logback.xml similarity index 100% rename from spring-5-security/src/main/resources/logback.xml rename to spring-security-modules/spring-5-security-cognito/src/main/resources/logback.xml diff --git a/spring-5-security-cognito/src/main/resources/templates/home.html b/spring-security-modules/spring-5-security-cognito/src/main/resources/templates/home.html similarity index 100% rename from spring-5-security-cognito/src/main/resources/templates/home.html rename to spring-security-modules/spring-5-security-cognito/src/main/resources/templates/home.html diff --git a/spring-5-security-oauth/README.md b/spring-security-modules/spring-5-security-oauth/README.md similarity index 100% rename from spring-5-security-oauth/README.md rename to spring-security-modules/spring-5-security-oauth/README.md diff --git a/spring-5-security-oauth/pom.xml b/spring-security-modules/spring-5-security-oauth/pom.xml similarity index 98% rename from spring-5-security-oauth/pom.xml rename to spring-security-modules/spring-5-security-oauth/pom.xml index 19aaa576c8..d31cf293a3 100644 --- a/spring-5-security-oauth/pom.xml +++ b/spring-security-modules/spring-5-security-oauth/pom.xml @@ -12,7 +12,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/jersey/JerseyApplication.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/jersey/JerseyApplication.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/jersey/JerseyApplication.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/jersey/JerseyApplication.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/jersey/JerseyResource.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/jersey/JerseyResource.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/jersey/JerseyResource.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/jersey/JerseyResource.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/jersey/RestConfig.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/jersey/RestConfig.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/jersey/RestConfig.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/jersey/RestConfig.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/jersey/SecurityConfig.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/jersey/SecurityConfig.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/jersey/SecurityConfig.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/jersey/SecurityConfig.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/CustomRequestSecurityConfig.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/CustomRequestSecurityConfig.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2/CustomRequestSecurityConfig.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/CustomRequestSecurityConfig.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/LoginController.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/LoginController.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2/LoginController.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/LoginController.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/MvcConfig.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/MvcConfig.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2/MvcConfig.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/MvcConfig.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SecurityConfig.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SecurityConfig.java similarity index 92% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SecurityConfig.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SecurityConfig.java index e17e339142..c9164e2215 100644 --- a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SecurityConfig.java +++ b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SecurityConfig.java @@ -12,6 +12,8 @@ import org.springframework.core.env.Environment; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.oauth2.client.CommonOAuth2Provider; +import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService; import org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient; import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient; import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; @@ -46,7 +48,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { .defaultSuccessUrl("/loginSuccess") .failureUrl("/loginFailure"); } - + @Bean public AuthorizationRequestRepository authorizationRequestRepository() { return new HttpSessionOAuth2AuthorizationRequestRepository(); @@ -58,11 +60,10 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { return accessTokenResponseClient; } - // additional configuration for non-Spring Boot projects private static List clients = Arrays.asList("google", "facebook"); - //@Bean +// @Bean public ClientRegistrationRepository clientRegistrationRepository() { List registrations = clients.stream() .map(c -> getRegistration(c)) @@ -72,6 +73,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { return new InMemoryClientRegistrationRepository(registrations); } +// @Bean + public OAuth2AuthorizedClientService authorizedClientService() { + return new InMemoryOAuth2AuthorizedClientService(clientRegistrationRepository()); + } + private static String CLIENT_PROPERTY_KEY = "spring.security.oauth2.client.registration."; @Autowired diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2/SpringOAuthApplication.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/ExtractorsApplication.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/configuration/SecurityConfig.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/configuration/SecurityConfig.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/configuration/SecurityConfig.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/configuration/SecurityConfig.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/custom/BaeldungAuthoritiesExtractor.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/custom/BaeldungAuthoritiesExtractor.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/custom/BaeldungAuthoritiesExtractor.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/custom/BaeldungAuthoritiesExtractor.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/custom/BaeldungPrincipalExtractor.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/custom/BaeldungPrincipalExtractor.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/custom/BaeldungPrincipalExtractor.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/custom/BaeldungPrincipalExtractor.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/github/GithubAuthoritiesExtractor.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/github/GithubAuthoritiesExtractor.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/github/GithubAuthoritiesExtractor.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/github/GithubAuthoritiesExtractor.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/github/GithubPrincipalExtractor.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/github/GithubPrincipalExtractor.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/github/GithubPrincipalExtractor.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2extractors/extractor/github/GithubPrincipalExtractor.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/CustomAuthorizationRequestResolver.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/CustomAuthorizationRequestResolver.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/CustomAuthorizationRequestResolver.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/CustomAuthorizationRequestResolver.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/CustomRequestEntityConverter.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/CustomRequestEntityConverter.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/CustomRequestEntityConverter.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/CustomRequestEntityConverter.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/CustomTokenResponseConverter.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/CustomTokenResponseConverter.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/CustomTokenResponseConverter.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/CustomTokenResponseConverter.java diff --git a/spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/LinkedinTokenResponseConverter.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/LinkedinTokenResponseConverter.java similarity index 100% rename from spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/LinkedinTokenResponseConverter.java rename to spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2request/LinkedinTokenResponseConverter.java diff --git a/spring-5-security-oauth/src/main/resources/application-oauth2-extractors-baeldung.properties b/spring-security-modules/spring-5-security-oauth/src/main/resources/application-oauth2-extractors-baeldung.properties similarity index 100% rename from spring-5-security-oauth/src/main/resources/application-oauth2-extractors-baeldung.properties rename to spring-security-modules/spring-5-security-oauth/src/main/resources/application-oauth2-extractors-baeldung.properties diff --git a/spring-5-security-oauth/src/main/resources/application-oauth2-extractors-github.properties b/spring-security-modules/spring-5-security-oauth/src/main/resources/application-oauth2-extractors-github.properties similarity index 100% rename from spring-5-security-oauth/src/main/resources/application-oauth2-extractors-github.properties rename to spring-security-modules/spring-5-security-oauth/src/main/resources/application-oauth2-extractors-github.properties diff --git a/spring-5-security-oauth/src/main/resources/application-oauth2.properties b/spring-security-modules/spring-5-security-oauth/src/main/resources/application-oauth2.properties similarity index 100% rename from spring-5-security-oauth/src/main/resources/application-oauth2.properties rename to spring-security-modules/spring-5-security-oauth/src/main/resources/application-oauth2.properties diff --git a/spring-5-security-oauth/src/main/resources/application.properties b/spring-security-modules/spring-5-security-oauth/src/main/resources/application.properties similarity index 100% rename from spring-5-security-oauth/src/main/resources/application.properties rename to spring-security-modules/spring-5-security-oauth/src/main/resources/application.properties diff --git a/spring-5-security-oauth/src/main/resources/default-application.properties b/spring-security-modules/spring-5-security-oauth/src/main/resources/default-application.properties similarity index 100% rename from spring-5-security-oauth/src/main/resources/default-application.properties rename to spring-security-modules/spring-5-security-oauth/src/main/resources/default-application.properties diff --git a/spring-5-security-oauth/src/main/resources/jersey-application.properties b/spring-security-modules/spring-5-security-oauth/src/main/resources/jersey-application.properties similarity index 100% rename from spring-5-security-oauth/src/main/resources/jersey-application.properties rename to spring-security-modules/spring-5-security-oauth/src/main/resources/jersey-application.properties diff --git a/spring-boot-modules/spring-boot-kotlin/src/main/resources/logback.xml b/spring-security-modules/spring-5-security-oauth/src/main/resources/logback.xml similarity index 100% rename from spring-boot-modules/spring-boot-kotlin/src/main/resources/logback.xml rename to spring-security-modules/spring-5-security-oauth/src/main/resources/logback.xml diff --git a/spring-5-security-oauth/src/main/resources/static/css/main.css b/spring-security-modules/spring-5-security-oauth/src/main/resources/static/css/main.css similarity index 100% rename from spring-5-security-oauth/src/main/resources/static/css/main.css rename to spring-security-modules/spring-5-security-oauth/src/main/resources/static/css/main.css diff --git a/spring-5-security-oauth/src/main/resources/templates/index.html b/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/index.html similarity index 100% rename from spring-5-security-oauth/src/main/resources/templates/index.html rename to spring-security-modules/spring-5-security-oauth/src/main/resources/templates/index.html diff --git a/spring-5-security-oauth/src/main/resources/templates/loginFailure.html b/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/loginFailure.html similarity index 100% rename from spring-5-security-oauth/src/main/resources/templates/loginFailure.html rename to spring-security-modules/spring-5-security-oauth/src/main/resources/templates/loginFailure.html diff --git a/spring-5-security-oauth/src/main/resources/templates/loginSuccess.html b/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/loginSuccess.html similarity index 100% rename from spring-5-security-oauth/src/main/resources/templates/loginSuccess.html rename to spring-security-modules/spring-5-security-oauth/src/main/resources/templates/loginSuccess.html diff --git a/spring-5-security-oauth/src/main/resources/templates/oauth2_extractors.html b/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth2_extractors.html similarity index 100% rename from spring-5-security-oauth/src/main/resources/templates/oauth2_extractors.html rename to spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth2_extractors.html diff --git a/spring-5-security-oauth/src/main/resources/templates/oauth_login.html b/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth_login.html similarity index 100% rename from spring-5-security-oauth/src/main/resources/templates/oauth_login.html rename to spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth_login.html diff --git a/spring-5-security-oauth/src/main/resources/templates/securedPage.html b/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/securedPage.html similarity index 100% rename from spring-5-security-oauth/src/main/resources/templates/securedPage.html rename to spring-security-modules/spring-5-security-oauth/src/main/resources/templates/securedPage.html diff --git a/spring-5-security-oauth/src/test/java/com/baeldung/jersey/JerseyResourceUnitTest.java b/spring-security-modules/spring-5-security-oauth/src/test/java/com/baeldung/jersey/JerseyResourceUnitTest.java similarity index 100% rename from spring-5-security-oauth/src/test/java/com/baeldung/jersey/JerseyResourceUnitTest.java rename to spring-security-modules/spring-5-security-oauth/src/test/java/com/baeldung/jersey/JerseyResourceUnitTest.java diff --git a/spring-5-security-oauth/src/test/java/com/baeldung/oauth2extractors/ExtractorsUnitTest.java b/spring-security-modules/spring-5-security-oauth/src/test/java/com/baeldung/oauth2extractors/ExtractorsUnitTest.java similarity index 100% rename from spring-5-security-oauth/src/test/java/com/baeldung/oauth2extractors/ExtractorsUnitTest.java rename to spring-security-modules/spring-5-security-oauth/src/test/java/com/baeldung/oauth2extractors/ExtractorsUnitTest.java diff --git a/spring-5-security/README.md b/spring-security-modules/spring-5-security/README.md similarity index 89% rename from spring-5-security/README.md rename to spring-security-modules/spring-5-security/README.md index 6847d4bf5c..bad99c22d4 100644 --- a/spring-5-security/README.md +++ b/spring-security-modules/spring-5-security/README.md @@ -9,6 +9,6 @@ This module contains articles about Spring Security 5 - [New Password Storage In Spring Security 5](https://www.baeldung.com/spring-security-5-password-storage) - [Default Password Encoder in Spring Security 5](https://www.baeldung.com/spring-security-5-default-password-encoder) - [Guide to the AuthenticationManagerResolver in Spring Security](https://www.baeldung.com/spring-security-authenticationmanagerresolver) -- [Disable Security for a Profile in Spring Boot](https://www.baeldung.com/spring-security-disable-profile) - [Manual Logout With Spring Security](https://www.baeldung.com/spring-security-manual-logout) - [How to Disable Spring Security Logout Redirects](https://www.baeldung.com/spring-security-disable-logout-redirects) +- [Prevent Cross-Site Scripting (XSS) in a Spring Application](https://www.baeldung.com/spring-prevent-xss) diff --git a/spring-5-security/pom.xml b/spring-security-modules/spring-5-security/pom.xml similarity index 80% rename from spring-5-security/pom.xml rename to spring-security-modules/spring-5-security/pom.xml index c486d5346b..f50b5ff7a9 100644 --- a/spring-5-security/pom.xml +++ b/spring-security-modules/spring-5-security/pom.xml @@ -12,7 +12,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 @@ -46,6 +46,21 @@ spring-security-test test
+ + org.owasp.esapi + esapi + 2.2.2.0 + + + org.jsoup + jsoup + 1.13.1 + + + commons-io + commons-io + 2.8.0 +
diff --git a/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverApplication.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverApplication.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverApplication.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverApplication.java diff --git a/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverController.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverController.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverController.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/authresolver/AuthResolverController.java diff --git a/spring-5-security/src/main/java/com/baeldung/authresolver/CustomWebSecurityConfigurer.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/authresolver/CustomWebSecurityConfigurer.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/authresolver/CustomWebSecurityConfigurer.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/authresolver/CustomWebSecurityConfigurer.java diff --git a/spring-5-security/src/main/java/com/baeldung/dsl/ClientErrorLoggingConfigurer.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/dsl/ClientErrorLoggingConfigurer.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/dsl/ClientErrorLoggingConfigurer.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/dsl/ClientErrorLoggingConfigurer.java diff --git a/spring-5-security/src/main/java/com/baeldung/dsl/ClientErrorLoggingFilter.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/dsl/ClientErrorLoggingFilter.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/dsl/ClientErrorLoggingFilter.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/dsl/ClientErrorLoggingFilter.java diff --git a/spring-5-security/src/main/java/com/baeldung/dsl/CustomConfigurerApplication.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/dsl/CustomConfigurerApplication.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/dsl/CustomConfigurerApplication.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/dsl/CustomConfigurerApplication.java diff --git a/spring-5-security/src/main/java/com/baeldung/dsl/MyController.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/dsl/MyController.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/dsl/MyController.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/dsl/MyController.java diff --git a/spring-5-security/src/main/java/com/baeldung/dsl/SecurityConfig.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/dsl/SecurityConfig.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/dsl/SecurityConfig.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/dsl/SecurityConfig.java diff --git a/spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryAuthApplication.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryAuthApplication.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryAuthApplication.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryAuthApplication.java diff --git a/spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryAuthController.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryAuthController.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryAuthController.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryAuthController.java diff --git a/spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryAuthWebSecurityConfigurer.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryAuthWebSecurityConfigurer.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryAuthWebSecurityConfigurer.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryAuthWebSecurityConfigurer.java diff --git a/spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryNoOpAuthWebSecurityConfigurer.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryNoOpAuthWebSecurityConfigurer.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryNoOpAuthWebSecurityConfigurer.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/inmemory/InMemoryNoOpAuthWebSecurityConfigurer.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomAuthenticationFilter.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomAuthenticationFilter.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomAuthenticationFilter.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomAuthenticationFilter.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomAuthenticationToken.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomAuthenticationToken.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomAuthenticationToken.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomAuthenticationToken.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserDetailsAuthenticationProvider.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserDetailsAuthenticationProvider.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserDetailsAuthenticationProvider.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserDetailsAuthenticationProvider.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserDetailsService.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserDetailsService.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserDetailsService.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserDetailsService.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserDetailsServiceImpl.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserDetailsServiceImpl.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserDetailsServiceImpl.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserDetailsServiceImpl.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserRepository.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserRepository.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserRepository.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/CustomUserRepository.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/ExtraLoginFieldsApplication.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/ExtraLoginFieldsApplication.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/ExtraLoginFieldsApplication.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/ExtraLoginFieldsApplication.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/PasswordEncoderConfiguration.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/PasswordEncoderConfiguration.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/PasswordEncoderConfiguration.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/PasswordEncoderConfiguration.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/SecurityConfig.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/SecurityConfig.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/SecurityConfig.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/SecurityConfig.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/User.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/User.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/User.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/User.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/UserRepository.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/UserRepository.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/UserRepository.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/UserRepository.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/WebController.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/WebController.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/WebController.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldscustom/WebController.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/ExtraLoginFieldsApplication.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/ExtraLoginFieldsApplication.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/ExtraLoginFieldsApplication.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/ExtraLoginFieldsApplication.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/PasswordEncoderConfiguration.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/PasswordEncoderConfiguration.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/PasswordEncoderConfiguration.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/PasswordEncoderConfiguration.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SecurityConfig.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SecurityConfig.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SecurityConfig.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SecurityConfig.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleAuthenticationFilter.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleAuthenticationFilter.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleAuthenticationFilter.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleAuthenticationFilter.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleUserDetailsService.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleUserDetailsService.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleUserDetailsService.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleUserDetailsService.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleUserRepository.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleUserRepository.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleUserRepository.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/SimpleUserRepository.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/User.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/User.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/User.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/User.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/UserRepository.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/UserRepository.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/UserRepository.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/UserRepository.java diff --git a/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/WebController.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/WebController.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/WebController.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/loginextrafieldssimple/WebController.java diff --git a/spring-5-security/src/main/java/com/baeldung/logoutredirects/LogoutApplication.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/logoutredirects/LogoutApplication.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/logoutredirects/LogoutApplication.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/logoutredirects/LogoutApplication.java diff --git a/spring-5-security/src/main/java/com/baeldung/logoutredirects/securityconfig/SpringSecurityConfig.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/logoutredirects/securityconfig/SpringSecurityConfig.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/logoutredirects/securityconfig/SpringSecurityConfig.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/logoutredirects/securityconfig/SpringSecurityConfig.java diff --git a/spring-5-security/src/main/java/com/baeldung/manuallogout/ManualLogoutApplication.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/manuallogout/ManualLogoutApplication.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/manuallogout/ManualLogoutApplication.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/manuallogout/ManualLogoutApplication.java diff --git a/spring-5-security/src/main/java/com/baeldung/manuallogout/SimpleSecurityConfiguration.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/manuallogout/SimpleSecurityConfiguration.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/manuallogout/SimpleSecurityConfiguration.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/manuallogout/SimpleSecurityConfiguration.java diff --git a/spring-5-security/src/main/java/com/baeldung/passwordstorage/BaeldungPasswordEncoderSetup.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/passwordstorage/BaeldungPasswordEncoderSetup.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/passwordstorage/BaeldungPasswordEncoderSetup.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/passwordstorage/BaeldungPasswordEncoderSetup.java diff --git a/spring-5-security/src/main/java/com/baeldung/passwordstorage/PasswordStorageApplication.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/passwordstorage/PasswordStorageApplication.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/passwordstorage/PasswordStorageApplication.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/passwordstorage/PasswordStorageApplication.java diff --git a/spring-5-security/src/main/java/com/baeldung/passwordstorage/PasswordStorageWebSecurityConfigurer.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/passwordstorage/PasswordStorageWebSecurityConfigurer.java similarity index 100% rename from spring-5-security/src/main/java/com/baeldung/passwordstorage/PasswordStorageWebSecurityConfigurer.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/passwordstorage/PasswordStorageWebSecurityConfigurer.java diff --git a/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/Application.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/Application.java new file mode 100644 index 0000000000..b463a7adc3 --- /dev/null +++ b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/Application.java @@ -0,0 +1,14 @@ +package com.baeldung.xss; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; + +@SpringBootApplication +@EnableWebSecurity +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/interoperability/Customer.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/Person.java similarity index 51% rename from core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/interoperability/Customer.java rename to spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/Person.java index 4a070a0f97..1e7c02bae8 100644 --- a/core-kotlin-modules/core-kotlin/src/main/java/com/baeldung/interoperability/Customer.java +++ b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/Person.java @@ -1,9 +1,9 @@ -package com.baeldung.interoperability; - -public class Customer { +package com.baeldung.xss; +public class Person { private String firstName; private String lastName; + private int age; public String getFirstName() { return firstName; @@ -21,4 +21,16 @@ public class Customer { this.lastName = lastName; } + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public String toString() { + return "Person {" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + ", age=" + age + '}'; + } } diff --git a/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/PersonController.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/PersonController.java new file mode 100644 index 0000000000..8486e04e48 --- /dev/null +++ b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/PersonController.java @@ -0,0 +1,31 @@ +package com.baeldung.xss; + +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestBody; + +import java.util.Map; + +@RestController +@RequestMapping("/personService") +public class PersonController { + + @PostMapping(value = "/person") + private ResponseEntity savePerson(@RequestHeader Map headers, + @RequestParam String param, @RequestBody Person body) { + ObjectNode response = JsonNodeFactory.instance.objectNode(); + headers.forEach((key, value) -> response.put(key, value)); + response.put("firstName", body.getFirstName()); + response.put("lastName", body.getLastName()); + response.put("age", body.getAge()); + response.put("param", param); + return new ResponseEntity(response.toString(), HttpStatus.OK); + } +} \ No newline at end of file diff --git a/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/SecurityConf.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/SecurityConf.java new file mode 100644 index 0000000000..25d8026e4a --- /dev/null +++ b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/SecurityConf.java @@ -0,0 +1,25 @@ +package com.baeldung.xss; + +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +public class SecurityConf extends WebSecurityConfigurerAdapter { + + @Override + public void configure(WebSecurity web) { + // Ignoring here is only for this example. Normally people would apply their own authentication/authorization policies + web.ignoring().antMatchers("/**"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http + .headers() + .xssProtection() + .and() + .contentSecurityPolicy("script-src 'self'"); + } +} diff --git a/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/XSSFilter.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/XSSFilter.java new file mode 100644 index 0000000000..431ed4d120 --- /dev/null +++ b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/XSSFilter.java @@ -0,0 +1,44 @@ +package com.baeldung.xss; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.StringUtils; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import javax.servlet.Filter; +import javax.servlet.FilterConfig; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.ServletException; +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class XSSFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) { + } + + @Override + public void destroy() { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + + XSSRequestWrapper wrappedRequest = new XSSRequestWrapper((HttpServletRequest) request); + + String body = IOUtils.toString(wrappedRequest.getReader()); + if (!StringUtils.isBlank(body)) { + body = XSSUtils.stripXSS(body); + wrappedRequest.resetInputStream(body.getBytes()); + } + + chain.doFilter(wrappedRequest, response); + } + +} \ No newline at end of file diff --git a/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/XSSRequestWrapper.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/XSSRequestWrapper.java new file mode 100644 index 0000000000..8fe4e20b5c --- /dev/null +++ b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/XSSRequestWrapper.java @@ -0,0 +1,123 @@ +package com.baeldung.xss; + +import org.apache.commons.codec.Charsets; +import org.apache.commons.io.IOUtils; +import javax.servlet.ReadListener; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; + +import static com.baeldung.xss.XSSUtils.stripXSS; + + +public class XSSRequestWrapper extends HttpServletRequestWrapper { + + private byte[] rawData; + private HttpServletRequest request; + private ResettableServletInputStream servletStream; + + public XSSRequestWrapper(HttpServletRequest request) { + super(request); + this.request = request; + this.servletStream = new ResettableServletInputStream(); + } + + public void resetInputStream(byte[] newRawData) { + rawData = newRawData; + servletStream.stream = new ByteArrayInputStream(newRawData); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + if (rawData == null) { + rawData = IOUtils.toByteArray(this.request.getReader(), Charsets.UTF_8); + servletStream.stream = new ByteArrayInputStream(rawData); + } + return servletStream; + } + + @Override + public BufferedReader getReader() throws IOException { + if (rawData == null) { + rawData = IOUtils.toByteArray(this.request.getReader(), Charsets.UTF_8); + servletStream.stream = new ByteArrayInputStream(rawData); + } + return new BufferedReader(new InputStreamReader(servletStream)); + } + + private class ResettableServletInputStream extends ServletInputStream { + + private InputStream stream; + + @Override + public int read() throws IOException { + return stream.read(); + } + + @Override + public boolean isFinished() { + return false; + } + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setReadListener(ReadListener readListener) { + + } + } + + @Override + public String[] getParameterValues(String parameter) { + String[] values = super.getParameterValues(parameter); + if (values == null) { + return null; + } + int count = values.length; + String[] encodedValues = new String[count]; + for (int i = 0; i < count; i++) { + encodedValues[i] = stripXSS(values[i]); + } + return encodedValues; + } + + @Override + public String getParameter(String parameter) { + String value = super.getParameter(parameter); + return stripXSS(value); + } + + @Override + public String getHeader(String name) { + String value = super.getHeader(name); + return stripXSS(value); + } + + @Override + public Enumeration getHeaders(String name) { + List result = new ArrayList<>(); + Enumeration headers = super.getHeaders(name); + while (headers.hasMoreElements()) { + String header = headers.nextElement(); + String[] tokens = header.split(","); + for (String token : tokens) { + result.add(stripXSS(token)); + } + } + return Collections.enumeration(result); + } + +} diff --git a/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/XSSUtils.java b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/XSSUtils.java new file mode 100644 index 0000000000..51bcba8115 --- /dev/null +++ b/spring-security-modules/spring-5-security/src/main/java/com/baeldung/xss/XSSUtils.java @@ -0,0 +1,19 @@ +package com.baeldung.xss; + +import org.jsoup.Jsoup; +import org.jsoup.safety.Whitelist; +import org.owasp.esapi.ESAPI; + +public class XSSUtils { + + public static String stripXSS(String value) { + if (value == null) { + return null; + } + value = ESAPI.encoder() + .canonicalize(value) + .replaceAll("\0", ""); + return Jsoup.clean(value, Whitelist.none()); + } + +} diff --git a/spring-security-modules/spring-5-security/src/main/resources/ESAPI.properties b/spring-security-modules/spring-5-security/src/main/resources/ESAPI.properties new file mode 100644 index 0000000000..a2746a4dbc --- /dev/null +++ b/spring-security-modules/spring-5-security/src/main/resources/ESAPI.properties @@ -0,0 +1,545 @@ +# +# OWASP Enterprise Security API (ESAPI) Properties file -- PRODUCTION Version +# +# This file is part of the Open Web Application Security Project (OWASP) +# Enterprise Security API (ESAPI) project. For details, please see +# https://owasp.org/www-project-enterprise-security-api/ +# +# Copyright (c) 2008,2009 - The OWASP Foundation +# +# DISCUSS: This may cause a major backwards compatibility issue, etc. but +# from a name space perspective, we probably should have prefaced +# all the property names with ESAPI or at least OWASP. Otherwise +# there could be problems is someone loads this properties file into +# the System properties. We could also put this file into the +# esapi.jar file (perhaps as a ResourceBundle) and then allow an external +# ESAPI properties be defined that would overwrite these defaults. +# That keeps the application's properties relatively simple as usually +# they will only want to override a few properties. If looks like we +# already support multiple override levels of this in the +# DefaultSecurityConfiguration class, but I'm suggesting placing the +# defaults in the esapi.jar itself. That way, if the jar is signed, +# we could detect if those properties had been tampered with. (The +# code to check the jar signatures is pretty simple... maybe 70-90 LOC, +# but off course there is an execution penalty (similar to the way +# that the separate sunjce.jar used to be when a class from it was +# first loaded). Thoughts? +############################################################################### +# +# WARNING: Operating system protection should be used to lock down the .esapi +# resources directory and all the files inside and all the directories all the +# way up to the root directory of the file system. Note that if you are using +# file-based implementations, that some files may need to be read-write as they +# get updated dynamically. +# +#=========================================================================== +# ESAPI Configuration +# +# If true, then print all the ESAPI properties set here when they are loaded. +# If false, they are not printed. Useful to reduce output when running JUnit tests. +# If you need to troubleshoot a properties related problem, turning this on may help. +# This is 'false' in the src/test/resources/.esapi version. It is 'true' by +# default for reasons of backward compatibility with earlier ESAPI versions. +ESAPI.printProperties=true + +# ESAPI is designed to be easily extensible. You can use the reference implementation +# or implement your own providers to take advantage of your enterprise's security +# infrastructure. The functions in ESAPI are referenced using the ESAPI locator, like: +# +# String ciphertext = +# ESAPI.encryptor().encrypt("Secret message"); // Deprecated in 2.0 +# CipherText cipherText = +# ESAPI.encryptor().encrypt(new PlainText("Secret message")); // Preferred +# +# Below you can specify the classname for the provider that you wish to use in your +# application. The only requirement is that it implement the appropriate ESAPI interface. +# This allows you to switch security implementations in the future without rewriting the +# entire application. +# +# ExperimentalAccessController requires ESAPI-AccessControlPolicy.xml in .esapi directory +ESAPI.AccessControl=org.owasp.esapi.reference.DefaultAccessController +# FileBasedAuthenticator requires users.txt file in .esapi directory +ESAPI.Authenticator=org.owasp.esapi.reference.FileBasedAuthenticator +ESAPI.Encoder=org.owasp.esapi.reference.DefaultEncoder +ESAPI.Encryptor=org.owasp.esapi.reference.crypto.JavaEncryptor + +ESAPI.Executor=org.owasp.esapi.reference.DefaultExecutor +ESAPI.HTTPUtilities=org.owasp.esapi.reference.DefaultHTTPUtilities +ESAPI.IntrusionDetector=org.owasp.esapi.reference.DefaultIntrusionDetector +# Log4JFactory Requires log4j.xml or log4j.properties in classpath - http://www.laliluna.de/log4j-tutorial.html +# Note that this is now considered deprecated! +ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory +#ESAPI.Logger=org.owasp.esapi.logging.log4j.Log4JLogFactory +#ESAPI.Logger=org.owasp.esapi.logging.java.JavaLogFactory +# To use the new SLF4J logger in ESAPI (see GitHub issue #129), set +# ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory +# and do whatever other normal SLF4J configuration that you normally would do for your application. +ESAPI.Randomizer=org.owasp.esapi.reference.DefaultRandomizer +ESAPI.Validator=org.owasp.esapi.reference.DefaultValidator + +#=========================================================================== +# ESAPI Authenticator +# +Authenticator.AllowedLoginAttempts=3 +Authenticator.MaxOldPasswordHashes=13 +Authenticator.UsernameParameterName=username +Authenticator.PasswordParameterName=password +# RememberTokenDuration (in days) +Authenticator.RememberTokenDuration=14 +# Session Timeouts (in minutes) +Authenticator.IdleTimeoutDuration=20 +Authenticator.AbsoluteTimeoutDuration=120 + +#=========================================================================== +# ESAPI Encoder +# +# ESAPI canonicalizes input before validation to prevent bypassing filters with encoded attacks. +# Failure to canonicalize input is a very common mistake when implementing validation schemes. +# Canonicalization is automatic when using the ESAPI Validator, but you can also use the +# following code to canonicalize data. +# +# ESAPI.Encoder().canonicalize( "%22hello world"" ); +# +# Multiple encoding is when a single encoding format is applied multiple times. Allowing +# multiple encoding is strongly discouraged. +Encoder.AllowMultipleEncoding=false + +# Mixed encoding is when multiple different encoding formats are applied, or when +# multiple formats are nested. Allowing multiple encoding is strongly discouraged. +Encoder.AllowMixedEncoding=false + +# The default list of codecs to apply when canonicalizing untrusted data. The list should include the codecs +# for all downstream interpreters or decoders. For example, if the data is likely to end up in a URL, HTML, or +# inside JavaScript, then the list of codecs below is appropriate. The order of the list is not terribly important. +Encoder.DefaultCodecList=HTMLEntityCodec,PercentCodec,JavaScriptCodec + + +#=========================================================================== +# ESAPI Encryption +# +# The ESAPI Encryptor provides basic cryptographic functions with a simplified API. +# To get started, generate a new key using java -classpath esapi.jar org.owasp.esapi.reference.crypto.JavaEncryptor +# There is not currently any support for key rotation, so be careful when changing your key and salt as it +# will invalidate all signed, encrypted, and hashed data. +# +# WARNING: Not all combinations of algorithms and key lengths are supported. +# If you choose to use a key length greater than 128, you MUST download the +# unlimited strength policy files and install in the lib directory of your JRE/JDK. +# See http://java.sun.com/javase/downloads/index.jsp for more information. +# +# ***** IMPORTANT: Do NOT forget to replace these with your own values! ***** +# To calculate these values, you can run: +# java -classpath esapi.jar org.owasp.esapi.reference.crypto.JavaEncryptor +# +#Encryptor.MasterKey= +#Encryptor.MasterSalt= + +# Provides the default JCE provider that ESAPI will "prefer" for its symmetric +# encryption and hashing. (That is it will look to this provider first, but it +# will defer to other providers if the requested algorithm is not implemented +# by this provider.) If left unset, ESAPI will just use your Java VM's current +# preferred JCE provider, which is generally set in the file +# "$JAVA_HOME/jre/lib/security/java.security". +# +# The main intent of this is to allow ESAPI symmetric encryption to be +# used with a FIPS 140-2 compliant crypto-module. For details, see the section +# "Using ESAPI Symmetric Encryption with FIPS 140-2 Cryptographic Modules" in +# the ESAPI 2.0 Symmetric Encryption User Guide, at: +# http://owasp-esapi-java.googlecode.com/svn/trunk/documentation/esapi4java-core-2.0-symmetric-crypto-user-guide.html +# However, this property also allows you to easily use an alternate JCE provider +# such as "Bouncy Castle" without having to make changes to "java.security". +# See Javadoc for SecurityProviderLoader for further details. If you wish to use +# a provider that is not known to SecurityProviderLoader, you may specify the +# fully-qualified class name of the JCE provider class that implements +# java.security.Provider. If the name contains a '.', this is interpreted as +# a fully-qualified class name that implements java.security.Provider. +# +# NOTE: Setting this property has the side-effect of changing it in your application +# as well, so if you are using JCE in your application directly rather than +# through ESAPI (you wouldn't do that, would you? ;-), it will change the +# preferred JCE provider there as well. +# +# Default: Keeps the JCE provider set to whatever JVM sets it to. +Encryptor.PreferredJCEProvider= + +# AES is the most widely used and strongest encryption algorithm. This +# should agree with your Encryptor.CipherTransformation property. +# Warning: This property does not control the default reference implementation for +# ESAPI 2.0 using JavaEncryptor. Also, this property will be dropped +# in the future. +# @deprecated +Encryptor.EncryptionAlgorithm=AES +# For ESAPI Java 2.0 - New encrypt / decrypt methods use this. +Encryptor.CipherTransformation=AES/CBC/PKCS5Padding + +# Applies to ESAPI 2.0 and later only! +# Comma-separated list of cipher modes that provide *BOTH* +# confidentiality *AND* message authenticity. (NIST refers to such cipher +# modes as "combined modes" so that's what we shall call them.) If any of these +# cipher modes are used then no MAC is calculated and stored +# in the CipherText upon encryption. Likewise, if one of these +# cipher modes is used with decryption, no attempt will be made +# to validate the MAC contained in the CipherText object regardless +# of whether it contains one or not. Since the expectation is that +# these cipher modes support support message authenticity already, +# injecting a MAC in the CipherText object would be at best redundant. +# +# Note that as of JDK 1.5, the SunJCE provider does not support *any* +# of these cipher modes. Of these listed, only GCM and CCM are currently +# NIST approved. YMMV for other JCE providers. E.g., Bouncy Castle supports +# GCM and CCM with "NoPadding" mode, but not with "PKCS5Padding" or other +# padding modes. +Encryptor.cipher_modes.combined_modes=GCM,CCM,IAPM,EAX,OCB,CWC + +# Applies to ESAPI 2.0 and later only! +# Additional cipher modes allowed for ESAPI 2.0 encryption. These +# cipher modes are in _addition_ to those specified by the property +# 'Encryptor.cipher_modes.combined_modes'. +# Note: We will add support for streaming modes like CFB & OFB once +# we add support for 'specified' to the property 'Encryptor.ChooseIVMethod' +# (probably in ESAPI 2.1). +# DISCUSS: Better name? +Encryptor.cipher_modes.additional_allowed=CBC + +# Default key size to use for cipher specified by Encryptor.EncryptionAlgorithm. +# Note that this MUST be a valid key size for the algorithm being used +# (as specified by Encryptor.EncryptionAlgorithm). So for example, if AES is used, +# it must be 128, 192, or 256. If DESede is chosen, then it must be either 112 or 168. +# +# Note that 128-bits is almost always sufficient and for AES it appears to be more +# somewhat more resistant to related key attacks than is 256-bit AES.) +# +# Defaults to 128-bits if left blank. +# +# NOTE: If you use a key size > 128-bits, then you MUST have the JCE Unlimited +# Strength Jurisdiction Policy files installed!!! +# +Encryptor.EncryptionKeyLength=128 + +# This is the _minimum_ key size (in bits) that we allow with ANY symmetric +# cipher for doing encryption. (There is no minimum for decryption.) +# +# Generally, if you only use one algorithm, this should be set the same as +# the Encryptor.EncryptionKeyLength property. +Encryptor.MinEncryptionKeyLength=128 + +# Because 2.x uses CBC mode by default, it requires an initialization vector (IV). +# (All cipher modes except ECB require an IV.) There are two choices: we can either +# use a fixed IV known to both parties or allow ESAPI to choose a random IV. While +# the IV does not need to be hidden from adversaries, it is important that the +# adversary not be allowed to choose it. Also, random IVs are generally much more +# secure than fixed IVs. (In fact, it is essential that feed-back cipher modes +# such as CFB and OFB use a different IV for each encryption with a given key so +# in such cases, random IVs are much preferred. By default, ESAPI 2.0 uses random +# IVs. If you wish to use 'fixed' IVs, set 'Encryptor.ChooseIVMethod=fixed' and +# uncomment the Encryptor.fixedIV. +# +# Valid values: random|fixed|specified 'specified' not yet implemented; planned for 2.3 +# 'fixed' is deprecated as of 2.2 +# and will be removed in 2.3. +Encryptor.ChooseIVMethod=random + + +# If you choose to use a fixed IV, then you must place a fixed IV here that +# is known to all others who are sharing your secret key. The format should +# be a hex string that is the same length as the cipher block size for the +# cipher algorithm that you are using. The following is an *example* for AES +# from an AES test vector for AES-128/CBC as described in: +# NIST Special Publication 800-38A (2001 Edition) +# "Recommendation for Block Cipher Modes of Operation". +# (Note that the block size for AES is 16 bytes == 128 bits.) +# +# @Deprecated -- fixed IVs are deprecated as of the 2.2 release and support +# will be removed in the next release (tentatively, 2.3). +# If you MUST use this, at least replace this IV with one +# that your legacy application was using. +Encryptor.fixedIV=0x000102030405060708090a0b0c0d0e0f + +# Whether or not CipherText should use a message authentication code (MAC) with it. +# This prevents an adversary from altering the IV as well as allowing a more +# fool-proof way of determining the decryption failed because of an incorrect +# key being supplied. This refers to the "separate" MAC calculated and stored +# in CipherText, not part of any MAC that is calculated as a result of a +# "combined mode" cipher mode. +# +# If you are using ESAPI with a FIPS 140-2 cryptographic module, you *must* also +# set this property to false. That is because ESAPI takes the master key and +# derives 2 keys from it--a key for the MAC and a key for encryption--and +# because ESAPI is not itself FIPS 140-2 verified such intermediary aterations +# to keys from FIPS approved sources would have the effect of making your FIPS +# approved key generation and thus your FIPS approved JCE provider unapproved! +# More details in +# documentation/esapi4java-core-2.0-readme-crypto-changes.html +# documentation/esapi4java-core-2.0-symmetric-crypto-user-guide.html +# You have been warned. +Encryptor.CipherText.useMAC=true + +# Whether or not the PlainText object may be overwritten and then marked +# eligible for garbage collection. If not set, this is still treated as 'true'. +Encryptor.PlainText.overwrite=true + +# Do not use DES except in a legacy situations. 56-bit is way too small key size. +#Encryptor.EncryptionKeyLength=56 +#Encryptor.MinEncryptionKeyLength=56 +#Encryptor.EncryptionAlgorithm=DES + +# TripleDES is considered strong enough for most purposes. +# Note: There is also a 112-bit version of DESede. Using the 168-bit version +# requires downloading the special jurisdiction policy from Sun. +#Encryptor.EncryptionKeyLength=168 +#Encryptor.MinEncryptionKeyLength=112 +#Encryptor.EncryptionAlgorithm=DESede + +Encryptor.HashAlgorithm=SHA-512 +Encryptor.HashIterations=1024 +Encryptor.DigitalSignatureAlgorithm=SHA1withDSA +Encryptor.DigitalSignatureKeyLength=1024 +Encryptor.RandomAlgorithm=SHA1PRNG +Encryptor.CharacterEncoding=UTF-8 + +# This is the Pseudo Random Function (PRF) that ESAPI's Key Derivation Function +# (KDF) normally uses. Note this is *only* the PRF used for ESAPI's KDF and +# *not* what is used for ESAPI's MAC. (Currently, HmacSHA1 is always used for +# the MAC, mostly to keep the overall size at a minimum.) +# +# Currently supported choices for JDK 1.5 and 1.6 are: +# HmacSHA1 (160 bits), HmacSHA256 (256 bits), HmacSHA384 (384 bits), and +# HmacSHA512 (512 bits). +# Note that HmacMD5 is *not* supported for the PRF used by the KDF even though +# the JDKs support it. See the ESAPI 2.0 Symmetric Encryption User Guide +# further details. +Encryptor.KDF.PRF=HmacSHA256 +#=========================================================================== +# ESAPI HttpUtilties +# +# The HttpUtilities provide basic protections to HTTP requests and responses. Primarily these methods +# protect against malicious data from attackers, such as unprintable characters, escaped characters, +# and other simple attacks. The HttpUtilities also provides utility methods for dealing with cookies, +# headers, and CSRF tokens. +# +# Default file upload location (remember to escape backslashes with \\) +HttpUtilities.UploadDir=C:\\ESAPI\\testUpload +HttpUtilities.UploadTempDir=C:\\temp +# Force flags on cookies, if you use HttpUtilities to set cookies +HttpUtilities.ForceHttpOnlySession=false +HttpUtilities.ForceSecureSession=false +HttpUtilities.ForceHttpOnlyCookies=true +HttpUtilities.ForceSecureCookies=true +# Maximum size of HTTP header key--the validator regex may have additional values. +HttpUtilities.MaxHeaderNameSize=256 +# Maximum size of HTTP header value--the validator regex may have additional values. +HttpUtilities.MaxHeaderValueSize=4096 +# Maximum size of JSESSIONID for the application--the validator regex may have additional values. +HttpUtilities.HTTPJSESSIONIDLENGTH=50 +# Maximum length of a URL (see https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers) +HttpUtilities.URILENGTH=2000 +# Maximum length of a redirect +HttpUtilities.maxRedirectLength=512 +# Maximum length for an http scheme +HttpUtilities.HTTPSCHEMELENGTH=10 +# Maximum length for an http host +HttpUtilities.HTTPHOSTLENGTH=100 +# Maximum length for an http path +HttpUtilities.HTTPPATHLENGTH=150 +#Maximum length for a context path +HttpUtilities.contextPathLength=150 +#Maximum length for an httpServletPath +HttpUtilities.HTTPSERVLETPATHLENGTH=100 +#Maximum length for an http query parameter name +HttpUtilities.httpQueryParamNameLength=100 +#Maximum length for an http query parameter -- old default was 2000, but that's the max length for a URL... +HttpUtilities.httpQueryParamValueLength=500 +# File upload configuration +HttpUtilities.ApprovedUploadExtensions=.pdf,.doc,.docx,.ppt,.pptx,.xls,.xlsx,.rtf,.txt,.jpg,.png +HttpUtilities.MaxUploadFileBytes=500000000 +# Using UTF-8 throughout your stack is highly recommended. That includes your database driver, +# container, and any other technologies you may be using. Failure to do this may expose you +# to Unicode transcoding injection attacks. Use of UTF-8 does not hinder internationalization. +HttpUtilities.ResponseContentType=text/html; charset=UTF-8 +# This is the name of the cookie used to represent the HTTP session +# Typically this will be the default "JSESSIONID" +HttpUtilities.HttpSessionIdName=JSESSIONID +#Sets whether or not we will overwrite http status codes to 200. +HttpUtilities.OverwriteStatusCodes=true +#Sets the application's base character encoding. This is forked from the Java Encryptor property. +HttpUtilities.CharacterEncoding=UTF-8 + +#=========================================================================== +# ESAPI Executor +# CHECKME - This should be made OS independent. Don't use unsafe defaults. +# # Examples only -- do NOT blindly copy! +# For Windows: +# Executor.WorkingDirectory=C:\\Windows\\Temp +# Executor.ApprovedExecutables=C:\\Windows\\System32\\cmd.exe,C:\\Windows\\System32\\runas.exe +# For *nux, MacOS: +# Executor.WorkingDirectory=/tmp +# Executor.ApprovedExecutables=/bin/bash +Executor.WorkingDirectory= +Executor.ApprovedExecutables= + + +#=========================================================================== +# ESAPI Logging +# Set the application name if these logs are combined with other applications +Logger.ApplicationName=ExampleApplication +# If you use an HTML log viewer that does not properly HTML escape log data, you can set LogEncodingRequired to true +Logger.LogEncodingRequired=false +# Determines whether ESAPI should log the application name. This might be clutter in some single-server/single-app environments. +Logger.LogApplicationName=true +# Determines whether ESAPI should log the server IP and port. This might be clutter in some single-server environments. +Logger.LogServerIP=true +# LogFileName, the name of the logging file. Provide a full directory path (e.g., C:\\ESAPI\\ESAPI_logging_file) if you +# want to place it in a specific directory. +Logger.LogFileName=ESAPI_logging_file +# MaxLogFileSize, the max size (in bytes) of a single log file before it cuts over to a new one (default is 10,000,000) +Logger.MaxLogFileSize=10000000 +# Determines whether ESAPI should log the user info. +Logger.UserInfo=true +# Determines whether ESAPI should log the session id and client IP. +Logger.ClientInfo=true + +#=========================================================================== +# ESAPI Intrusion Detection +# +# Each event has a base to which .count, .interval, and .action are added +# The IntrusionException will fire if we receive "count" events within "interval" seconds +# The IntrusionDetector is configurable to take the following actions: log, logout, and disable +# (multiple actions separated by commas are allowed e.g. event.test.actions=log,disable +# +# Custom Events +# Names must start with "event." as the base +# Use IntrusionDetector.addEvent( "test" ) in your code to trigger "event.test" here +# You can also disable intrusion detection completely by changing +# the following parameter to true +# +IntrusionDetector.Disable=false +# +IntrusionDetector.event.test.count=2 +IntrusionDetector.event.test.interval=10 +IntrusionDetector.event.test.actions=disable,log + +# Exception Events +# All EnterpriseSecurityExceptions are registered automatically +# Call IntrusionDetector.getInstance().addException(e) for Exceptions that do not extend EnterpriseSecurityException +# Use the fully qualified classname of the exception as the base + +# any intrusion is an attack +IntrusionDetector.org.owasp.esapi.errors.IntrusionException.count=1 +IntrusionDetector.org.owasp.esapi.errors.IntrusionException.interval=1 +IntrusionDetector.org.owasp.esapi.errors.IntrusionException.actions=log,disable,logout + +# for test purposes +# CHECKME: Shouldn't there be something in the property name itself that designates +# that these are for testing??? +IntrusionDetector.org.owasp.esapi.errors.IntegrityException.count=10 +IntrusionDetector.org.owasp.esapi.errors.IntegrityException.interval=5 +IntrusionDetector.org.owasp.esapi.errors.IntegrityException.actions=log,disable,logout + +# rapid validation errors indicate scans or attacks in progress +# org.owasp.esapi.errors.ValidationException.count=10 +# org.owasp.esapi.errors.ValidationException.interval=10 +# org.owasp.esapi.errors.ValidationException.actions=log,logout + +# sessions jumping between hosts indicates session hijacking +IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.count=2 +IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.interval=10 +IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.actions=log,logout + + +#=========================================================================== +# ESAPI Validation +# +# The ESAPI Validator works on regular expressions with defined names. You can define names +# either here, or you may define application specific patterns in a separate file defined below. +# This allows enterprises to specify both organizational standards as well as application specific +# validation rules. +# +# Use '\p{L}' (without the quotes) within the character class to match +# any Unicode LETTER. You can also use a range, like: \u00C0-\u017F +# You can also use any of the regex flags as documented at +# https://docs.oracle.com/javase/tutorial/essential/regex/pattern.html, e.g. (?u) +# +Validator.ConfigurationFile=validation.properties + +# Validators used by ESAPI +Validator.AccountName=^[a-zA-Z0-9]{3,20}$ +Validator.SystemCommand=^[a-zA-Z\\-\\/]{1,64}$ +Validator.RoleName=^[a-z]{1,20}$ + +#the word TEST below should be changed to your application +#name - only relative URL's are supported +Validator.Redirect=^\\/test.*$ + +# Global HTTP Validation Rules +# Values with Base64 encoded data (e.g. encrypted state) will need at least [a-zA-Z0-9\/+=] +Validator.HTTPScheme=^(http|https)$ +Validator.HTTPServerName=^[a-zA-Z0-9_.\\-]*$ +Validator.HTTPCookieName=^[a-zA-Z0-9\\-_]{1,32}$ +Validator.HTTPCookieValue=^[a-zA-Z0-9\\-\\/+=_ ]*$ +# Note that headerName and Value length is also configured in the HTTPUtilities section +Validator.HTTPHeaderName=^[a-zA-Z0-9\\-_]{1,256}$ +Validator.HTTPHeaderValue=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ ]*$ +Validator.HTTPServletPath=^[a-zA-Z0-9.\\-\\/_]*$ +Validator.HTTPPath=^[a-zA-Z0-9.\\-_]*$ +Validator.HTTPURL=^.*$ +Validator.HTTPJSESSIONID=^[A-Z0-9]{10,32}$ + + +# Contributed by Fraenku@gmx.ch +# Github Issue 126 https://github.com/ESAPI/esapi-java-legacy/issues/126 +Validator.HTTPParameterName=^[a-zA-Z0-9_\\-]{1,32}$ +Validator.HTTPParameterValue=^[\\p{L}\\p{N}.\\-/+=_ !$*?@]{0,1000}$ +Validator.HTTPContextPath=^/[a-zA-Z0-9.\\-_]*$ +Validator.HTTPQueryString=^([a-zA-Z0-9_\\-]{1,32}=[\\p{L}\\p{N}.\\-/+=_ !$*?@%]*&?)*$ +Validator.HTTPURI=^/([a-zA-Z0-9.\\-_]*/?)*$ + + +# Validation of file related input +Validator.FileName=^[a-zA-Z0-9!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$ +Validator.DirectoryName=^[a-zA-Z0-9:/\\\\!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$ + +# Validation of dates. Controls whether or not 'lenient' dates are accepted. +# See DataFormat.setLenient(boolean flag) for further details. +Validator.AcceptLenientDates=false + +# ~~~~~ Important Note ~~~~~ +# This is a workaround to make sure that a commit to address GitHub issue #509 +# doesn't accidentally break someone's production code. So essentially what we +# are doing is to reverting back to the previous possibly buggy (by +# documentation intent at least), but, by now, expected legacy behavior. +# Prior to the code changes for issue #509, if invalid / malicious HTML input was +# observed, AntiSamy would simply attempt to sanitize (cleanse) it and it would +# only be logged. However, the code change made ESAPI comply with its +# documentation, which stated that a ValidationException should be thrown in +# such cases. Unfortunately, changing this behavior--especially when no one is +# 100% certain that the documentation was correct--could break existing code +# using ESAPI so after a lot of debate, issue #521 was created to restore the +# previous behavior, but still allow the documented behavior. (We did this +# because it wasn't really causing an security issues since AntiSamy would clean +# it up anyway and we value backward compatibility as long as it doesn't clearly +# present security vulnerabilities.) +# More defaults about this are written up under GitHub issue #521 and +# the pull request it references. Future major releases of ESAPI (e.g., ESAPI 3.x) +# will not support this previous behavior, but it will remain for ESAPI 2.x. +# Set this to 'throw' if you want the originally intended behavior of throwing +# that was fixed via issue #509. Set to 'clean' if you want want the HTML input +# sanitized instead. +# +# Possible values: +# clean -- Use the legacy behavior where unsafe HTML input is logged and the +# sanitized (i.e., clean) input as determined by AntiSamy and your +# AntiSamy rules is returned. This is the default behavior if this +# new property is not found. +# throw -- The new, presumably correct and originally intended behavior where +# a ValidationException is thrown when unsafe HTML input is +# encountered. +# +#Validator.HtmlValidationAction=clean +Validator.HtmlValidationAction=throw + +# With the fix for #310 to enable loading antisamy-esapi.xml from the classpath +# also an enhancement was made to be able to use a different filename for the configuration. +# You don't have to configure the filename here, but in that case the code will keep looking for antisamy-esapi.xml. +# This is the default behaviour of ESAPI. +# +#Validator.HtmlValidationConfigurationFile=antisamy-esapi.xml \ No newline at end of file diff --git a/spring-5-security/src/main/resources/application-extrafields.properties b/spring-security-modules/spring-5-security/src/main/resources/application-extrafields.properties similarity index 100% rename from spring-5-security/src/main/resources/application-extrafields.properties rename to spring-security-modules/spring-5-security/src/main/resources/application-extrafields.properties diff --git a/spring-5-security/src/main/resources/application.properties b/spring-security-modules/spring-5-security/src/main/resources/application.properties similarity index 100% rename from spring-5-security/src/main/resources/application.properties rename to spring-security-modules/spring-5-security/src/main/resources/application.properties diff --git a/spring-dispatcher-servlet/src/main/resources/logback.xml b/spring-security-modules/spring-5-security/src/main/resources/logback.xml similarity index 100% rename from spring-dispatcher-servlet/src/main/resources/logback.xml rename to spring-security-modules/spring-5-security/src/main/resources/logback.xml diff --git a/spring-5-security/src/main/resources/static/css/main.css b/spring-security-modules/spring-5-security/src/main/resources/static/css/main.css similarity index 100% rename from spring-5-security/src/main/resources/static/css/main.css rename to spring-security-modules/spring-5-security/src/main/resources/static/css/main.css diff --git a/spring-5-security/src/main/resources/templates/index.html b/spring-security-modules/spring-5-security/src/main/resources/templates/index.html similarity index 100% rename from spring-5-security/src/main/resources/templates/index.html rename to spring-security-modules/spring-5-security/src/main/resources/templates/index.html diff --git a/spring-5-security/src/main/resources/templatesextrafields/index.html b/spring-security-modules/spring-5-security/src/main/resources/templatesextrafields/index.html similarity index 100% rename from spring-5-security/src/main/resources/templatesextrafields/index.html rename to spring-security-modules/spring-5-security/src/main/resources/templatesextrafields/index.html diff --git a/spring-5-security/src/main/resources/templatesextrafields/login.html b/spring-security-modules/spring-5-security/src/main/resources/templatesextrafields/login.html similarity index 100% rename from spring-5-security/src/main/resources/templatesextrafields/login.html rename to spring-security-modules/spring-5-security/src/main/resources/templatesextrafields/login.html diff --git a/spring-5-security/src/main/resources/templatesextrafields/user/index.html b/spring-security-modules/spring-5-security/src/main/resources/templatesextrafields/user/index.html similarity index 100% rename from spring-5-security/src/main/resources/templatesextrafields/user/index.html rename to spring-security-modules/spring-5-security/src/main/resources/templatesextrafields/user/index.html diff --git a/spring-5-security/src/test/java/com/baeldung/SpringContextTest.java b/spring-security-modules/spring-5-security/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-5-security/src/test/java/com/baeldung/SpringContextTest.java rename to spring-security-modules/spring-5-security/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-5-security/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java b/spring-security-modules/spring-5-security/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java similarity index 100% rename from spring-5-security/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java rename to spring-security-modules/spring-5-security/src/test/java/com/baeldung/authresolver/AuthResolverIntegrationTest.java diff --git a/spring-5-security/src/test/java/com/baeldung/inmemory/InMemoryAuthControllerIntegrationTest.java b/spring-security-modules/spring-5-security/src/test/java/com/baeldung/inmemory/InMemoryAuthControllerIntegrationTest.java similarity index 100% rename from spring-5-security/src/test/java/com/baeldung/inmemory/InMemoryAuthControllerIntegrationTest.java rename to spring-security-modules/spring-5-security/src/test/java/com/baeldung/inmemory/InMemoryAuthControllerIntegrationTest.java diff --git a/spring-5-security/src/test/java/com/baeldung/loginextrafields/AbstractExtraLoginFieldsIntegrationTest.java b/spring-security-modules/spring-5-security/src/test/java/com/baeldung/loginextrafields/AbstractExtraLoginFieldsIntegrationTest.java similarity index 100% rename from spring-5-security/src/test/java/com/baeldung/loginextrafields/AbstractExtraLoginFieldsIntegrationTest.java rename to spring-security-modules/spring-5-security/src/test/java/com/baeldung/loginextrafields/AbstractExtraLoginFieldsIntegrationTest.java diff --git a/spring-5-security/src/test/java/com/baeldung/loginextrafields/LoginFieldsFullIntegrationTest.java b/spring-security-modules/spring-5-security/src/test/java/com/baeldung/loginextrafields/LoginFieldsFullIntegrationTest.java similarity index 100% rename from spring-5-security/src/test/java/com/baeldung/loginextrafields/LoginFieldsFullIntegrationTest.java rename to spring-security-modules/spring-5-security/src/test/java/com/baeldung/loginextrafields/LoginFieldsFullIntegrationTest.java diff --git a/spring-5-security/src/test/java/com/baeldung/loginextrafields/LoginFieldsSimpleIntegrationTest.java b/spring-security-modules/spring-5-security/src/test/java/com/baeldung/loginextrafields/LoginFieldsSimpleIntegrationTest.java similarity index 100% rename from spring-5-security/src/test/java/com/baeldung/loginextrafields/LoginFieldsSimpleIntegrationTest.java rename to spring-security-modules/spring-5-security/src/test/java/com/baeldung/loginextrafields/LoginFieldsSimpleIntegrationTest.java diff --git a/spring-5-security/src/test/java/com/baeldung/logoutredirects/LogoutApplicationUnitTest.java b/spring-security-modules/spring-5-security/src/test/java/com/baeldung/logoutredirects/LogoutApplicationUnitTest.java similarity index 100% rename from spring-5-security/src/test/java/com/baeldung/logoutredirects/LogoutApplicationUnitTest.java rename to spring-security-modules/spring-5-security/src/test/java/com/baeldung/logoutredirects/LogoutApplicationUnitTest.java diff --git a/spring-5-security/src/test/java/com/baeldung/manuallogout/ManualLogoutIntegrationTest.java b/spring-security-modules/spring-5-security/src/test/java/com/baeldung/manuallogout/ManualLogoutIntegrationTest.java similarity index 100% rename from spring-5-security/src/test/java/com/baeldung/manuallogout/ManualLogoutIntegrationTest.java rename to spring-security-modules/spring-5-security/src/test/java/com/baeldung/manuallogout/ManualLogoutIntegrationTest.java diff --git a/spring-security-modules/spring-5-security/src/test/java/com/baeldung/xss/PersonControllerUnitTest.java b/spring-security-modules/spring-5-security/src/test/java/com/baeldung/xss/PersonControllerUnitTest.java new file mode 100644 index 0000000000..4e278ebf16 --- /dev/null +++ b/spring-security-modules/spring-5-security/src/test/java/com/baeldung/xss/PersonControllerUnitTest.java @@ -0,0 +1,64 @@ +package com.baeldung.xss; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.http.*; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; +import java.io.IOException; +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +class PersonControllerUnitTest { + + @LocalServerPort + int randomServerPort; + + @Test + public void givenRequestIsSuspicious_whenRequestIsPost_thenResponseIsClean() + throws IOException { + // given + String createPersonUrl; + RestTemplate restTemplate; + HttpHeaders headers; + UriComponentsBuilder builder; + ObjectMapper objectMapper = new ObjectMapper(); + ObjectNode personJsonObject = JsonNodeFactory.instance.objectNode(); + createPersonUrl = "http://localhost:" + randomServerPort + "/personService/person"; + restTemplate = new RestTemplate(); + headers = new HttpHeaders(); + + // when + personJsonObject.put("id", 1); + personJsonObject.put("firstName", "baeldung "); + personJsonObject.put("lastName", "baeldung click me!"); + + builder = UriComponentsBuilder.fromHttpUrl(createPersonUrl) + .queryParam("param", ""); + headers.add("header_4", "

Your search for 'flowers '"); + HttpEntity request = new HttpEntity<>(personJsonObject.toString(), headers); + + ResponseEntity personResultAsJsonStr = restTemplate.exchange(builder.toUriString(), + HttpMethod.POST, request, String.class); + JsonNode root = objectMapper.readTree(personResultAsJsonStr.getBody()); + + // then + assertThat(root.get("firstName").textValue()).isEqualTo("baeldung "); + assertThat(root.get("lastName").textValue()).isEqualTo("baeldung click me!"); + assertThat(root.get("param").textValue()).isEmpty(); + assertThat(root.get("header_1").textValue()).isEmpty(); + assertThat(root.get("header_2").textValue()).isEmpty(); + assertThat(root.get("header_3").textValue()).isEmpty(); + assertThat(root.get("header_4").textValue()).isEqualTo("Your search for 'flowers '"); + } +} diff --git a/persistence-modules/spring-hibernate4/src/test/resources/.gitignore b/spring-security-modules/spring-ldap/.gitignore similarity index 100% rename from persistence-modules/spring-hibernate4/src/test/resources/.gitignore rename to spring-security-modules/spring-ldap/.gitignore diff --git a/spring-ldap/README.md b/spring-security-modules/spring-ldap/README.md similarity index 100% rename from spring-ldap/README.md rename to spring-security-modules/spring-ldap/README.md diff --git a/spring-ldap/pom.xml b/spring-security-modules/spring-ldap/pom.xml similarity index 98% rename from spring-ldap/pom.xml rename to spring-security-modules/spring-ldap/pom.xml index a9882ccb52..60da7d4c0d 100644 --- a/spring-ldap/pom.xml +++ b/spring-security-modules/spring-ldap/pom.xml @@ -9,8 +9,8 @@ com.baeldung - parent-modules - 1.0.0-SNAPSHOT + spring-security-modules + 0.0.1-SNAPSHOT diff --git a/spring-ldap/src/main/java/com/baeldung/ldap/client/LdapClient.java b/spring-security-modules/spring-ldap/src/main/java/com/baeldung/ldap/client/LdapClient.java similarity index 100% rename from spring-ldap/src/main/java/com/baeldung/ldap/client/LdapClient.java rename to spring-security-modules/spring-ldap/src/main/java/com/baeldung/ldap/client/LdapClient.java diff --git a/spring-ldap/src/main/java/com/baeldung/ldap/data/repository/User.java b/spring-security-modules/spring-ldap/src/main/java/com/baeldung/ldap/data/repository/User.java similarity index 100% rename from spring-ldap/src/main/java/com/baeldung/ldap/data/repository/User.java rename to spring-security-modules/spring-ldap/src/main/java/com/baeldung/ldap/data/repository/User.java diff --git a/spring-ldap/src/main/java/com/baeldung/ldap/data/repository/UserRepository.java b/spring-security-modules/spring-ldap/src/main/java/com/baeldung/ldap/data/repository/UserRepository.java similarity index 100% rename from spring-ldap/src/main/java/com/baeldung/ldap/data/repository/UserRepository.java rename to spring-security-modules/spring-ldap/src/main/java/com/baeldung/ldap/data/repository/UserRepository.java diff --git a/spring-ldap/src/main/java/com/baeldung/ldap/data/service/LdapClient.java b/spring-security-modules/spring-ldap/src/main/java/com/baeldung/ldap/data/service/LdapClient.java similarity index 100% rename from spring-ldap/src/main/java/com/baeldung/ldap/data/service/LdapClient.java rename to spring-security-modules/spring-ldap/src/main/java/com/baeldung/ldap/data/service/LdapClient.java diff --git a/spring-ldap/src/main/java/com/baeldung/ldap/data/service/UserService.java b/spring-security-modules/spring-ldap/src/main/java/com/baeldung/ldap/data/service/UserService.java similarity index 100% rename from spring-ldap/src/main/java/com/baeldung/ldap/data/service/UserService.java rename to spring-security-modules/spring-ldap/src/main/java/com/baeldung/ldap/data/service/UserService.java diff --git a/spring-ldap/src/main/java/com/baeldung/ldap/javaconfig/AppConfig.java b/spring-security-modules/spring-ldap/src/main/java/com/baeldung/ldap/javaconfig/AppConfig.java similarity index 100% rename from spring-ldap/src/main/java/com/baeldung/ldap/javaconfig/AppConfig.java rename to spring-security-modules/spring-ldap/src/main/java/com/baeldung/ldap/javaconfig/AppConfig.java diff --git a/spring-ldap/src/main/resources/application.properties b/spring-security-modules/spring-ldap/src/main/resources/application.properties similarity index 100% rename from spring-ldap/src/main/resources/application.properties rename to spring-security-modules/spring-ldap/src/main/resources/application.properties diff --git a/spring-ldap/src/main/resources/logback.xml b/spring-security-modules/spring-ldap/src/main/resources/logback.xml similarity index 100% rename from spring-ldap/src/main/resources/logback.xml rename to spring-security-modules/spring-ldap/src/main/resources/logback.xml diff --git a/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapClientLiveTest.java b/spring-security-modules/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapClientLiveTest.java similarity index 100% rename from spring-ldap/src/test/java/com/baeldung/ldap/client/LdapClientLiveTest.java rename to spring-security-modules/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapClientLiveTest.java diff --git a/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapDataRepositoryIntegrationTest.java b/spring-security-modules/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapDataRepositoryIntegrationTest.java similarity index 100% rename from spring-ldap/src/test/java/com/baeldung/ldap/client/LdapDataRepositoryIntegrationTest.java rename to spring-security-modules/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapDataRepositoryIntegrationTest.java diff --git a/spring-ldap/src/test/java/com/baeldung/ldap/javaconfig/TestConfig.java b/spring-security-modules/spring-ldap/src/test/java/com/baeldung/ldap/javaconfig/TestConfig.java similarity index 100% rename from spring-ldap/src/test/java/com/baeldung/ldap/javaconfig/TestConfig.java rename to spring-security-modules/spring-ldap/src/test/java/com/baeldung/ldap/javaconfig/TestConfig.java diff --git a/spring-ldap/src/test/java/org/baeldung/SpringContextTest.java b/spring-security-modules/spring-ldap/src/test/java/org/baeldung/SpringContextTest.java similarity index 100% rename from spring-ldap/src/test/java/org/baeldung/SpringContextTest.java rename to spring-security-modules/spring-ldap/src/test/java/org/baeldung/SpringContextTest.java diff --git a/spring-ldap/src/test/resources/test.ldif b/spring-security-modules/spring-ldap/src/test/resources/test.ldif similarity index 100% rename from spring-ldap/src/test/resources/test.ldif rename to spring-security-modules/spring-ldap/src/test/resources/test.ldif diff --git a/spring-ldap/src/test/resources/test_application.properties b/spring-security-modules/spring-ldap/src/test/resources/test_application.properties similarity index 100% rename from spring-ldap/src/test/resources/test_application.properties rename to spring-security-modules/spring-ldap/src/test/resources/test_application.properties diff --git a/spring-security-modules/spring-security-kotlin-dsl/README.md b/spring-security-modules/spring-security-kotlin-dsl/README.md deleted file mode 100644 index 39e521d84e..0000000000 --- a/spring-security-modules/spring-security-kotlin-dsl/README.md +++ /dev/null @@ -1,3 +0,0 @@ -### Relevant Articles: - -- [Spring Security with Kotlin DSL](https://www.baeldung.com/kotlin/spring-security-dsl) diff --git a/spring-security-modules/spring-security-kotlin-dsl/pom.xml b/spring-security-modules/spring-security-kotlin-dsl/pom.xml deleted file mode 100644 index 24e99decfb..0000000000 --- a/spring-security-modules/spring-security-kotlin-dsl/pom.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - 4.0.0 - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../../parent-boot-2 - - - com.baeldung.spring.security.dsl - spring-security-kotlin-dsl - 1.0 - spring-security-kotlin-dsl - Spring Security Kotlin DSL - - - - org.springframework.boot - spring-boot-starter-security - - - org.springframework.boot - spring-boot-starter-web - - - com.fasterxml.jackson.module - jackson-module-kotlin - - - org.jetbrains.kotlin - kotlin-reflect - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - - - - org.projectlombok - lombok - true - - - org.springframework.boot - spring-boot-starter-test - test - - - - - ${project.basedir}/src/main/kotlin - ${project.basedir}/src/test/kotlin - - - org.springframework.boot - spring-boot-maven-plugin - - - org.jetbrains.kotlin - kotlin-maven-plugin - - - -Xjsr305=strict - - - spring - - - - - org.jetbrains.kotlin - kotlin-maven-allopen - ${kotlin.version} - - - - - - - - 11 - 1.3.72 - - - diff --git a/spring-security-modules/spring-security-kotlin-dsl/src/main/kotlin/com/baeldung/security/kotlin/dsl/SpringSecurityKotlinApplication.kt b/spring-security-modules/spring-security-kotlin-dsl/src/main/kotlin/com/baeldung/security/kotlin/dsl/SpringSecurityKotlinApplication.kt deleted file mode 100644 index 27cc41c1e5..0000000000 --- a/spring-security-modules/spring-security-kotlin-dsl/src/main/kotlin/com/baeldung/security/kotlin/dsl/SpringSecurityKotlinApplication.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.baeldung.security.kotlin.dsl - -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication -import org.springframework.context.annotation.Configuration -import org.springframework.context.support.beans -import org.springframework.core.annotation.Order -import org.springframework.security.config.annotation.web.builders.HttpSecurity -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter -import org.springframework.security.config.web.servlet.invoke -import org.springframework.security.core.userdetails.User -import org.springframework.security.provisioning.InMemoryUserDetailsManager -import org.springframework.web.servlet.function.ServerResponse -import org.springframework.web.servlet.function.router - -@EnableWebSecurity -@SpringBootApplication -class SpringSecurityKotlinApplication - -@Order(1) -@Configuration -class AdminSecurityConfiguration : WebSecurityConfigurerAdapter() { - override fun configure(http: HttpSecurity?) { - http { - authorizeRequests { - authorize("/greetings/**", hasAuthority("ROLE_ADMIN")) - } - httpBasic {} - } - } -} - -@Configuration -class BasicSecurityConfiguration : WebSecurityConfigurerAdapter() { - override fun configure(http: HttpSecurity?) { - http { - authorizeRequests { - authorize("/**", permitAll) - } - httpBasic {} - } - } -} - -fun main(args: Array) { - runApplication(*args) { - addInitializers( beans { - bean { - fun user(user: String, password: String, vararg roles: String) = - User - .withDefaultPasswordEncoder() - .username(user) - .password(password) - .roles(*roles) - .build() - - InMemoryUserDetailsManager(user("user", "password", "USER") - , user("admin", "password", "USER", "ADMIN")) - } - - bean { - router { - GET("/greetings") { - request -> request.principal().map { it.name }.map { ServerResponse.ok().body(mapOf("greeting" to "Hello $it")) }.orElseGet { ServerResponse.badRequest().build() } - } - } - } - }) - } -} diff --git a/spring-security-modules/spring-security-kotlin-dsl/src/test/kotlin/com/spring/security/kotlin/dsl/SpringSecurityKotlinApplicationTests.kt b/spring-security-modules/spring-security-kotlin-dsl/src/test/kotlin/com/spring/security/kotlin/dsl/SpringSecurityKotlinApplicationTests.kt deleted file mode 100644 index 3da8110feb..0000000000 --- a/spring-security-modules/spring-security-kotlin-dsl/src/test/kotlin/com/spring/security/kotlin/dsl/SpringSecurityKotlinApplicationTests.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.spring.security.kotlin.dsl - -import org.junit.jupiter.api.Test -import org.junit.runner.RunWith -import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc -import org.springframework.boot.test.context.SpringBootTest -import org.springframework.security.test.context.support.WithMockUser -import org.springframework.test.context.junit4.SpringRunner -import org.springframework.test.web.servlet.MockMvc -import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.* -import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user -import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic -import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated -import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated -import org.springframework.test.web.servlet.get -import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.* -import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status - -@RunWith(SpringRunner::class) -@SpringBootTest -@AutoConfigureMockMvc -class SpringSecurityKotlinApplicationTests { - - @Autowired - private lateinit var mockMvc: MockMvc - - @Test - fun `ordinary user not permitted to access the endpoint`() { - this.mockMvc - .perform(get("/greetings") - .with(httpBasic("user", "password"))) - .andExpect(unauthenticated()) - } -} diff --git a/spring-security-modules/spring-security-legacy-oidc/README.md b/spring-security-modules/spring-security-legacy-oidc/README.md new file mode 100644 index 0000000000..9d47b35b21 --- /dev/null +++ b/spring-security-modules/spring-security-legacy-oidc/README.md @@ -0,0 +1,23 @@ +## Spring Security OpenID + +This module contains articles about OpenID with Spring Security + +### Relevant articles + +- [Spring Security and OpenID Connect (Legacy)](https://www.baeldung.com/spring-security-openid-connect-legacy) + +### OpenID Connect with Spring Security + +### Run the Project + +``` +mvn spring-boot:run +``` + +### Obtain Google App - Client ID, Secret + +- We need to get client id and client secret by creating a new project at [Google Developer Console](https://console.developers.google.com/project/_/apiui/credential?pli=1) +- We can follow these instructions to register our client application on their platform + +- Once we have the client id and secret, we have to make sure we add them to the application.properties file. + diff --git a/spring-security-modules/spring-security-legacy-oidc/pom.xml b/spring-security-modules/spring-security-legacy-oidc/pom.xml new file mode 100644 index 0000000000..a4ead0f6e0 --- /dev/null +++ b/spring-security-modules/spring-security-legacy-oidc/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + spring-security-legacy-oidc + spring-security-legacy-oidc + war + Spring OpenID Connect sample project + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-tomcat + + + + org.springframework.security.oauth + spring-security-oauth2 + ${spring-security-oauth2.version} + + + + org.springframework.security + spring-security-jwt + ${spring-security-jwt.version} + + + + com.auth0 + jwks-rsa + ${jwks-rsa.version} + + + + + 2.2.1.RELEASE + 1.0.9.RELEASE + 0.3.0 + + + diff --git a/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/GoogleOpenIdConnectConfig.java b/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/GoogleOpenIdConnectConfig.java new file mode 100644 index 0000000000..a9fdcfb286 --- /dev/null +++ b/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/GoogleOpenIdConnectConfig.java @@ -0,0 +1,51 @@ +package com.baeldung.openid.oidc; + +import java.util.Arrays; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.oauth2.client.OAuth2ClientContext; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; + +@Configuration +@EnableOAuth2Client +public class GoogleOpenIdConnectConfig { + @Value("${google.clientId}") + private String clientId; + + @Value("${google.clientSecret}") + private String clientSecret; + + @Value("${google.accessTokenUri}") + private String accessTokenUri; + + @Value("${google.userAuthorizationUri}") + private String userAuthorizationUri; + + @Value("${google.redirectUri}") + private String redirectUri; + + @Bean + public OAuth2ProtectedResourceDetails googleOpenId() { + final AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); + details.setClientId(clientId); + details.setClientSecret(clientSecret); + details.setAccessTokenUri(accessTokenUri); + details.setUserAuthorizationUri(userAuthorizationUri); + details.setScope(Arrays.asList("openid", "email")); + details.setPreEstablishedRedirectUri(redirectUri); + details.setUseCurrentUri(false); + return details; + } + + @Bean + public OAuth2RestTemplate googleOpenIdTemplate(final OAuth2ClientContext clientContext) { + final OAuth2RestTemplate template = new OAuth2RestTemplate(googleOpenId(), clientContext); + return template; + } + +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/HomeController.java b/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/HomeController.java new file mode 100644 index 0000000000..3d2e776eca --- /dev/null +++ b/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/HomeController.java @@ -0,0 +1,22 @@ +package com.baeldung.openid.oidc; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +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.ResponseBody; + +@Controller +public class HomeController { + private final Logger logger = LoggerFactory.getLogger(getClass()); + + @RequestMapping("/") + @ResponseBody + public final String home() { + final String username = SecurityContextHolder.getContext().getAuthentication().getName(); + logger.info(username); + return "Welcome, " + username; + } + +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/OpenIdConnectFilter.java b/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/OpenIdConnectFilter.java new file mode 100644 index 0000000000..c0b08bc548 --- /dev/null +++ b/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/OpenIdConnectFilter.java @@ -0,0 +1,103 @@ +package com.baeldung.openid.oidc; + +import java.io.IOException; +import java.net.URL; +import java.security.interfaces.RSAPublicKey; +import java.util.Date; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.AuthenticationManager; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.jwt.Jwt; +import org.springframework.security.jwt.JwtHelper; +import org.springframework.security.jwt.crypto.sign.RsaVerifier; +import org.springframework.security.oauth2.client.OAuth2RestOperations; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.common.OAuth2AccessToken; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; + +import com.auth0.jwk.Jwk; +import com.auth0.jwk.JwkProvider; +import com.auth0.jwk.UrlJwkProvider; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class OpenIdConnectFilter extends AbstractAuthenticationProcessingFilter { + @Value("${google.clientId}") + private String clientId; + + @Value("${google.issuer}") + private String issuer; + + @Value("${google.jwkUrl}") + private String jwkUrl; + + public OAuth2RestOperations restTemplate; + + public OpenIdConnectFilter(String defaultFilterProcessesUrl) { + super(defaultFilterProcessesUrl); + setAuthenticationManager(new NoopAuthenticationManager()); + } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { + + OAuth2AccessToken accessToken; + try { + accessToken = restTemplate.getAccessToken(); + } catch (final OAuth2Exception e) { + throw new BadCredentialsException("Could not obtain access token", e); + } + try { + final String idToken = accessToken.getAdditionalInformation().get("id_token").toString(); + String kid = JwtHelper.headers(idToken) + .get("kid"); + final Jwt tokenDecoded = JwtHelper.decodeAndVerify(idToken, verifier(kid)); + final Map authInfo = new ObjectMapper().readValue(tokenDecoded.getClaims(), Map.class); + verifyClaims(authInfo); + final OpenIdConnectUserDetails user = new OpenIdConnectUserDetails(authInfo, accessToken); + return new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); + } catch (final Exception e) { + throw new BadCredentialsException("Could not obtain user details from token", e); + } + + } + + public void verifyClaims(Map claims) { + int exp = (int) claims.get("exp"); + Date expireDate = new Date(exp * 1000L); + Date now = new Date(); + if (expireDate.before(now) || !claims.get("iss").equals(issuer) || !claims.get("aud").equals(clientId)) { + throw new RuntimeException("Invalid claims"); + } + } + + + private RsaVerifier verifier(String kid) throws Exception { + JwkProvider provider = new UrlJwkProvider(new URL(jwkUrl)); + Jwk jwk = provider.get(kid); + return new RsaVerifier((RSAPublicKey) jwk.getPublicKey()); + } + + public void setRestTemplate(OAuth2RestTemplate restTemplate2) { + restTemplate = restTemplate2; + + } + + private static class NoopAuthenticationManager implements AuthenticationManager { + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + throw new UnsupportedOperationException("No authentication should be done with this AuthenticationManager"); + } + + } +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/OpenIdConnectUserDetails.java b/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/OpenIdConnectUserDetails.java new file mode 100644 index 0000000000..4ff61bcad9 --- /dev/null +++ b/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/OpenIdConnectUserDetails.java @@ -0,0 +1,81 @@ +package com.baeldung.openid.oidc; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.oauth2.common.OAuth2AccessToken; + +public class OpenIdConnectUserDetails implements UserDetails { + + private static final long serialVersionUID = 1L; + + private String userId; + private String username; + private OAuth2AccessToken token; + + public OpenIdConnectUserDetails(Map userInfo, OAuth2AccessToken token) { + this.userId = userInfo.get("sub"); + this.username = userInfo.get("email"); + this.token = token; + } + + @Override + public String getUsername() { + return username; + } + + @Override + public Collection getAuthorities() { + return Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")); + } + + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + public OAuth2AccessToken getToken() { + return token; + } + + public void setToken(OAuth2AccessToken token) { + this.token = token; + } + + public void setUsername(String username) { + this.username = username; + } + + @Override + public String getPassword() { + return null; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/SecurityConfig.java b/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/SecurityConfig.java new file mode 100644 index 0000000000..fc5397a35b --- /dev/null +++ b/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/SecurityConfig.java @@ -0,0 +1,48 @@ +package com.baeldung.openid.oidc; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; +import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; +import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; + +@Configuration +@EnableWebSecurity +public class SecurityConfig extends WebSecurityConfigurerAdapter { + @Autowired + private OAuth2RestTemplate restTemplate; + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Bean + public OpenIdConnectFilter myFilter() { + final OpenIdConnectFilter filter = new OpenIdConnectFilter("/google-login"); + filter.setRestTemplate(restTemplate); + return filter; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http + .addFilterAfter(new OAuth2ClientContextFilter(), AbstractPreAuthenticatedProcessingFilter.class) + .addFilterAfter(myFilter(), OAuth2ClientContextFilter.class) + .httpBasic().authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/google-login")) + .and() + .authorizeRequests() + // .antMatchers("/","/index*").permitAll() + .anyRequest().authenticated() + ; + + // @formatter:on + } +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/SpringOpenidApplication.java b/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/SpringOpenidApplication.java new file mode 100644 index 0000000000..ec686f746d --- /dev/null +++ b/spring-security-modules/spring-security-legacy-oidc/src/main/java/com/baeldung/openid/oidc/SpringOpenidApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.openid.oidc; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; + +@SpringBootApplication +public class SpringOpenidApplication extends SpringBootServletInitializer { + + public static void main(String[] args) { + SpringApplication.run(SpringOpenidApplication.class, args); + } + +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-legacy-oidc/src/main/resources/application.properties b/spring-security-modules/spring-security-legacy-oidc/src/main/resources/application.properties new file mode 100644 index 0000000000..e9ae90dd10 --- /dev/null +++ b/spring-security-modules/spring-security-legacy-oidc/src/main/resources/application.properties @@ -0,0 +1,8 @@ +server.port=8081 +google.clientId=475873350264-g1opb20lf2fc60h0o84rrkn972krgkvo.apps.googleusercontent.com +google.clientSecret=GiA1Agf_aSt-bhTrnXjre-5Z +google.accessTokenUri=https://www.googleapis.com/oauth2/v3/token +google.userAuthorizationUri=https://accounts.google.com/o/oauth2/auth +google.redirectUri=http://localhost:8081/google-login +google.issuer=accounts.google.com +google.jwkUrl=https://www.googleapis.com/oauth2/v2/certs \ No newline at end of file diff --git a/spring-social-login/src/main/resources/logback.xml b/spring-security-modules/spring-security-legacy-oidc/src/main/resources/logback.xml similarity index 95% rename from spring-social-login/src/main/resources/logback.xml rename to spring-security-modules/spring-security-legacy-oidc/src/main/resources/logback.xml index 7d900d8ea8..3b8d0b9964 100644 --- a/spring-social-login/src/main/resources/logback.xml +++ b/spring-security-modules/spring-security-legacy-oidc/src/main/resources/logback.xml @@ -10,4 +10,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/spring-kafka/src/test/java/com/baeldung/SpringContextManualTest.java b/spring-security-modules/spring-security-legacy-oidc/src/test/java/com/baeldung/openid/oidc/SpringContextTest.java similarity index 64% rename from spring-kafka/src/test/java/com/baeldung/SpringContextManualTest.java rename to spring-security-modules/spring-security-legacy-oidc/src/test/java/com/baeldung/openid/oidc/SpringContextTest.java index 0d2c19136f..0a21c5e93f 100644 --- a/spring-kafka/src/test/java/com/baeldung/SpringContextManualTest.java +++ b/spring-security-modules/spring-security-legacy-oidc/src/test/java/com/baeldung/openid/oidc/SpringContextTest.java @@ -1,17 +1,15 @@ -package com.baeldung; +package com.baeldung.openid.oidc; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.spring.kafka.KafkaApplication; - @RunWith(SpringRunner.class) -@SpringBootTest(classes = KafkaApplication.class) -public class SpringContextManualTest { +@SpringBootTest(classes = SpringOpenidApplication.class) +public class SpringContextTest { @Test public void whenSpringContextIsBootstrapped_thenNoExceptions() { } -} +} \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-sso/pom.xml b/spring-security-modules/spring-security-oauth2-sso/pom.xml index ed4b1d64ba..a272ba5b50 100644 --- a/spring-security-modules/spring-security-oauth2-sso/pom.xml +++ b/spring-security-modules/spring-security-oauth2-sso/pom.xml @@ -24,8 +24,8 @@ 3.1.0 - 2.3.3.RELEASE - 2.1.1.RELEASE + 2.4.0.RELEASE + 2.4.0 1.0.1.RELEASE 2.0.0-M2 diff --git a/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-auth-server/pom.xml b/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-auth-server/pom.xml index 3537c01e46..20a43eaf04 100644 --- a/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-auth-server/pom.xml +++ b/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-auth-server/pom.xml @@ -8,7 +8,7 @@ com.baeldung - spring-security-sso + spring-security-oauth2-sso 1.0.0-SNAPSHOT diff --git a/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-kerberos/pom.xml b/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-kerberos/pom.xml index a67cc4af83..f17ca171a5 100644 --- a/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-kerberos/pom.xml +++ b/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-kerberos/pom.xml @@ -7,7 +7,7 @@ com.baeldung - spring-security-sso + spring-security-oauth2-sso 1.0.0-SNAPSHOT @@ -91,5 +91,9 @@ + + + com.baeldung.intro.Application + \ No newline at end of file diff --git a/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui-2/pom.xml b/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui-2/pom.xml index 0645ba3593..514dd0d0f7 100644 --- a/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui-2/pom.xml +++ b/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui-2/pom.xml @@ -8,7 +8,7 @@ com.baeldung - spring-security-sso + spring-security-oauth2-sso 1.0.0-SNAPSHOT diff --git a/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui-2/src/main/resources/application.yml b/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui-2/src/main/resources/application.yml index 97c8de7839..8cee9f24d5 100644 --- a/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui-2/src/main/resources/application.yml +++ b/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui-2/src/main/resources/application.yml @@ -2,6 +2,7 @@ server: port: 8083 servlet: context-path: /ui2 + register-default-servlet: true session: cookie: name: UI2SESSION diff --git a/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui/pom.xml b/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui/pom.xml index d34317a4b0..5076b1878b 100644 --- a/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui/pom.xml +++ b/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui/pom.xml @@ -8,7 +8,7 @@ com.baeldung - spring-security-sso + spring-security-oauth2-sso 1.0.0-SNAPSHOT diff --git a/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui/src/main/resources/application.yml b/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui/src/main/resources/application.yml index d1d9ea6ebc..f98dee9429 100644 --- a/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui/src/main/resources/application.yml +++ b/spring-security-modules/spring-security-oauth2-sso/spring-security-sso-ui/src/main/resources/application.yml @@ -2,6 +2,7 @@ server: port: 8082 servlet: context-path: /ui + register-default-servlet: true session: cookie: name: UISESSION diff --git a/spring-security-modules/spring-security-oidc/README.md b/spring-security-modules/spring-security-oidc/README.md index ca6053f70f..92ba60cad9 100644 --- a/spring-security-modules/spring-security-oidc/README.md +++ b/spring-security-modules/spring-security-oidc/README.md @@ -5,7 +5,6 @@ This module contains articles about OpenID with Spring Security ### Relevant articles - [Spring Security and OpenID Connect](https://www.baeldung.com/spring-security-openid-connect) -- [Spring Security and OpenID Connect (Legacy)](https://www.baeldung.com/spring-security-openid-connect-legacy) ### OpenID Connect with Spring Security diff --git a/spring-security-modules/spring-security-web-boot-2/src/main/java/com/baeldung/loginredirect/LoginPageInterceptor.java b/spring-security-modules/spring-security-web-boot-2/src/main/java/com/baeldung/loginredirect/LoginPageInterceptor.java index aa93201f37..f08b824369 100644 --- a/spring-security-modules/spring-security-web-boot-2/src/main/java/com/baeldung/loginredirect/LoginPageInterceptor.java +++ b/spring-security-modules/spring-security-web-boot-2/src/main/java/com/baeldung/loginredirect/LoginPageInterceptor.java @@ -1,16 +1,16 @@ package com.baeldung.loginredirect; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import org.apache.http.HttpStatus; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; +import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.util.UrlPathHelper; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -class LoginPageInterceptor extends HandlerInterceptorAdapter { +class LoginPageInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { diff --git a/spring-security-modules/spring-security-web-login/README.md b/spring-security-modules/spring-security-web-login/README.md index 5d92a8e1b4..9521a430c2 100644 --- a/spring-security-modules/spring-security-web-login/README.md +++ b/spring-security-modules/spring-security-web-login/README.md @@ -8,7 +8,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Articles: - [Spring Security Form Login](https://www.baeldung.com/spring-security-login) - [Spring Security Logout](https://www.baeldung.com/spring-security-logout) -- [Spring Security Expressions – hasRole Example](https://www.baeldung.com/spring-security-expressions-basic) - [Spring HTTP/HTTPS Channel Security](https://www.baeldung.com/spring-channel-security-https) - [Spring Security – Customize the 403 Forbidden/Access Denied Page](https://www.baeldung.com/spring-security-custom-access-denied-page) - [Spring Security – Redirect to the Previous URL After Login](https://www.baeldung.com/spring-security-redirect-login) diff --git a/spring-security-modules/spring-security-web-mvc/pom.xml b/spring-security-modules/spring-security-web-mvc/pom.xml index 2651b3a0f2..b1e94b2db3 100644 --- a/spring-security-modules/spring-security-web-mvc/pom.xml +++ b/spring-security-modules/spring-security-web-mvc/pom.xml @@ -61,27 +61,6 @@ spring-boot-starter-test test - - org.springframework.security - spring-security-test - ${spring.mvc.version} - test - - - org.springframework.security - spring-security-web - ${spring.mvc.version} - - - org.springframework.security - spring-security-config - ${spring.mvc.version} - - - org.springframework - spring-webmvc - ${spring.mvc.version} - javax.servlet javax.servlet-api @@ -104,7 +83,6 @@ - 5.2.2.RELEASE 4.0.1 diff --git a/spring-security-modules/spring-security-web-rest/README.md b/spring-security-modules/spring-security-web-rest/README.md index c13668798d..fd1f86f6b8 100644 --- a/spring-security-modules/spring-security-web-rest/README.md +++ b/spring-security-modules/spring-security-web-rest/README.md @@ -14,5 +14,4 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [Spring Security Context Propagation with @Async](https://www.baeldung.com/spring-security-async-principal-propagation) - [Servlet 3 Async Support with Spring MVC and Spring Security](https://www.baeldung.com/spring-mvc-async-security) - [Intro to Spring Security Expressions](https://www.baeldung.com/spring-security-expressions) -- [Spring Security Expressions - hasRole Example](https://www.baeldung.com/spring-security-expressions-basic) - [Error Handling for REST with Spring](https://www.baeldung.com/exception-handling-for-rest-with-spring) diff --git a/spring-security-modules/spring-security-web-rest/pom.xml b/spring-security-modules/spring-security-web-rest/pom.xml index d2468152da..2330243aa6 100644 --- a/spring-security-modules/spring-security-web-rest/pom.xml +++ b/spring-security-modules/spring-security-web-rest/pom.xml @@ -168,7 +168,6 @@ ${springfox-swagger.version} - commons-fileupload commons-fileupload @@ -271,7 +270,6 @@ 26.0-jre - 1.3.2 2.9.0 diff --git a/spring-security-modules/spring-security-web-rest/src/main/java/com/baeldung/security/SecurityJavaConfig.java b/spring-security-modules/spring-security-web-rest/src/main/java/com/baeldung/security/SecurityJavaConfig.java index d20198c2bb..7f0b20ea34 100644 --- a/spring-security-modules/spring-security-web-rest/src/main/java/com/baeldung/security/SecurityJavaConfig.java +++ b/spring-security-modules/spring-security-web-rest/src/main/java/com/baeldung/security/SecurityJavaConfig.java @@ -7,14 +7,15 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.task.DelegatingSecurityContextAsyncTaskExecutor; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; @Configuration @@ -34,11 +35,6 @@ public class SecurityJavaConfig extends WebSecurityConfigurerAdapter { private SimpleUrlAuthenticationFailureHandler myFailureHandler = new SimpleUrlAuthenticationFailureHandler(); - public SecurityJavaConfig() { - super(); - SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL); - } - @Override protected void configure(final AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() @@ -77,4 +73,18 @@ public class SecurityJavaConfig extends WebSecurityConfigurerAdapter { return new BCryptPasswordEncoder(); } + @Bean + public ThreadPoolTaskExecutor threadPoolTaskExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + executor.setCorePoolSize(10); + executor.setMaxPoolSize(100); + executor.setQueueCapacity(50); + executor.setThreadNamePrefix("async-"); + return executor; + } + + @Bean + public DelegatingSecurityContextAsyncTaskExecutor taskExecutor(ThreadPoolTaskExecutor delegate) { + return new DelegatingSecurityContextAsyncTaskExecutor(delegate); + } } \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-sockets/README.md b/spring-security-modules/spring-security-web-sockets/README.md index 14ef0c8b99..76717e2fe6 100644 --- a/spring-security-modules/spring-security-web-sockets/README.md +++ b/spring-security-modules/spring-security-web-sockets/README.md @@ -5,7 +5,7 @@ This module contains articles about WebSockets with Spring Security ### Relevant Articles: - [Intro to Security and WebSockets](https://www.baeldung.com/spring-security-websockets) -- [Spring WebSockets: Build an User Chat](https://www.baeldung.com/spring-websockets-send-message-to-user) +- [Spring WebSockets: Send Messages to a Specific User](https://www.baeldung.com/spring-websockets-send-message-to-user) - [REST vs WebSockets](https://www.baeldung.com/rest-vs-websockets) ### Running This Project: diff --git a/spring-session/README.md b/spring-security-modules/spring-session/README.md similarity index 100% rename from spring-session/README.md rename to spring-security-modules/spring-session/README.md diff --git a/spring-session/pom.xml b/spring-security-modules/spring-session/pom.xml similarity index 93% rename from spring-session/pom.xml rename to spring-security-modules/spring-session/pom.xml index 6616a0d1f3..ac10700240 100644 --- a/spring-session/pom.xml +++ b/spring-security-modules/spring-session/pom.xml @@ -12,7 +12,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 diff --git a/spring-session/spring-session-jdbc/README.md b/spring-security-modules/spring-session/spring-session-jdbc/README.md similarity index 60% rename from spring-session/spring-session-jdbc/README.md rename to spring-security-modules/spring-session/spring-session-jdbc/README.md index a31ee044e8..6af3f53137 100644 --- a/spring-session/spring-session-jdbc/README.md +++ b/spring-security-modules/spring-session/spring-session-jdbc/README.md @@ -3,5 +3,3 @@ This module contains articles about Spring Session with JDBC. ### Relevant Articles: - -- [Spring Session with JDBC](https://www.baeldung.com/spring-session-jdbc) diff --git a/spring-session/spring-session-jdbc/pom.xml b/spring-security-modules/spring-session/spring-session-jdbc/pom.xml similarity index 95% rename from spring-session/spring-session-jdbc/pom.xml rename to spring-security-modules/spring-session/spring-session-jdbc/pom.xml index 64cdb4dd09..95c366fc2e 100644 --- a/spring-session/spring-session-jdbc/pom.xml +++ b/spring-security-modules/spring-session/spring-session-jdbc/pom.xml @@ -13,7 +13,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../../parent-boot-2 diff --git a/spring-session/spring-session-jdbc/src/main/java/com/baeldung/springsessionjdbc/SpringSessionJdbcApplication.java b/spring-security-modules/spring-session/spring-session-jdbc/src/main/java/com/baeldung/springsessionjdbc/SpringSessionJdbcApplication.java similarity index 100% rename from spring-session/spring-session-jdbc/src/main/java/com/baeldung/springsessionjdbc/SpringSessionJdbcApplication.java rename to spring-security-modules/spring-session/spring-session-jdbc/src/main/java/com/baeldung/springsessionjdbc/SpringSessionJdbcApplication.java diff --git a/spring-session/spring-session-jdbc/src/main/java/com/baeldung/springsessionjdbc/controller/SpringSessionJdbcController.java b/spring-security-modules/spring-session/spring-session-jdbc/src/main/java/com/baeldung/springsessionjdbc/controller/SpringSessionJdbcController.java similarity index 100% rename from spring-session/spring-session-jdbc/src/main/java/com/baeldung/springsessionjdbc/controller/SpringSessionJdbcController.java rename to spring-security-modules/spring-session/spring-session-jdbc/src/main/java/com/baeldung/springsessionjdbc/controller/SpringSessionJdbcController.java diff --git a/spring-session/spring-session-jdbc/src/main/resources/application.properties b/spring-security-modules/spring-session/spring-session-jdbc/src/main/resources/application.properties similarity index 100% rename from spring-session/spring-session-jdbc/src/main/resources/application.properties rename to spring-security-modules/spring-session/spring-session-jdbc/src/main/resources/application.properties diff --git a/spring-jooq/src/main/resources/logback.xml b/spring-security-modules/spring-session/spring-session-jdbc/src/main/resources/logback.xml similarity index 100% rename from spring-jooq/src/main/resources/logback.xml rename to spring-security-modules/spring-session/spring-session-jdbc/src/main/resources/logback.xml diff --git a/spring-session/spring-session-jdbc/src/test/java/com/baeldung/SpringContextTest.java b/spring-security-modules/spring-session/spring-session-jdbc/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-session/spring-session-jdbc/src/test/java/com/baeldung/SpringContextTest.java rename to spring-security-modules/spring-session/spring-session-jdbc/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-session/spring-session-jdbc/src/test/java/com/baeldung/springsessionjdbc/SpringSessionJdbcIntegrationTest.java b/spring-security-modules/spring-session/spring-session-jdbc/src/test/java/com/baeldung/springsessionjdbc/SpringSessionJdbcIntegrationTest.java similarity index 100% rename from spring-session/spring-session-jdbc/src/test/java/com/baeldung/springsessionjdbc/SpringSessionJdbcIntegrationTest.java rename to spring-security-modules/spring-session/spring-session-jdbc/src/test/java/com/baeldung/springsessionjdbc/SpringSessionJdbcIntegrationTest.java diff --git a/spring-session/spring-session-mongodb/README.md b/spring-security-modules/spring-session/spring-session-mongodb/README.md similarity index 100% rename from spring-session/spring-session-mongodb/README.md rename to spring-security-modules/spring-session/spring-session-mongodb/README.md diff --git a/spring-session/spring-session-mongodb/pom.xml b/spring-security-modules/spring-session/spring-session-mongodb/pom.xml similarity index 96% rename from spring-session/spring-session-mongodb/pom.xml rename to spring-security-modules/spring-session/spring-session-mongodb/pom.xml index 10d4eb595e..82c8520356 100644 --- a/spring-session/spring-session-mongodb/pom.xml +++ b/spring-security-modules/spring-session/spring-session-mongodb/pom.xml @@ -13,7 +13,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../../parent-boot-2 diff --git a/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBApplication.java b/spring-security-modules/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBApplication.java similarity index 100% rename from spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBApplication.java rename to spring-security-modules/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBApplication.java diff --git a/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/controller/SpringSessionMongoDBController.java b/spring-security-modules/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/controller/SpringSessionMongoDBController.java similarity index 100% rename from spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/controller/SpringSessionMongoDBController.java rename to spring-security-modules/spring-session/spring-session-mongodb/src/main/java/com/baeldung/springsessionmongodb/controller/SpringSessionMongoDBController.java diff --git a/spring-session/spring-session-mongodb/src/main/resources/application.properties b/spring-security-modules/spring-session/spring-session-mongodb/src/main/resources/application.properties similarity index 100% rename from spring-session/spring-session-mongodb/src/main/resources/application.properties rename to spring-security-modules/spring-session/spring-session-mongodb/src/main/resources/application.properties diff --git a/spring-mvc-basics-2/src/main/resources/logback.xml b/spring-security-modules/spring-session/spring-session-mongodb/src/main/resources/logback.xml similarity index 100% rename from spring-mvc-basics-2/src/main/resources/logback.xml rename to spring-security-modules/spring-session/spring-session-mongodb/src/main/resources/logback.xml diff --git a/spring-session/spring-session-mongodb/src/test/java/com/baeldung/SpringContextTest.java b/spring-security-modules/spring-session/spring-session-mongodb/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-session/spring-session-mongodb/src/test/java/com/baeldung/SpringContextTest.java rename to spring-security-modules/spring-session/spring-session-mongodb/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java b/spring-security-modules/spring-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java similarity index 100% rename from spring-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java rename to spring-security-modules/spring-session/spring-session-mongodb/src/test/java/com/baeldung/springsessionmongodb/SpringSessionMongoDBIntegrationTest.java diff --git a/spring-session/spring-session-mongodb/src/test/resources/application.properties b/spring-security-modules/spring-session/spring-session-mongodb/src/test/resources/application.properties similarity index 100% rename from spring-session/spring-session-mongodb/src/test/resources/application.properties rename to spring-security-modules/spring-session/spring-session-mongodb/src/test/resources/application.properties diff --git a/spring-session/spring-session-redis/README.md b/spring-security-modules/spring-session/spring-session-redis/README.md similarity index 100% rename from spring-session/spring-session-redis/README.md rename to spring-security-modules/spring-session/spring-session-redis/README.md diff --git a/spring-session/spring-session-redis/pom.xml b/spring-security-modules/spring-session/spring-session-redis/pom.xml similarity index 96% rename from spring-session/spring-session-redis/pom.xml rename to spring-security-modules/spring-session/spring-session-redis/pom.xml index 8d225e06ed..36eb632e1c 100644 --- a/spring-session/spring-session-redis/pom.xml +++ b/spring-security-modules/spring-session/spring-session-redis/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../../parent-boot-2 + ../../../parent-boot-2 diff --git a/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java b/spring-security-modules/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java similarity index 100% rename from spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java rename to spring-security-modules/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SecurityConfig.java diff --git a/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SessionController.java b/spring-security-modules/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SessionController.java similarity index 100% rename from spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SessionController.java rename to spring-security-modules/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SessionController.java diff --git a/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SessionWebApplication.java b/spring-security-modules/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SessionWebApplication.java similarity index 100% rename from spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SessionWebApplication.java rename to spring-security-modules/spring-session/spring-session-redis/src/main/java/com/baeldung/spring/session/SessionWebApplication.java diff --git a/spring-session/spring-session-redis/src/main/resources/application.properties b/spring-security-modules/spring-session/spring-session-redis/src/main/resources/application.properties similarity index 100% rename from spring-session/spring-session-redis/src/main/resources/application.properties rename to spring-security-modules/spring-session/spring-session-redis/src/main/resources/application.properties diff --git a/spring-mvc-basics-4/src/main/resources/logback.xml b/spring-security-modules/spring-session/spring-session-redis/src/main/resources/logback.xml similarity index 100% rename from spring-mvc-basics-4/src/main/resources/logback.xml rename to spring-security-modules/spring-session/spring-session-redis/src/main/resources/logback.xml diff --git a/spring-session/spring-session-redis/src/test/java/com/baeldung/SpringContextLiveTest.java b/spring-security-modules/spring-session/spring-session-redis/src/test/java/com/baeldung/SpringContextLiveTest.java similarity index 100% rename from spring-session/spring-session-redis/src/test/java/com/baeldung/SpringContextLiveTest.java rename to spring-security-modules/spring-session/spring-session-redis/src/test/java/com/baeldung/SpringContextLiveTest.java diff --git a/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java b/spring-security-modules/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java similarity index 100% rename from spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java rename to spring-security-modules/spring-session/spring-session-redis/src/test/java/com/baeldung/spring/session/SessionControllerIntegrationTest.java diff --git a/spring-social-login/README.md b/spring-security-modules/spring-social-login/README.md similarity index 100% rename from spring-social-login/README.md rename to spring-security-modules/spring-social-login/README.md diff --git a/spring-social-login/pom.xml b/spring-security-modules/spring-social-login/pom.xml similarity index 97% rename from spring-social-login/pom.xml rename to spring-security-modules/spring-social-login/pom.xml index 0de20cd087..209a546a5a 100644 --- a/spring-social-login/pom.xml +++ b/spring-security-modules/spring-social-login/pom.xml @@ -10,7 +10,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 diff --git a/spring-social-login/src/main/java/com/baeldung/config/Application.java b/spring-security-modules/spring-social-login/src/main/java/com/baeldung/config/Application.java similarity index 100% rename from spring-social-login/src/main/java/com/baeldung/config/Application.java rename to spring-security-modules/spring-social-login/src/main/java/com/baeldung/config/Application.java diff --git a/spring-social-login/src/main/java/com/baeldung/config/SecurityConfig.java b/spring-security-modules/spring-social-login/src/main/java/com/baeldung/config/SecurityConfig.java similarity index 100% rename from spring-social-login/src/main/java/com/baeldung/config/SecurityConfig.java rename to spring-security-modules/spring-social-login/src/main/java/com/baeldung/config/SecurityConfig.java diff --git a/spring-social-login/src/main/java/com/baeldung/config/WebConfig.java b/spring-security-modules/spring-social-login/src/main/java/com/baeldung/config/WebConfig.java similarity index 100% rename from spring-social-login/src/main/java/com/baeldung/config/WebConfig.java rename to spring-security-modules/spring-social-login/src/main/java/com/baeldung/config/WebConfig.java diff --git a/spring-social-login/src/main/java/com/baeldung/persistence/dao/UserRepository.java b/spring-security-modules/spring-social-login/src/main/java/com/baeldung/persistence/dao/UserRepository.java similarity index 100% rename from spring-social-login/src/main/java/com/baeldung/persistence/dao/UserRepository.java rename to spring-security-modules/spring-social-login/src/main/java/com/baeldung/persistence/dao/UserRepository.java diff --git a/spring-social-login/src/main/java/com/baeldung/persistence/model/User.java b/spring-security-modules/spring-social-login/src/main/java/com/baeldung/persistence/model/User.java similarity index 100% rename from spring-social-login/src/main/java/com/baeldung/persistence/model/User.java rename to spring-security-modules/spring-social-login/src/main/java/com/baeldung/persistence/model/User.java diff --git a/spring-social-login/src/main/java/com/baeldung/security/FacebookConnectionSignup.java b/spring-security-modules/spring-social-login/src/main/java/com/baeldung/security/FacebookConnectionSignup.java similarity index 100% rename from spring-social-login/src/main/java/com/baeldung/security/FacebookConnectionSignup.java rename to spring-security-modules/spring-social-login/src/main/java/com/baeldung/security/FacebookConnectionSignup.java diff --git a/spring-social-login/src/main/java/com/baeldung/security/FacebookSignInAdapter.java b/spring-security-modules/spring-social-login/src/main/java/com/baeldung/security/FacebookSignInAdapter.java similarity index 100% rename from spring-social-login/src/main/java/com/baeldung/security/FacebookSignInAdapter.java rename to spring-security-modules/spring-social-login/src/main/java/com/baeldung/security/FacebookSignInAdapter.java diff --git a/spring-social-login/src/main/java/com/baeldung/security/MyUserDetailsService.java b/spring-security-modules/spring-social-login/src/main/java/com/baeldung/security/MyUserDetailsService.java similarity index 100% rename from spring-social-login/src/main/java/com/baeldung/security/MyUserDetailsService.java rename to spring-security-modules/spring-social-login/src/main/java/com/baeldung/security/MyUserDetailsService.java diff --git a/spring-social-login/src/main/resources/application.properties b/spring-security-modules/spring-social-login/src/main/resources/application.properties similarity index 60% rename from spring-social-login/src/main/resources/application.properties rename to spring-security-modules/spring-social-login/src/main/resources/application.properties index 2bd99d8239..22e6acf9e2 100644 --- a/spring-social-login/src/main/resources/application.properties +++ b/spring-security-modules/spring-social-login/src/main/resources/application.properties @@ -1,3 +1,4 @@ spring.social.facebook.appId=1715784745414888 spring.social.facebook.appSecret=abefd6497e9cc01ad03be28509617bf0 -spring.thymeleaf.cache=false \ No newline at end of file +spring.thymeleaf.cache=false +server.servlet.register-default-servlet=true \ No newline at end of file diff --git a/spring-social-login/src/main/resources/data.sql b/spring-security-modules/spring-social-login/src/main/resources/data.sql similarity index 100% rename from spring-social-login/src/main/resources/data.sql rename to spring-security-modules/spring-social-login/src/main/resources/data.sql diff --git a/spring-mvc-forms-jsp/src/main/resources/logback.xml b/spring-security-modules/spring-social-login/src/main/resources/logback.xml similarity index 100% rename from spring-mvc-forms-jsp/src/main/resources/logback.xml rename to spring-security-modules/spring-social-login/src/main/resources/logback.xml diff --git a/spring-social-login/src/main/resources/templates/index.html b/spring-security-modules/spring-social-login/src/main/resources/templates/index.html similarity index 100% rename from spring-social-login/src/main/resources/templates/index.html rename to spring-security-modules/spring-social-login/src/main/resources/templates/index.html diff --git a/spring-social-login/src/main/resources/templates/login.html b/spring-security-modules/spring-social-login/src/main/resources/templates/login.html similarity index 100% rename from spring-social-login/src/main/resources/templates/login.html rename to spring-security-modules/spring-social-login/src/main/resources/templates/login.html diff --git a/spring-social-login/src/test/java/com/baeldung/SpringContextTest.java b/spring-security-modules/spring-social-login/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-social-login/src/test/java/com/baeldung/SpringContextTest.java rename to spring-security-modules/spring-social-login/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-session/spring-session-redis/src/main/resources/logback.xml b/spring-session/spring-session-redis/src/main/resources/logback.xml deleted file mode 100644 index 7d900d8ea8..0000000000 --- a/spring-session/spring-session-redis/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/spring-swagger-codegen/spring-openapi-generator-api-client/pom.xml b/spring-swagger-codegen/spring-openapi-generator-api-client/pom.xml index 7c6de543ae..3074849e4c 100644 --- a/spring-swagger-codegen/spring-openapi-generator-api-client/pom.xml +++ b/spring-swagger-codegen/spring-openapi-generator-api-client/pom.xml @@ -90,7 +90,7 @@ com.fasterxml.jackson.core jackson-databind - ${jackson-databind-version} + ${jackson-version} com.fasterxml.jackson.jaxrs @@ -264,8 +264,8 @@ 1.5.22 4.3.9.RELEASE - 2.10.1 - 2.10.1 + 2.11.1 + 0.2.1 2.9.10 1.0.0 diff --git a/spring-web-modules/pom.xml b/spring-web-modules/pom.xml new file mode 100644 index 0000000000..37ee84da25 --- /dev/null +++ b/spring-web-modules/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + spring-web-modules + 0.0.1-SNAPSHOT + spring-web-modules + pom + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + spring-5-mvc + spring-mvc-basics + spring-mvc-basics-2 + spring-mvc-basics-3 + spring-mvc-basics-4 + spring-mvc-crash + spring-mvc-forms-jsp + spring-mvc-forms-thymeleaf + spring-mvc-java + spring-mvc-java-2 + spring-mvc-velocity + spring-mvc-views + spring-mvc-webflow + spring-mvc-xml + spring-rest-angular + spring-rest-http + spring-rest-http-2 + spring-rest-query-language + spring-rest-shell + spring-rest-simple + spring-rest-testing + spring-resttemplate + spring-resttemplate-2 + spring-resttemplate-3 + spring-thymeleaf + spring-thymeleaf-2 + spring-thymeleaf-3 + + + diff --git a/spring-5-mvc/.gitignore b/spring-web-modules/spring-5-mvc/.gitignore similarity index 100% rename from spring-5-mvc/.gitignore rename to spring-web-modules/spring-5-mvc/.gitignore diff --git a/spring-5-mvc/README.md b/spring-web-modules/spring-5-mvc/README.md similarity index 85% rename from spring-5-mvc/README.md rename to spring-web-modules/spring-5-mvc/README.md index aff8bb227c..edb6cec455 100644 --- a/spring-5-mvc/README.md +++ b/spring-web-modules/spring-5-mvc/README.md @@ -3,7 +3,6 @@ This module contains articles about Spring 5 model-view-controller (MVC) pattern ### Relevant Articles: -- [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) diff --git a/spring-web-modules/spring-5-mvc/pom.xml b/spring-web-modules/spring-5-mvc/pom.xml new file mode 100644 index 0000000000..ddcce8207b --- /dev/null +++ b/spring-web-modules/spring-5-mvc/pom.xml @@ -0,0 +1,99 @@ + + + 4.0.0 + spring-5-mvc + spring-5-mvc + jar + spring 5 MVC sample project about new features + + + 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-validation + + + org.springframework.boot + spring-boot-starter-web + + + + org.apache.commons + commons-lang3 + + + org.slf4j + slf4j-api + + + org.slf4j + jcl-over-slf4j + + + + org.springframework.boot + spring-boot-devtools + runtime + + + com.h2database + h2 + runtime + + + org.springframework + spring-test + + + org.springframework.boot + spring-boot-starter-test + test + + + com.jayway.restassured + rest-assured + ${jayway-rest-assured.version} + test + + + com.github.javafaker + javafaker + ${javafaker.version} + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + + + ${project.basedir}/src/test/kotlin + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + 2.9.0 + 4.5.8 + com.baeldung.Spring5Application + 0.18 + + + diff --git a/spring-5-mvc/src/main/java/com/baeldung/Constants.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/Constants.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/Constants.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/Constants.java diff --git a/spring-5-mvc/src/main/java/com/baeldung/Spring5Application.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/Spring5Application.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/Spring5Application.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/Spring5Application.java diff --git a/spring-5-mvc/src/main/java/com/baeldung/html/HtmlApplication.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/html/HtmlApplication.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/html/HtmlApplication.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/html/HtmlApplication.java diff --git a/spring-5-mvc/src/main/java/com/baeldung/html/HtmlController.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/html/HtmlController.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/html/HtmlController.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/html/HtmlController.java diff --git a/spring-5-mvc/src/main/java/com/baeldung/idc/Application.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/idc/Application.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/idc/Application.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/idc/Application.java diff --git a/spring-5-mvc/src/main/java/com/baeldung/idc/Book.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/idc/Book.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/idc/Book.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/idc/Book.java diff --git a/spring-5-mvc/src/main/java/com/baeldung/idc/BookController.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/idc/BookController.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/idc/BookController.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/idc/BookController.java diff --git a/spring-5-mvc/src/main/java/com/baeldung/idc/BookOperations.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/idc/BookOperations.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/idc/BookOperations.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/idc/BookOperations.java diff --git a/spring-5-mvc/src/main/java/com/baeldung/idc/BookRepository.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/idc/BookRepository.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/idc/BookRepository.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/idc/BookRepository.java diff --git a/spring-5-mvc/src/main/java/com/baeldung/model/Foo.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/model/Foo.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/model/Foo.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/model/Foo.java diff --git a/spring-5-mvc/src/main/java/com/baeldung/persistence/DataSetupBean.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/persistence/DataSetupBean.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/persistence/DataSetupBean.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/persistence/DataSetupBean.java diff --git a/spring-5-mvc/src/main/java/com/baeldung/persistence/FooRepository.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/persistence/FooRepository.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/persistence/FooRepository.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/persistence/FooRepository.java diff --git a/spring-5-mvc/src/main/java/com/baeldung/web/FooController.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/web/FooController.java similarity index 97% rename from spring-5-mvc/src/main/java/com/baeldung/web/FooController.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/web/FooController.java index 137864cddd..8d8e03bbaf 100644 --- a/spring-5-mvc/src/main/java/com/baeldung/web/FooController.java +++ b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/web/FooController.java @@ -1,66 +1,66 @@ -package com.baeldung.web; - -import java.util.List; - -import javax.validation.constraints.Max; -import javax.validation.constraints.Min; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.PageRequest; -import org.springframework.http.HttpStatus; -import org.springframework.validation.annotation.Validated; -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.RequestParam; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.server.ResponseStatusException; - -import com.baeldung.model.Foo; -import com.baeldung.persistence.FooRepository; - -@RestController -public class FooController { - - @Autowired - private FooRepository repo; - - // API - read - - @GetMapping("/foos/{id}") - @Validated - public Foo findById(@PathVariable @Min(0) final long id) { - return repo.findById(id).orElse(null); - } - - @GetMapping("/foos") - public List findAll() { - return repo.findAll(); - } - - @GetMapping( value="/foos", params = { "page", "size" }) - @Validated - public List findPaginated(@RequestParam("page") @Min(0) final int page, @Max(100) @RequestParam("size") final int size) { - return repo.findAll(PageRequest.of(page, size)).getContent(); - } - - // API - write - - @PutMapping("/foos/{id}") - @ResponseStatus(HttpStatus.OK) - public Foo update(@PathVariable("id") final String id, @RequestBody final Foo foo) { - return foo; - } - - @PostMapping("/foos") - @ResponseStatus(HttpStatus.CREATED) - public void create( @RequestBody final Foo foo) { - if (null == foo || null == foo.getName()) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST," 'name' is required"); - } - repo.save(foo); - } +package com.baeldung.web; + +import java.util.List; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.PageRequest; +import org.springframework.http.HttpStatus; +import org.springframework.validation.annotation.Validated; +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.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.server.ResponseStatusException; + +import com.baeldung.model.Foo; +import com.baeldung.persistence.FooRepository; + +@RestController +public class FooController { + + @Autowired + private FooRepository repo; + + // API - read + + @GetMapping("/foos/{id}") + @Validated + public Foo findById(@PathVariable @Min(0) final long id) { + return repo.findById(id).orElse(null); + } + + @GetMapping("/foos") + public List findAll() { + return repo.findAll(); + } + + @GetMapping( value="/foos", params = { "page", "size" }) + @Validated + public List findPaginated(@RequestParam("page") @Min(0) final int page, @Max(100) @RequestParam("size") final int size) { + return repo.findAll(PageRequest.of(page, size)).getContent(); + } + + // API - write + + @PutMapping("/foos/{id}") + @ResponseStatus(HttpStatus.OK) + public Foo update(@PathVariable("id") final String id, @RequestBody final Foo foo) { + return foo; + } + + @PostMapping("/foos") + @ResponseStatus(HttpStatus.CREATED) + public void create( @RequestBody final Foo foo) { + if (null == foo || null == foo.getName()) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST," 'name' is required"); + } + repo.save(foo); + } } \ No newline at end of file diff --git a/spring-5-mvc/src/main/java/com/baeldung/web/ResponseBodyEmitterController.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/web/ResponseBodyEmitterController.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/web/ResponseBodyEmitterController.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/web/ResponseBodyEmitterController.java diff --git a/spring-5-mvc/src/main/java/com/baeldung/web/SseEmitterController.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/web/SseEmitterController.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/web/SseEmitterController.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/web/SseEmitterController.java diff --git a/spring-5-mvc/src/main/java/com/baeldung/web/StreamingResponseBodyController.java b/spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/web/StreamingResponseBodyController.java similarity index 100% rename from spring-5-mvc/src/main/java/com/baeldung/web/StreamingResponseBodyController.java rename to spring-web-modules/spring-5-mvc/src/main/java/com/baeldung/web/StreamingResponseBodyController.java diff --git a/spring-5-mvc/src/main/resources/application.properties b/spring-web-modules/spring-5-mvc/src/main/resources/application.properties similarity index 100% rename from spring-5-mvc/src/main/resources/application.properties rename to spring-web-modules/spring-5-mvc/src/main/resources/application.properties diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/logback.xml b/spring-web-modules/spring-5-mvc/src/main/resources/logback.xml similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/resources/logback.xml rename to spring-web-modules/spring-5-mvc/src/main/resources/logback.xml diff --git a/spring-5-mvc/src/main/webapp/WEB-INF/jsp/index.jsp b/spring-web-modules/spring-5-mvc/src/main/webapp/WEB-INF/jsp/index.jsp similarity index 100% rename from spring-5-mvc/src/main/webapp/WEB-INF/jsp/index.jsp rename to spring-web-modules/spring-5-mvc/src/main/webapp/WEB-INF/jsp/index.jsp diff --git a/spring-5-mvc/src/main/webapp/WEB-INF/web.xml b/spring-web-modules/spring-5-mvc/src/main/webapp/WEB-INF/web.xml similarity index 100% rename from spring-5-mvc/src/main/webapp/WEB-INF/web.xml rename to spring-web-modules/spring-5-mvc/src/main/webapp/WEB-INF/web.xml diff --git a/spring-5-mvc/src/test/java/com/baeldung/LiveTest.java b/spring-web-modules/spring-5-mvc/src/test/java/com/baeldung/LiveTest.java similarity index 100% rename from spring-5-mvc/src/test/java/com/baeldung/LiveTest.java rename to spring-web-modules/spring-5-mvc/src/test/java/com/baeldung/LiveTest.java diff --git a/spring-5-mvc/src/test/java/com/baeldung/Spring5ApplicationIntegrationTest.java b/spring-web-modules/spring-5-mvc/src/test/java/com/baeldung/Spring5ApplicationIntegrationTest.java similarity index 100% rename from spring-5-mvc/src/test/java/com/baeldung/Spring5ApplicationIntegrationTest.java rename to spring-web-modules/spring-5-mvc/src/test/java/com/baeldung/Spring5ApplicationIntegrationTest.java diff --git a/spring-5-mvc/src/test/java/com/baeldung/html/HtmlControllerTest.java b/spring-web-modules/spring-5-mvc/src/test/java/com/baeldung/html/HtmlControllerTest.java similarity index 100% rename from spring-5-mvc/src/test/java/com/baeldung/html/HtmlControllerTest.java rename to spring-web-modules/spring-5-mvc/src/test/java/com/baeldung/html/HtmlControllerTest.java diff --git a/spring-mvc-basics-2/README.md b/spring-web-modules/spring-mvc-basics-2/README.md similarity index 100% rename from spring-mvc-basics-2/README.md rename to spring-web-modules/spring-mvc-basics-2/README.md diff --git a/spring-mvc-basics-2/pom.xml b/spring-web-modules/spring-mvc-basics-2/pom.xml similarity index 98% rename from spring-mvc-basics-2/pom.xml rename to spring-web-modules/spring-mvc-basics-2/pom.xml index c4688ffad6..0b4515994b 100644 --- a/spring-mvc-basics-2/pom.xml +++ b/spring-web-modules/spring-mvc-basics-2/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-spring-5 0.0.1-SNAPSHOT - ../parent-spring-5 + ../../parent-spring-5 @@ -168,7 +168,6 @@ 4.0.0 6.0.10.Final enter-location-of-server - 1.3.2 3.0.11.RELEASE 2.4.12 2.3.27-incubating diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ApplicationConfiguration.java diff --git a/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/EmailConfiguration.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/EmailConfiguration.java new file mode 100644 index 0000000000..7f296ce6a7 --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/EmailConfiguration.java @@ -0,0 +1,126 @@ +package com.baeldung.spring.configuration; + +import freemarker.cache.ClassTemplateLoader; +import freemarker.cache.TemplateLoader; +import freemarker.template.Configuration; +import java.util.Properties; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.PropertySource; +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.thymeleaf.spring5.SpringTemplateEngine; +import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; +import org.thymeleaf.templateresolver.ITemplateResolver; + +@ComponentScan(basePackages = { "com.baeldung.spring.mail" }) +@PropertySource(value={"classpath:application.properties"}) +public class EmailConfiguration { + + @Value("${spring.mail.host}") + private String mailServerHost; + + @Value("${spring.mail.port}") + private Integer mailServerPort; + + @Value("${spring.mail.username}") + private String mailServerUsername; + + @Value("${spring.mail.password}") + private String mailServerPassword; + + @Value("${spring.mail.properties.mail.smtp.auth}") + private String mailServerAuth; + + @Value("${spring.mail.properties.mail.smtp.starttls.enable}") + private String mailServerStartTls; + + @Value("${spring.mail.templates.path}") + private String mailTemplatesPath; + + @Bean + public JavaMailSender getJavaMailSender() { + JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); + + mailSender.setHost(mailServerHost); + mailSender.setPort(mailServerPort); + + mailSender.setUsername(mailServerUsername); + mailSender.setPassword(mailServerPassword); + + Properties props = mailSender.getJavaMailProperties(); + props.put("mail.transport.protocol", "smtp"); + props.put("mail.smtp.auth", mailServerAuth); + props.put("mail.smtp.starttls.enable", mailServerStartTls); + 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(ITemplateResolver templateResolver) { + SpringTemplateEngine templateEngine = new SpringTemplateEngine(); + templateEngine.setTemplateResolver(templateResolver); + templateEngine.setTemplateEngineMessageSource(emailMessageSource()); + return templateEngine; + } + + @Bean + public ITemplateResolver thymeleafClassLoaderTemplateResolver() { + ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); + templateResolver.setPrefix(mailTemplatesPath + "/"); + templateResolver.setSuffix(".html"); + templateResolver.setTemplateMode("HTML"); + templateResolver.setCharacterEncoding("UTF-8"); + return templateResolver; + } + +// @Bean +// public ITemplateResolver thymeleafFilesystemTemplateResolver() { +// FileTemplateResolver templateResolver = new FileTemplateResolver(); +// templateResolver.setPrefix(mailTemplatesPath + "/"); +// templateResolver.setSuffix(".html"); +// templateResolver.setTemplateMode("HTML"); +// templateResolver.setCharacterEncoding("UTF-8"); +// return templateResolver; +// } + + @Bean + public FreeMarkerConfigurer freemarkerClassLoaderConfig() { + Configuration configuration = new Configuration(Configuration.VERSION_2_3_27); + TemplateLoader templateLoader = new ClassTemplateLoader(this.getClass(), "/" + mailTemplatesPath); + configuration.setTemplateLoader(templateLoader); + FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer(); + freeMarkerConfigurer.setConfiguration(configuration); + return freeMarkerConfigurer; + } + +// @Bean +// public FreeMarkerConfigurer freemarkerFilesystemConfig() throws IOException { +// Configuration configuration = new Configuration(Configuration.VERSION_2_3_27); +// TemplateLoader templateLoader = new FileTemplateLoader(new File(mailTemplatesPath)); +// configuration.setTemplateLoader(templateLoader); +// FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer(); +// freeMarkerConfigurer.setConfiguration(configuration); +// return freeMarkerConfigurer; +// } + + @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/FreemarkerConfiguration.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/FreemarkerConfiguration.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/FreemarkerConfiguration.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/FreemarkerConfiguration.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/GroovyConfiguration.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/GroovyConfiguration.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/GroovyConfiguration.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/GroovyConfiguration.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/JadeTemplateConfiguration.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/JadeTemplateConfiguration.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/JadeTemplateConfiguration.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/JadeTemplateConfiguration.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/PushConfiguration.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/PushConfiguration.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/PushConfiguration.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/PushConfiguration.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ThymeleafConfiguration.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ThymeleafConfiguration.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ThymeleafConfiguration.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/ThymeleafConfiguration.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/WebInitializer.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/WebInitializer.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/WebInitializer.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/configuration/WebInitializer.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/AnnotationMethodHandlerAdapterExample.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/AnnotationMethodHandlerAdapterExample.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/AnnotationMethodHandlerAdapterExample.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/AnnotationMethodHandlerAdapterExample.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/CustomerController.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/CustomerController.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/CustomerController.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/CustomerController.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/EmployeeController.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/EmployeeController.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/EmployeeController.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/EmployeeController.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/FileUploadController.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/FileUploadController.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/FileUploadController.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/FileUploadController.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/MailController.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/MailController.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/MailController.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/MailController.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/RequestMappingHandlerAdapterExample.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/RequestMappingHandlerAdapterExample.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/RequestMappingHandlerAdapterExample.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/RequestMappingHandlerAdapterExample.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/RequestMethodController.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/RequestMethodController.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/RequestMethodController.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/RequestMethodController.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/SimpleControllerHandlerAdapterExample.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/SimpleControllerHandlerAdapterExample.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/SimpleControllerHandlerAdapterExample.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/SimpleControllerHandlerAdapterExample.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/UserController.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/UserController.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/UserController.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/UserController.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/Article.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/Article.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/Article.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/Article.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/ArticleFeedView.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/ArticleFeedView.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/ArticleFeedView.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/ArticleFeedView.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/ArticleRssController.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/ArticleRssController.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/ArticleRssController.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/ArticleRssController.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/ArticleRssFeedViewResolver.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/ArticleRssFeedViewResolver.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/ArticleRssFeedViewResolver.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/ArticleRssFeedViewResolver.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/JsonChannelHttpMessageConverter.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/JsonChannelHttpMessageConverter.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/JsonChannelHttpMessageConverter.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/rss/JsonChannelHttpMessageConverter.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/scribe/GithubController.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/scribe/GithubController.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/scribe/GithubController.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/scribe/GithubController.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/scribe/TwitterController.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/scribe/TwitterController.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/scribe/TwitterController.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/controller/scribe/TwitterController.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/Customer.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/Customer.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/Customer.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/Customer.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/Employee.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/Employee.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/Employee.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/Employee.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/MailObject.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/MailObject.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/MailObject.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/MailObject.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/User.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/User.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/User.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/domain/User.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/exception/InvalidRequestException.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/exception/InvalidRequestException.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/exception/InvalidRequestException.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/exception/InvalidRequestException.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/interceptor/FileUploadExceptionAdvice.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/interceptor/FileUploadExceptionAdvice.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/interceptor/FileUploadExceptionAdvice.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/interceptor/FileUploadExceptionAdvice.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailService.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailService.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailService.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailService.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java similarity index 97% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java index 1eb7a5f8b4..a0c8907a87 100644 --- a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java +++ b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/mail/EmailServiceImpl.java @@ -112,7 +112,7 @@ public class EmailServiceImpl implements EmailService { String to, String subject, Map templateModel) throws IOException, TemplateException, MessagingException { - Template freemarkerTemplate = freemarkerConfigurer.createConfiguration().getTemplate("template-freemarker.ftl"); + Template freemarkerTemplate = freemarkerConfigurer.getConfiguration().getTemplate("template-freemarker.ftl"); String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerTemplate, templateModel); sendHtmlMessage(to, subject, htmlBody); diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/push/controller/PushController.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/push/controller/PushController.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/push/controller/PushController.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/push/controller/PushController.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/requestparam/RequestParamController.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/requestparam/RequestParamController.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/requestparam/RequestParamController.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/requestparam/RequestParamController.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/service/EmployeeService.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/service/EmployeeService.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/service/EmployeeService.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/service/EmployeeService.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/service/EmployeeServiceImpl.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/service/EmployeeServiceImpl.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/service/EmployeeServiceImpl.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/service/EmployeeServiceImpl.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/ForwardedServlet.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/ForwardedServlet.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/ForwardedServlet.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/ForwardedServlet.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/HelloServlet.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/HelloServlet.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/HelloServlet.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/HelloServlet.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/RedirectedServlet.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/RedirectedServlet.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/RedirectedServlet.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/RedirectedServlet.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/WelcomeServlet.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/WelcomeServlet.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/WelcomeServlet.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/servlets/WelcomeServlet.java diff --git a/spring-mvc-basics-2/src/main/java/com/baeldung/spring/validator/CustomerValidator.java b/spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/validator/CustomerValidator.java similarity index 100% rename from spring-mvc-basics-2/src/main/java/com/baeldung/spring/validator/CustomerValidator.java rename to spring-web-modules/spring-mvc-basics-2/src/main/java/com/baeldung/spring/validator/CustomerValidator.java diff --git a/spring-mvc-basics-2/src/main/resources/application.properties b/spring-web-modules/spring-mvc-basics-2/src/main/resources/application.properties similarity index 71% rename from spring-mvc-basics-2/src/main/resources/application.properties rename to spring-web-modules/spring-mvc-basics-2/src/main/resources/application.properties index 9a804c07d8..7ca8d33d5c 100644 --- a/spring-mvc-basics-2/src/main/resources/application.properties +++ b/spring-web-modules/spring-mvc-basics-2/src/main/resources/application.properties @@ -6,7 +6,7 @@ spring.mail.port=587 spring.mail.username=username spring.mail.password=password spring.mail.properties.mail.smtp.auth=true -spring.mail.properties.mail.smtp.starttls.enable=true +spring.mail.properties.mail.smtp.starttls.enable=false # Amazon SES SMTP #spring.mail.host=email-smtp.us-west-2.amazonaws.com @@ -19,4 +19,14 @@ spring.mail.properties.mail.smtp.starttls.enable=true #spring.mail.properties.mail.smtp.starttls.required=true # path to attachment file -attachment.invoice=path_to_file \ No newline at end of file +attachment.invoice=path_to_file + + +# +# Mail templates +# + +# Templates directory inside main/resources or absolute filesystem path +spring.mail.templates.path=mail-templates +#spring.mail.templates.path=/path/to/templates + diff --git a/spring-mvc-kotlin/src/main/resources/logback.xml b/spring-web-modules/spring-mvc-basics-2/src/main/resources/logback.xml similarity index 100% rename from spring-mvc-kotlin/src/main/resources/logback.xml rename to spring-web-modules/spring-mvc-basics-2/src/main/resources/logback.xml diff --git a/spring-mvc-basics-2/src/main/resources/mail-logo.png b/spring-web-modules/spring-mvc-basics-2/src/main/resources/mail-logo.png similarity index 100% rename from spring-mvc-basics-2/src/main/resources/mail-logo.png rename to spring-web-modules/spring-mvc-basics-2/src/main/resources/mail-logo.png diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-freemarker.ftl b/spring-web-modules/spring-mvc-basics-2/src/main/resources/mail-templates/template-freemarker.ftl similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-freemarker.ftl rename to spring-web-modules/spring-mvc-basics-2/src/main/resources/mail-templates/template-freemarker.ftl diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-thymeleaf.html b/spring-web-modules/spring-mvc-basics-2/src/main/resources/mail-templates/template-thymeleaf.html similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/template-thymeleaf.html rename to spring-web-modules/spring-mvc-basics-2/src/main/resources/mail-templates/template-thymeleaf.html diff --git a/spring-mvc-basics-2/src/main/resources/mailMessages.properties b/spring-web-modules/spring-mvc-basics-2/src/main/resources/mailMessages.properties similarity index 100% rename from spring-mvc-basics-2/src/main/resources/mailMessages.properties rename to spring-web-modules/spring-mvc-basics-2/src/main/resources/mailMessages.properties diff --git a/spring-mvc-basics-2/src/main/resources/mailMessages_fr_FR.properties b/spring-web-modules/spring-mvc-basics-2/src/main/resources/mailMessages_fr_FR.properties similarity index 100% rename from spring-mvc-basics-2/src/main/resources/mailMessages_fr_FR.properties rename to spring-web-modules/spring-mvc-basics-2/src/main/resources/mailMessages_fr_FR.properties diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/Greeting.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/Greeting.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/Greeting.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/Greeting.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/Greeting.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/Greeting.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/Greeting.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/Greeting.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/customerHome.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/customerHome.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/customerHome.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/customerHome.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/customerView.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/customerView.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/customerView.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/customerView.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/demo.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/demo.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/demo.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/demo.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/emails.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/emails.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/emails.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/emails.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/employeeHome.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/employeeHome.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/employeeHome.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/employeeHome.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/employeeView.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/employeeView.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/employeeView.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/employeeView.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/error.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/error.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/error.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/error.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/file.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/file.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/file.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/file.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/send.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/send.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/send.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/send.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/sendHtml.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/sendHtml.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/sendHtml.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/mail/sendHtml.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/pages/home.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/pages/home.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/pages/home.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/pages/home.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/pages/springmvc.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/pages/springmvc.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/pages/springmvc.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/pages/springmvc.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-freemarker.ftl b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-freemarker.ftl similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-freemarker.ftl rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-freemarker.ftl diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-groovy.tpl b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-groovy.tpl similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-groovy.tpl rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-groovy.tpl diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-jade.jade b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-jade.jade similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-jade.jade rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-jade.jade diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-thymeleaf.html b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-thymeleaf.html similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-thymeleaf.html rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration-thymeleaf.html diff --git a/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration.jsp b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration.jsp similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration.jsp rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/WEB-INF/views/registration.jsp diff --git a/spring-mvc-basics-2/src/main/webapp/resources/logo.png b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/resources/logo.png similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/resources/logo.png rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/resources/logo.png diff --git a/spring-mvc-basics-2/src/main/webapp/static/css/app.css b/spring-web-modules/spring-mvc-basics-2/src/main/webapp/static/css/app.css similarity index 100% rename from spring-mvc-basics-2/src/main/webapp/static/css/app.css rename to spring-web-modules/spring-mvc-basics-2/src/main/webapp/static/css/app.css diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/SpringContextTest.java b/spring-web-modules/spring-mvc-basics-2/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-mvc-basics-2/src/test/java/com/baeldung/SpringContextTest.java rename to spring-web-modules/spring-mvc-basics-2/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/push/PushControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics-2/src/test/java/com/baeldung/controller/push/PushControllerIntegrationTest.java similarity index 100% rename from spring-mvc-basics-2/src/test/java/com/baeldung/controller/push/PushControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-2/src/test/java/com/baeldung/controller/push/PushControllerIntegrationTest.java diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java b/spring-web-modules/spring-mvc-basics-2/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java similarity index 100% rename from spring-mvc-basics-2/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-2/src/test/java/com/baeldung/controller/rss/ArticleRssIntegrationTest.java diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/spring/servlets/HelloServletIntegrationTest.java b/spring-web-modules/spring-mvc-basics-2/src/test/java/com/baeldung/spring/servlets/HelloServletIntegrationTest.java similarity index 100% rename from spring-mvc-basics-2/src/test/java/com/baeldung/spring/servlets/HelloServletIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-2/src/test/java/com/baeldung/spring/servlets/HelloServletIntegrationTest.java diff --git a/spring-mvc-basics-2/src/test/java/com/baeldung/spring/servlets/WelcomeServletIntegrationTest.java b/spring-web-modules/spring-mvc-basics-2/src/test/java/com/baeldung/spring/servlets/WelcomeServletIntegrationTest.java similarity index 100% rename from spring-mvc-basics-2/src/test/java/com/baeldung/spring/servlets/WelcomeServletIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-2/src/test/java/com/baeldung/spring/servlets/WelcomeServletIntegrationTest.java diff --git a/spring-mvc-basics-3/README.md b/spring-web-modules/spring-mvc-basics-3/README.md similarity index 100% rename from spring-mvc-basics-3/README.md rename to spring-web-modules/spring-mvc-basics-3/README.md diff --git a/spring-mvc-basics-3/pom.xml b/spring-web-modules/spring-mvc-basics-3/pom.xml similarity index 94% rename from spring-mvc-basics-3/pom.xml rename to spring-web-modules/spring-mvc-basics-3/pom.xml index a929337b25..a9245814a8 100644 --- a/spring-mvc-basics-3/pom.xml +++ b/spring-web-modules/spring-mvc-basics-3/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 @@ -78,12 +78,6 @@ test - - org.springframework.cloud - spring-cloud-context - ${springcloud.version} - - org.apache.httpcomponents httpclient @@ -149,7 +143,6 @@ 2.2 18.0 3.1.7 - 2.0.2.RELEASE 4.5.8 diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/Application.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/Application.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/Application.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/Application.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/config/WebConfig.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/config/WebConfig.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/config/WebConfig.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/config/WebConfig.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/controller/GenericEntityController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/controller/GenericEntityController.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/controller/GenericEntityController.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/controller/GenericEntityController.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/GenericBigDecimalConverter.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/GenericBigDecimalConverter.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/GenericBigDecimalConverter.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/GenericBigDecimalConverter.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToAbstractEntityConverterFactory.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToAbstractEntityConverterFactory.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToAbstractEntityConverterFactory.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToAbstractEntityConverterFactory.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToEmployeeConverter.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToEmployeeConverter.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToEmployeeConverter.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToEmployeeConverter.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToEnumConverter.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToEnumConverter.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToEnumConverter.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToEnumConverter.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToLocalDateTimeConverter.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToLocalDateTimeConverter.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToLocalDateTimeConverter.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/StringToLocalDateTimeConverter.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/controller/AbstractEntityController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/controller/AbstractEntityController.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/controller/AbstractEntityController.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/controller/AbstractEntityController.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/controller/StringToEmployeeConverterController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/controller/StringToEmployeeConverterController.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/controller/StringToEmployeeConverterController.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/converter/controller/StringToEmployeeConverterController.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/AbstractEntity.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/AbstractEntity.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/AbstractEntity.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/AbstractEntity.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Bar.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Bar.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Bar.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Bar.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Employee.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Employee.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Employee.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Employee.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Foo.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Foo.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Foo.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Foo.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/GenericEntity.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/GenericEntity.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/GenericEntity.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/GenericEntity.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Modes.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Modes.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Modes.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/domain/Modes.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/repository/GenericEntityRepository.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/repository/GenericEntityRepository.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/repository/GenericEntityRepository.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/repository/GenericEntityRepository.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/web/resolver/HeaderVersionArgumentResolver.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/web/resolver/HeaderVersionArgumentResolver.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/web/resolver/HeaderVersionArgumentResolver.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/web/resolver/HeaderVersionArgumentResolver.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/boot/web/resolver/Version.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/web/resolver/Version.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/boot/web/resolver/Version.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/boot/web/resolver/Version.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyHttpServletRequest.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyHttpServletRequest.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyHttpServletRequest.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyHttpServletRequest.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyServletInputStream.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyServletInputStream.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyServletInputStream.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/CachedBodyServletInputStream.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/ContentCachingFilter.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/ContentCachingFilter.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/ContentCachingFilter.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/ContentCachingFilter.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/HttpRequestDemoConfig.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/HttpRequestDemoConfig.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/HttpRequestDemoConfig.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/HttpRequestDemoConfig.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/Person.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/Person.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/Person.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/Person.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/PersonController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/PersonController.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/PersonController.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/PersonController.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/PrintRequestContentFilter.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/PrintRequestContentFilter.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/PrintRequestContentFilter.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/cachedrequest/PrintRequestContentFilter.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/Application.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/Application.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/Application.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/Application.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/controller/FAQController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/controller/FAQController.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/controller/FAQController.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/controller/FAQController.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/controller/Ping.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/controller/Ping.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/controller/Ping.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/controller/Ping.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/FilterRegistrationConfig.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/FilterRegistrationConfig.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/FilterRegistrationConfig.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/FilterRegistrationConfig.java diff --git a/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/HeaderValidatorFilter.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/HeaderValidatorFilter.java new file mode 100644 index 0000000000..d6c1777326 --- /dev/null +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/HeaderValidatorFilter.java @@ -0,0 +1,33 @@ +package com.baeldung.exclude_urls_filter.filter; + +import org.springframework.core.annotation.Order; +import org.springframework.http.HttpStatus; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Order(1) +public class HeaderValidatorFilter extends OncePerRequestFilter { + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, + FilterChain filterChain) + throws ServletException, + IOException { + String countryCode = request.getHeader("X-Country-Code"); + if (!"US".equals(countryCode)) { + response.sendError(HttpStatus.BAD_REQUEST.value(), "Invalid Locale"); + return; + } + filterChain.doFilter(request, response); + } + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { + String path = request.getRequestURI(); + return "/health".equals(path); + } +} diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/LogFilter.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/LogFilter.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/LogFilter.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/filter/LogFilter.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/service/FAQService.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/service/FAQService.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/service/FAQService.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/service/FAQService.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/service/FAQServiceImpl.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/service/FAQServiceImpl.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/service/FAQServiceImpl.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/exclude_urls_filter/service/FAQServiceImpl.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/Application.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/Application.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/Application.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/Application.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/controllers/PoemSubmission.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/controllers/PoemSubmission.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/controllers/PoemSubmission.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/controllers/PoemSubmission.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/model/Poem.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/model/Poem.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/model/Poem.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/flash_attributes/model/Poem.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/Application.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/Application.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/Application.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/Application.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/controllers/FeedbackForm.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/controllers/FeedbackForm.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/controllers/FeedbackForm.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/controllers/FeedbackForm.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/model/Feedback.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/model/Feedback.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/model/Feedback.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/form_submission/model/Feedback.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/MyMessageInterpolator.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/MyMessageInterpolator.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/MyMessageInterpolator.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/MyMessageInterpolator.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/NotNullRequest.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/NotNullRequest.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/NotNullRequest.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/NotNullRequest.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationController.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationController.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationController.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationExamples.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationExamples.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationExamples.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/interpolation/ValidationExamples.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/spring/Application.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/Application.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/spring/Application.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/Application.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/spring/config/MvcConfig.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/config/MvcConfig.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/spring/config/MvcConfig.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/config/MvcConfig.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/spring/config/converter/StringToEnumConverter.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/config/converter/StringToEnumConverter.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/spring/config/converter/StringToEnumConverter.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/config/converter/StringToEnumConverter.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/spring/enums/EnumController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/enums/EnumController.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/spring/enums/EnumController.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/enums/EnumController.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/spring/exceptions/GlobalControllerExceptionHandler.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/exceptions/GlobalControllerExceptionHandler.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/spring/exceptions/GlobalControllerExceptionHandler.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/exceptions/GlobalControllerExceptionHandler.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/spring/headers/controller/ReadHeaderRestController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/headers/controller/ReadHeaderRestController.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/spring/headers/controller/ReadHeaderRestController.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/headers/controller/ReadHeaderRestController.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/spring/model/Modes.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/model/Modes.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/spring/model/Modes.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/model/Modes.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/spring/slash/Application.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/slash/Application.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/spring/slash/Application.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/slash/Application.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/spring/slash/SlashParsingController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/slash/SlashParsingController.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/spring/slash/SlashParsingController.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/spring/slash/SlashParsingController.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/SpringListValidationApplication.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/SpringListValidationApplication.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/SpringListValidationApplication.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/SpringListValidationApplication.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraint.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraint.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraint.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraint.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java similarity index 78% rename from spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java index 0154fb636a..409b6e1ab5 100644 --- a/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java +++ b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/constraint/MaxSizeConstraintValidator.java @@ -11,11 +11,7 @@ public class MaxSizeConstraintValidator implements ConstraintValidator values, ConstraintValidatorContext context) { - boolean isValid = true; - if (values.size() > 4) { - isValid = false; - } - return isValid; + return values.size() <= 4; } } diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/controller/MovieController.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/exception/ConstraintViolationExceptionHandler.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/model/Movie.java diff --git a/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/service/MovieService.java b/spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/service/MovieService.java similarity index 100% rename from spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/service/MovieService.java rename to spring-web-modules/spring-mvc-basics-3/src/main/java/com/baeldung/validation/listvalidation/service/MovieService.java diff --git a/spring-mvc-basics-3/src/main/resources/application.properties b/spring-web-modules/spring-mvc-basics-3/src/main/resources/application.properties similarity index 100% rename from spring-mvc-basics-3/src/main/resources/application.properties rename to spring-web-modules/spring-mvc-basics-3/src/main/resources/application.properties diff --git a/spring-mvc-basics-3/src/main/resources/templates/feedback.html b/spring-web-modules/spring-mvc-basics-3/src/main/resources/templates/feedback.html similarity index 100% rename from spring-mvc-basics-3/src/main/resources/templates/feedback.html rename to spring-web-modules/spring-mvc-basics-3/src/main/resources/templates/feedback.html diff --git a/spring-mvc-basics-3/src/main/resources/templates/submit.html b/spring-web-modules/spring-mvc-basics-3/src/main/resources/templates/submit.html similarity index 100% rename from spring-mvc-basics-3/src/main/resources/templates/submit.html rename to spring-web-modules/spring-mvc-basics-3/src/main/resources/templates/submit.html diff --git a/spring-mvc-basics-3/src/main/resources/templates/success.html b/spring-web-modules/spring-mvc-basics-3/src/main/resources/templates/success.html similarity index 100% rename from spring-mvc-basics-3/src/main/resources/templates/success.html rename to spring-web-modules/spring-mvc-basics-3/src/main/resources/templates/success.html diff --git a/spring-mvc-basics-3/src/test/java/com/baeldung/AppContextIntegrationTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/AppContextIntegrationTest.java similarity index 100% rename from spring-mvc-basics-3/src/test/java/com/baeldung/AppContextIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/AppContextIntegrationTest.java diff --git a/spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootApplicationIntegrationTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootApplicationIntegrationTest.java similarity index 100% rename from spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootApplicationIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootApplicationIntegrationTest.java diff --git a/spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootJPAIntegrationTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootJPAIntegrationTest.java similarity index 100% rename from spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootJPAIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootJPAIntegrationTest.java diff --git a/spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootMailIntegrationTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootMailIntegrationTest.java similarity index 100% rename from spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootMailIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/SpringBootMailIntegrationTest.java diff --git a/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/CachedBodyHttpServletRequestUnitTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/CachedBodyHttpServletRequestUnitTest.java similarity index 100% rename from spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/CachedBodyHttpServletRequestUnitTest.java rename to spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/CachedBodyHttpServletRequestUnitTest.java diff --git a/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/CachedBodyServletInputStreamUnitTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/CachedBodyServletInputStreamUnitTest.java similarity index 100% rename from spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/CachedBodyServletInputStreamUnitTest.java rename to spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/CachedBodyServletInputStreamUnitTest.java diff --git a/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/ContentCachingFilterUnitTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/ContentCachingFilterUnitTest.java similarity index 100% rename from spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/ContentCachingFilterUnitTest.java rename to spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/ContentCachingFilterUnitTest.java diff --git a/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/PersonControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/PersonControllerIntegrationTest.java similarity index 100% rename from spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/PersonControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/PersonControllerIntegrationTest.java diff --git a/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/PrintRequestContentFilterUnitTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/PrintRequestContentFilterUnitTest.java similarity index 100% rename from spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/PrintRequestContentFilterUnitTest.java rename to spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/cachedrequest/PrintRequestContentFilterUnitTest.java diff --git a/spring-mvc-basics-3/src/test/java/com/baeldung/headers/controller/ReadHeaderRestControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/headers/controller/ReadHeaderRestControllerIntegrationTest.java similarity index 100% rename from spring-mvc-basics-3/src/test/java/com/baeldung/headers/controller/ReadHeaderRestControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/headers/controller/ReadHeaderRestControllerIntegrationTest.java diff --git a/spring-mvc-basics-3/src/test/java/com/baeldung/spring/slash/SlashParsingControllerIntTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/spring/slash/SlashParsingControllerIntTest.java similarity index 100% rename from spring-mvc-basics-3/src/test/java/com/baeldung/spring/slash/SlashParsingControllerIntTest.java rename to spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/spring/slash/SlashParsingControllerIntTest.java diff --git a/spring-mvc-basics-3/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java similarity index 100% rename from spring-mvc-basics-3/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-3/src/test/java/com/baeldung/validation/listvalidation/MovieControllerIntegrationTest.java diff --git a/spring-ldap/.gitignore b/spring-web-modules/spring-mvc-basics-4/.gitignore similarity index 100% rename from spring-ldap/.gitignore rename to spring-web-modules/spring-mvc-basics-4/.gitignore diff --git a/spring-mvc-basics-4/README.md b/spring-web-modules/spring-mvc-basics-4/README.md similarity index 73% rename from spring-mvc-basics-4/README.md rename to spring-web-modules/spring-mvc-basics-4/README.md index 0da83540ad..211564a363 100644 --- a/spring-mvc-basics-4/README.md +++ b/spring-web-modules/spring-mvc-basics-4/README.md @@ -1,11 +1,11 @@ ## Spring MVC Basics with Java Configuration Example Project ### The Course -The "REST With Spring" Classes: http://bit.ly/restwithspring +The "REST With Spring" Classes: https://bit.ly/restwithspring ### Relevant Articles: - [Quick Guide to Spring Controllers](https://www.baeldung.com/spring-controllers) -- [Model, ModelMap, and ModelView in Spring MVC](https://www.baeldung.com/spring-mvc-model-model-map-model-view) +- [Model, ModelMap, and ModelAndView in Spring MVC](https://www.baeldung.com/spring-mvc-model-model-map-model-view) - [Spring Web Contexts](https://www.baeldung.com/spring-web-contexts) - [Spring Optional Path variables](https://www.baeldung.com/spring-optional-path-variables) - [JSON Parameters with Spring MVC](https://www.baeldung.com/spring-mvc-send-json-parameters) diff --git a/spring-mvc-basics-4/pom.xml b/spring-web-modules/spring-mvc-basics-4/pom.xml similarity index 94% rename from spring-mvc-basics-4/pom.xml rename to spring-web-modules/spring-mvc-basics-4/pom.xml index 8382cd03b8..07dddcde0c 100644 --- a/spring-mvc-basics-4/pom.xml +++ b/spring-web-modules/spring-mvc-basics-4/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/Greeting.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/Greeting.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/contexts/Greeting.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/Greeting.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/AnnotationsBasedApplicationAndServletInitializer.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/AnnotationsBasedApplicationAndServletInitializer.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/AnnotationsBasedApplicationAndServletInitializer.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/AnnotationsBasedApplicationAndServletInitializer.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/AnnotationsBasedApplicationInitializer.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/AnnotationsBasedApplicationInitializer.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/AnnotationsBasedApplicationInitializer.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/AnnotationsBasedApplicationInitializer.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/ApplicationInitializer.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/ApplicationInitializer.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/ApplicationInitializer.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/ApplicationInitializer.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/NormalWebAppConfig.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/NormalWebAppConfig.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/NormalWebAppConfig.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/NormalWebAppConfig.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/RootApplicationConfig.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/RootApplicationConfig.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/RootApplicationConfig.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/RootApplicationConfig.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/SecureAnnotationsBasedApplicationAndServletInitializer.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/SecureAnnotationsBasedApplicationAndServletInitializer.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/SecureAnnotationsBasedApplicationAndServletInitializer.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/SecureAnnotationsBasedApplicationAndServletInitializer.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/SecureWebAppConfig.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/SecureWebAppConfig.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/SecureWebAppConfig.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/config/SecureWebAppConfig.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/normal/HelloWorldController.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/normal/HelloWorldController.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/contexts/normal/HelloWorldController.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/normal/HelloWorldController.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/secure/HelloWorldSecureController.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/secure/HelloWorldSecureController.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/contexts/secure/HelloWorldSecureController.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/secure/HelloWorldSecureController.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/services/ApplicationContextUtilService.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/services/ApplicationContextUtilService.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/contexts/services/ApplicationContextUtilService.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/services/ApplicationContextUtilService.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/services/GreeterService.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/services/GreeterService.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/contexts/services/GreeterService.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/contexts/services/GreeterService.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/controller/config/StudentControllerConfig.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/config/StudentControllerConfig.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/controller/config/StudentControllerConfig.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/config/StudentControllerConfig.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/controller/config/WebConfig.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/config/WebConfig.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/controller/config/WebConfig.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/config/WebConfig.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/PassParametersController.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/PassParametersController.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/PassParametersController.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/PassParametersController.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/RestAnnotatedController.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/RestAnnotatedController.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/RestAnnotatedController.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/RestAnnotatedController.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/RestController.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/RestController.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/RestController.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/RestController.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/TestController.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/TestController.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/TestController.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/controller/TestController.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/controller/student/Student.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/student/Student.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/controller/student/Student.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/controller/student/Student.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/config/JsonParamsConfig.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/config/JsonParamsConfig.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/config/JsonParamsConfig.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/config/JsonParamsConfig.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/config/JsonParamsInit.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/config/JsonParamsInit.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/config/JsonParamsInit.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/config/JsonParamsInit.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/controller/ProductController.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/controller/ProductController.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/controller/ProductController.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/controller/ProductController.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/model/Product.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/model/Product.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/model/Product.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/model/Product.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/propertyeditor/ProductEditor.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/propertyeditor/ProductEditor.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/propertyeditor/ProductEditor.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/jsonparams/propertyeditor/ProductEditor.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/Article.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/Article.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/Article.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/Article.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerController.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerController.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerController.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerController.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithMapParamController.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithMapParamController.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithMapParamController.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithMapParamController.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithOptionalParamController.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithOptionalParamController.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithOptionalParamController.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithOptionalParamController.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithRequiredAttributeController.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithRequiredAttributeController.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithRequiredAttributeController.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithRequiredAttributeController.java diff --git a/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java b/spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java similarity index 100% rename from spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java rename to spring-web-modules/spring-mvc-basics-4/src/main/java/com/baeldung/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java diff --git a/spring-mvc-basics-4/src/main/resources/application.properties b/spring-web-modules/spring-mvc-basics-4/src/main/resources/application.properties similarity index 100% rename from spring-mvc-basics-4/src/main/resources/application.properties rename to spring-web-modules/spring-mvc-basics-4/src/main/resources/application.properties diff --git a/spring-mvc-velocity/src/main/resources/logback.xml b/spring-web-modules/spring-mvc-basics-4/src/main/resources/logback.xml similarity index 100% rename from spring-mvc-velocity/src/main/resources/logback.xml rename to spring-web-modules/spring-mvc-basics-4/src/main/resources/logback.xml diff --git a/spring-mvc-basics-4/src/main/resources/test-mvc.xml b/spring-web-modules/spring-mvc-basics-4/src/main/resources/test-mvc.xml similarity index 100% rename from spring-mvc-basics-4/src/main/resources/test-mvc.xml rename to spring-web-modules/spring-mvc-basics-4/src/main/resources/test-mvc.xml diff --git a/spring-mvc-basics-4/src/main/webapp/WEB-INF/greeting.xml b/spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/greeting.xml similarity index 100% rename from spring-mvc-basics-4/src/main/webapp/WEB-INF/greeting.xml rename to spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/greeting.xml diff --git a/spring-mvc-basics-4/src/main/webapp/WEB-INF/index.jsp b/spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/index.jsp similarity index 100% rename from spring-mvc-basics-4/src/main/webapp/WEB-INF/index.jsp rename to spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/index.jsp diff --git a/spring-mvc-basics-4/src/main/webapp/WEB-INF/normal-webapp-servlet.xml b/spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/normal-webapp-servlet.xml similarity index 100% rename from spring-mvc-basics-4/src/main/webapp/WEB-INF/normal-webapp-servlet.xml rename to spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/normal-webapp-servlet.xml diff --git a/spring-mvc-basics-4/src/main/webapp/WEB-INF/rootApplicationContext.xml b/spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/rootApplicationContext.xml similarity index 100% rename from spring-mvc-basics-4/src/main/webapp/WEB-INF/rootApplicationContext.xml rename to spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/rootApplicationContext.xml diff --git a/spring-mvc-basics-4/src/main/webapp/WEB-INF/secure-webapp-servlet.xml b/spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/secure-webapp-servlet.xml similarity index 100% rename from spring-mvc-basics-4/src/main/webapp/WEB-INF/secure-webapp-servlet.xml rename to spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/secure-webapp-servlet.xml diff --git a/spring-mvc-basics-4/src/main/webapp/WEB-INF/secure/view/welcome.jsp b/spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/secure/view/welcome.jsp similarity index 100% rename from spring-mvc-basics-4/src/main/webapp/WEB-INF/secure/view/welcome.jsp rename to spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/secure/view/welcome.jsp diff --git a/spring-mvc-basics-4/src/main/webapp/WEB-INF/view/sample.jsp b/spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/view/sample.jsp similarity index 100% rename from spring-mvc-basics-4/src/main/webapp/WEB-INF/view/sample.jsp rename to spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/view/sample.jsp diff --git a/spring-mvc-basics-4/src/main/webapp/WEB-INF/view/scopesExample.jsp b/spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/view/scopesExample.jsp similarity index 100% rename from spring-mvc-basics-4/src/main/webapp/WEB-INF/view/scopesExample.jsp rename to spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/view/scopesExample.jsp diff --git a/spring-mvc-basics-4/src/main/webapp/WEB-INF/view/viewPage.html b/spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/view/viewPage.html similarity index 100% rename from spring-mvc-basics-4/src/main/webapp/WEB-INF/view/viewPage.html rename to spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/view/viewPage.html diff --git a/spring-mvc-basics-4/src/main/webapp/WEB-INF/view/welcome.jsp b/spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/view/welcome.jsp similarity index 100% rename from spring-mvc-basics-4/src/main/webapp/WEB-INF/view/welcome.jsp rename to spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/view/welcome.jsp diff --git a/spring-mvc-basics-4/src/main/webapp/WEB-INF/web-old.xml b/spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/web-old.xml similarity index 100% rename from spring-mvc-basics-4/src/main/webapp/WEB-INF/web-old.xml rename to spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/web-old.xml diff --git a/spring-mvc-basics-4/src/main/webapp/WEB-INF/welcome.jsp b/spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/welcome.jsp similarity index 100% rename from spring-mvc-basics-4/src/main/webapp/WEB-INF/welcome.jsp rename to spring-web-modules/spring-mvc-basics-4/src/main/webapp/WEB-INF/welcome.jsp diff --git a/spring-mvc-basics-4/src/main/webapp/index.jsp b/spring-web-modules/spring-mvc-basics-4/src/main/webapp/index.jsp similarity index 100% rename from spring-mvc-basics-4/src/main/webapp/index.jsp rename to spring-web-modules/spring-mvc-basics-4/src/main/webapp/index.jsp diff --git a/spring-mvc-basics-4/src/test/java/com/baeldung/controller/ControllerAnnotationIntegrationTest.java b/spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/controller/ControllerAnnotationIntegrationTest.java similarity index 100% rename from spring-mvc-basics-4/src/test/java/com/baeldung/controller/ControllerAnnotationIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/controller/ControllerAnnotationIntegrationTest.java diff --git a/spring-mvc-basics-4/src/test/java/com/baeldung/controller/ControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/controller/ControllerIntegrationTest.java similarity index 100% rename from spring-mvc-basics-4/src/test/java/com/baeldung/controller/ControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/controller/ControllerIntegrationTest.java diff --git a/spring-mvc-basics-4/src/test/java/com/baeldung/controller/PassParametersControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/controller/PassParametersControllerIntegrationTest.java similarity index 100% rename from spring-mvc-basics-4/src/test/java/com/baeldung/controller/PassParametersControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/controller/PassParametersControllerIntegrationTest.java diff --git a/spring-mvc-basics-4/src/test/java/com/baeldung/jsonparams/JsonParamsIntegrationTest.java b/spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/jsonparams/JsonParamsIntegrationTest.java similarity index 100% rename from spring-mvc-basics-4/src/test/java/com/baeldung/jsonparams/JsonParamsIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/jsonparams/JsonParamsIntegrationTest.java diff --git a/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerControllerIntegrationTest.java similarity index 100% rename from spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerControllerIntegrationTest.java diff --git a/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java b/spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java similarity index 100% rename from spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java diff --git a/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java b/spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java similarity index 100% rename from spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java diff --git a/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java b/spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java similarity index 100% rename from spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java diff --git a/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java b/spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java similarity index 100% rename from spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java rename to spring-web-modules/spring-mvc-basics-4/src/test/java/com/baeldung/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java diff --git a/spring-mvc-basics-4/src/test/resources/test-mvc.xml b/spring-web-modules/spring-mvc-basics-4/src/test/resources/test-mvc.xml similarity index 100% rename from spring-mvc-basics-4/src/test/resources/test-mvc.xml rename to spring-web-modules/spring-mvc-basics-4/src/test/resources/test-mvc.xml diff --git a/spring-mvc-basics-4/.gitignore b/spring-web-modules/spring-mvc-basics/.gitignore similarity index 100% rename from spring-mvc-basics-4/.gitignore rename to spring-web-modules/spring-mvc-basics/.gitignore diff --git a/spring-mvc-basics/README.md b/spring-web-modules/spring-mvc-basics/README.md similarity index 85% rename from spring-mvc-basics/README.md rename to spring-web-modules/spring-mvc-basics/README.md index cd36ffd94a..49d23aef25 100644 --- a/spring-mvc-basics/README.md +++ b/spring-web-modules/spring-mvc-basics/README.md @@ -4,10 +4,11 @@ This module contains articles about the basics of Spring MVC. Articles about mor their own module. ### The Course -The "REST With Spring" Classes: http://bit.ly/restwithspring +The "REST With Spring" Classes: https://bit.ly/restwithspring ### Relevant Articles: - [Spring MVC Tutorial](https://www.baeldung.com/spring-mvc-tutorial) +- [An Intro to the Spring DispatcherServlet](https://www.baeldung.com/spring-dispatcherservlet) - [The Spring @Controller and @RestController Annotations](https://www.baeldung.com/spring-controller-vs-restcontroller) - [A Guide to the ViewResolver in Spring MVC](https://www.baeldung.com/spring-mvc-view-resolver-tutorial) - [Guide to Spring Handler Mappings](https://www.baeldung.com/spring-handler-mappings) @@ -17,4 +18,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Using Spring @ResponseStatus to Set HTTP Status Code](https://www.baeldung.com/spring-response-status) - [Spring MVC and the @ModelAttribute Annotation](https://www.baeldung.com/spring-mvc-and-the-modelattribute-annotation) - [The HttpMediaTypeNotAcceptableException in Spring MVC](https://www.baeldung.com/spring-httpmediatypenotacceptable) -- More articles: [[more -->]](/spring-mvc-basics-2) \ No newline at end of file +- More articles: [[more -->]](/spring-mvc-basics-2) diff --git a/spring-mvc-basics/pom.xml b/spring-web-modules/spring-mvc-basics/pom.xml similarity index 87% rename from spring-mvc-basics/pom.xml rename to spring-web-modules/spring-mvc-basics/pom.xml index d212bc425a..ac92c7bfe5 100644 --- a/spring-mvc-basics/pom.xml +++ b/spring-web-modules/spring-mvc-basics/pom.xml @@ -12,7 +12,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 @@ -24,6 +24,11 @@ org.springframework.boot spring-boot-starter-validation + + commons-fileupload + commons-fileupload + ${commons-fileupload.version} + org.apache.tomcat.embed diff --git a/spring-mvc-basics/src/main/java/com/baeldung/Application.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/Application.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/Application.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/Application.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/config/MainWebAppInitializer.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/config/MainWebAppInitializer.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/config/MainWebAppInitializer.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/config/MainWebAppInitializer.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/ContactNumberConstraint.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/ContactNumberValidator.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/FieldsValueMatch.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/customvalidator/FieldsValueMatchValidator.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionExampleController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionExampleController.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionExampleController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionExampleController.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/model/Book.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/Book.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/model/Book.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/Book.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/model/Employee.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/Employee.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/model/Employee.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/Employee.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/model/NewUserForm.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/NewUserForm.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/model/NewUserForm.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/NewUserForm.java diff --git a/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/domain/User.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/User.java similarity index 93% rename from spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/domain/User.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/User.java index 6e8cde50db..3265bcc93a 100644 --- a/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/domain/User.java +++ b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/User.java @@ -1,4 +1,4 @@ -package com.baeldung.springdispatcherservlet.domain; +package com.baeldung.model; public class User { diff --git a/spring-mvc-basics/src/main/java/com/baeldung/model/ValidatedPhone.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/ValidatedPhone.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/model/ValidatedPhone.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/model/ValidatedPhone.java diff --git a/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/services/UserService.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/services/UserService.java similarity index 72% rename from spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/services/UserService.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/services/UserService.java index 1b9bdd4a71..4a70701903 100644 --- a/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/services/UserService.java +++ b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/services/UserService.java @@ -1,8 +1,8 @@ -package com.baeldung.springdispatcherservlet.services; +package com.baeldung.services; import org.springframework.stereotype.Service; -import com.baeldung.springdispatcherservlet.domain.User; +import com.baeldung.model.User; @Service public class UserService { diff --git a/spring-mvc-basics/src/main/java/com/baeldung/spring/web/config/WebConfig.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/spring/web/config/WebConfig.java similarity index 53% rename from spring-mvc-basics/src/main/java/com/baeldung/spring/web/config/WebConfig.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/spring/web/config/WebConfig.java index 9a321f65a2..ac917018b0 100644 --- a/spring-mvc-basics/src/main/java/com/baeldung/spring/web/config/WebConfig.java +++ b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/spring/web/config/WebConfig.java @@ -1,13 +1,22 @@ package com.baeldung.spring.web.config; +import java.io.IOException; + import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.http.MediaType; +import org.springframework.ui.context.support.ResourceBundleThemeSource; +import org.springframework.web.multipart.commons.CommonsMultipartResolver; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.resource.PathResourceResolver; +import org.springframework.web.servlet.theme.CookieThemeResolver; +import org.springframework.web.servlet.theme.ThemeChangeInterceptor; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; import org.springframework.web.servlet.view.ResourceBundleViewResolver; @@ -24,6 +33,14 @@ public class WebConfig implements WebMvcConfigurer { .setViewName("index"); } + /** Multipart file uploading configuratioin */ + @Bean + public CommonsMultipartResolver multipartResolver() throws IOException { + CommonsMultipartResolver resolver = new CommonsMultipartResolver(); + resolver.setMaxUploadSize(10000000); + return resolver; + } + @Bean public ViewResolver viewResolver() { final InternalResourceViewResolver bean = new InternalResourceViewResolver(); @@ -34,6 +51,47 @@ public class WebConfig implements WebMvcConfigurer { return bean; } + /** Static resource locations including themes*/ + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**/*") + .addResourceLocations("/", "/resources/") + .setCachePeriod(3600) + .resourceChain(true) + .addResolver(new PathResourceResolver()); + } + + /** BEGIN theme configuration */ + @Bean + public ResourceBundleThemeSource themeSource() { + ResourceBundleThemeSource themeSource = new ResourceBundleThemeSource(); + themeSource.setDefaultEncoding("UTF-8"); + themeSource.setBasenamePrefix("themes."); + return themeSource; + } + + @Bean + public CookieThemeResolver themeResolver() { + CookieThemeResolver resolver = new CookieThemeResolver(); + resolver.setDefaultThemeName("default"); + resolver.setCookieName("example-theme-cookie"); + return resolver; + } + + @Bean + public ThemeChangeInterceptor themeChangeInterceptor() { + ThemeChangeInterceptor interceptor = new ThemeChangeInterceptor(); + interceptor.setParamName("theme"); + return interceptor; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(themeChangeInterceptor()); + } + + /** END theme configuration */ + @Bean public ViewResolver resourceBundleViewResolver() { final ResourceBundleViewResolver bean = new ResourceBundleViewResolver(); diff --git a/spring-mvc-basics/src/main/java/com/baeldung/web/controller/EmployeeController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/EmployeeController.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/web/controller/EmployeeController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/EmployeeController.java diff --git a/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/controller/MultipartController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/MultipartController.java similarity index 96% rename from spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/controller/MultipartController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/MultipartController.java index a693bf039f..2255ba780c 100644 --- a/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/controller/MultipartController.java +++ b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/MultipartController.java @@ -1,4 +1,4 @@ -package com.baeldung.springdispatcherservlet.controller; +package com.baeldung.web.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; diff --git a/spring-mvc-basics/src/main/java/com/baeldung/web/controller/NewUserController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/NewUserController.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/web/controller/NewUserController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/NewUserController.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/web/controller/RequestMappingShortcutsController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/RequestMappingShortcutsController.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/web/controller/RequestMappingShortcutsController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/RequestMappingShortcutsController.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/web/controller/ResponseStatusRestController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/ResponseStatusRestController.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/web/controller/ResponseStatusRestController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/ResponseStatusRestController.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/web/controller/SampleController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/SampleController.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/web/controller/SampleController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/SampleController.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/web/controller/SimpleBookController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/SimpleBookController.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/web/controller/SimpleBookController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/SimpleBookController.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/web/controller/SimpleBookRestController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/SimpleBookRestController.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/web/controller/SimpleBookRestController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/SimpleBookRestController.java diff --git a/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/controller/UserController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/UserController.java similarity index 83% rename from spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/controller/UserController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/UserController.java index 16e6f293ec..9e39c961a1 100644 --- a/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/controller/UserController.java +++ b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/UserController.java @@ -1,7 +1,8 @@ -package com.baeldung.springdispatcherservlet.controller; +package com.baeldung.web.controller; + +import com.baeldung.model.User; +import com.baeldung.services.UserService; -import com.baeldung.springdispatcherservlet.domain.User; -import com.baeldung.springdispatcherservlet.services.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/controller/UserRestController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/UserRestController.java similarity index 82% rename from spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/controller/UserRestController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/UserRestController.java index 9052662f17..7d13c53ba1 100644 --- a/spring-dispatcher-servlet/src/main/java/com/baeldung/springdispatcherservlet/controller/UserRestController.java +++ b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/UserRestController.java @@ -1,7 +1,8 @@ -package com.baeldung.springdispatcherservlet.controller; +package com.baeldung.web.controller; + +import com.baeldung.model.User; +import com.baeldung.services.UserService; -import com.baeldung.springdispatcherservlet.domain.User; -import com.baeldung.springdispatcherservlet.services.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; diff --git a/spring-mvc-basics/src/main/java/com/baeldung/web/controller/ValidatedPhoneController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/ValidatedPhoneController.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/web/controller/ValidatedPhoneController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/ValidatedPhoneController.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/web/controller/handlermapping/BeanNameHandlerMappingController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/handlermapping/BeanNameHandlerMappingController.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/web/controller/handlermapping/BeanNameHandlerMappingController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/handlermapping/BeanNameHandlerMappingController.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/web/controller/handlermapping/SimpleUrlMappingController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/handlermapping/SimpleUrlMappingController.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/web/controller/handlermapping/SimpleUrlMappingController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/handlermapping/SimpleUrlMappingController.java diff --git a/spring-mvc-basics/src/main/java/com/baeldung/web/controller/handlermapping/WelcomeController.java b/spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/handlermapping/WelcomeController.java similarity index 100% rename from spring-mvc-basics/src/main/java/com/baeldung/web/controller/handlermapping/WelcomeController.java rename to spring-web-modules/spring-mvc-basics/src/main/java/com/baeldung/web/controller/handlermapping/WelcomeController.java diff --git a/spring-mvc-basics/src/main/resources/application.properties b/spring-web-modules/spring-mvc-basics/src/main/resources/application.properties similarity index 73% rename from spring-mvc-basics/src/main/resources/application.properties rename to spring-web-modules/spring-mvc-basics/src/main/resources/application.properties index b8a9be0b40..cf26fbfb60 100644 --- a/spring-mvc-basics/src/main/resources/application.properties +++ b/spring-web-modules/spring-mvc-basics/src/main/resources/application.properties @@ -5,3 +5,6 @@ spring.mvc.pathmatch.use-suffix-pattern=true #spring.mvc.contentnegotiation.favor-path-extension=true #spring.mvc.contentnegotiation.favor-parameter=true #spring.mvc.contentnegotiation.parameter-name=mediaType + +# https://github.com/spring-projects/spring-boot/issues/24207 +spring.main.allow-bean-definition-overriding=true diff --git a/spring-mvc-basics/src/main/resources/mvc-configuration.xml b/spring-web-modules/spring-mvc-basics/src/main/resources/mvc-configuration.xml similarity index 100% rename from spring-mvc-basics/src/main/resources/mvc-configuration.xml rename to spring-web-modules/spring-mvc-basics/src/main/resources/mvc-configuration.xml diff --git a/spring-dispatcher-servlet/src/main/resources/themes/default.properties b/spring-web-modules/spring-mvc-basics/src/main/resources/themes/default.properties similarity index 100% rename from spring-dispatcher-servlet/src/main/resources/themes/default.properties rename to spring-web-modules/spring-mvc-basics/src/main/resources/themes/default.properties diff --git a/spring-dispatcher-servlet/src/main/resources/themes/example.properties b/spring-web-modules/spring-mvc-basics/src/main/resources/themes/example.properties similarity index 100% rename from spring-dispatcher-servlet/src/main/resources/themes/example.properties rename to spring-web-modules/spring-mvc-basics/src/main/resources/themes/example.properties diff --git a/spring-mvc-basics/src/main/resources/views.properties b/spring-web-modules/spring-mvc-basics/src/main/resources/views.properties similarity index 100% rename from spring-mvc-basics/src/main/resources/views.properties rename to spring-web-modules/spring-mvc-basics/src/main/resources/views.properties diff --git a/spring-mvc-basics/src/main/resources/views.xml b/spring-web-modules/spring-mvc-basics/src/main/resources/views.xml similarity index 100% rename from spring-mvc-basics/src/main/resources/views.xml rename to spring-web-modules/spring-mvc-basics/src/main/resources/views.xml diff --git a/spring-mvc-basics/src/main/webapp/WEB-INF/view/employeeHome.jsp b/spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view/employeeHome.jsp similarity index 100% rename from spring-mvc-basics/src/main/webapp/WEB-INF/view/employeeHome.jsp rename to spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view/employeeHome.jsp diff --git a/spring-mvc-basics/src/main/webapp/WEB-INF/view/employeeView.jsp b/spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view/employeeView.jsp similarity index 100% rename from spring-mvc-basics/src/main/webapp/WEB-INF/view/employeeView.jsp rename to spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view/employeeView.jsp diff --git a/spring-mvc-basics/src/main/webapp/WEB-INF/view/index.jsp b/spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view/index.jsp similarity index 100% rename from spring-mvc-basics/src/main/webapp/WEB-INF/view/index.jsp rename to spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view/index.jsp diff --git a/spring-mvc-basics/src/main/webapp/WEB-INF/view/phoneHome.jsp b/spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view/phoneHome.jsp similarity index 100% rename from spring-mvc-basics/src/main/webapp/WEB-INF/view/phoneHome.jsp rename to spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view/phoneHome.jsp diff --git a/spring-mvc-basics/src/main/webapp/WEB-INF/view/sample.jsp b/spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view/sample.jsp similarity index 100% rename from spring-mvc-basics/src/main/webapp/WEB-INF/view/sample.jsp rename to spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view/sample.jsp diff --git a/spring-mvc-basics/src/main/webapp/WEB-INF/view/userHome.jsp b/spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view/userHome.jsp similarity index 100% rename from spring-mvc-basics/src/main/webapp/WEB-INF/view/userHome.jsp rename to spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view/userHome.jsp diff --git a/spring-mvc-basics/src/main/webapp/WEB-INF/view2/sample2.jsp b/spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view2/sample2.jsp similarity index 100% rename from spring-mvc-basics/src/main/webapp/WEB-INF/view2/sample2.jsp rename to spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view2/sample2.jsp diff --git a/spring-mvc-basics/src/main/webapp/WEB-INF/view3/sample3.jsp b/spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view3/sample3.jsp similarity index 100% rename from spring-mvc-basics/src/main/webapp/WEB-INF/view3/sample3.jsp rename to spring-web-modules/spring-mvc-basics/src/main/webapp/WEB-INF/view3/sample3.jsp diff --git a/spring-mvc-basics/src/test/java/com/baeldung/SpringContextTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/SpringContextTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/config/BeanNameUrlHandlerMappingConfig.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/config/BeanNameUrlHandlerMappingConfig.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/config/BeanNameUrlHandlerMappingConfig.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/config/BeanNameUrlHandlerMappingConfig.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/config/HandlerMappingDefaultConfig.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/config/HandlerMappingDefaultConfig.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/config/HandlerMappingDefaultConfig.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/config/HandlerMappingDefaultConfig.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/config/HandlerMappingPrioritiesConfig.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/config/HandlerMappingPrioritiesConfig.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/config/HandlerMappingPrioritiesConfig.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/config/HandlerMappingPrioritiesConfig.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/config/SimpleUrlHandlerMappingConfig.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/config/SimpleUrlHandlerMappingConfig.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/config/SimpleUrlHandlerMappingConfig.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/config/SimpleUrlHandlerMappingConfig.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionControllerIntegrationTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/exception/HttpMediaTypeNotAcceptableExceptionControllerIntegrationTest.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/handlermappings/BeanNameMappingConfigIntegrationTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/handlermappings/BeanNameMappingConfigIntegrationTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/handlermappings/BeanNameMappingConfigIntegrationTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/handlermappings/BeanNameMappingConfigIntegrationTest.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/handlermappings/HandlerMappingDefaultConfigIntegrationTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/handlermappings/HandlerMappingDefaultConfigIntegrationTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/handlermappings/HandlerMappingDefaultConfigIntegrationTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/handlermappings/HandlerMappingDefaultConfigIntegrationTest.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/handlermappings/HandlerMappingPriorityConfigIntegrationTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/handlermappings/HandlerMappingPriorityConfigIntegrationTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/handlermappings/HandlerMappingPriorityConfigIntegrationTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/handlermappings/HandlerMappingPriorityConfigIntegrationTest.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/handlermappings/SimpleUrlMappingConfigIntegrationTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/handlermappings/SimpleUrlMappingConfigIntegrationTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/handlermappings/SimpleUrlMappingConfigIntegrationTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/handlermappings/SimpleUrlMappingConfigIntegrationTest.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/ClassValidationMvcIntegrationTest.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/web/controller/CustomMVCValidatorIntegrationTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/CustomMVCValidatorIntegrationTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/web/controller/CustomMVCValidatorIntegrationTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/CustomMVCValidatorIntegrationTest.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerContentNegotiationIntegrationTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerContentNegotiationIntegrationTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerContentNegotiationIntegrationTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerContentNegotiationIntegrationTest.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerModelAttributeIntegrationTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerModelAttributeIntegrationTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerModelAttributeIntegrationTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/EmployeeControllerModelAttributeIntegrationTest.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/web/controller/RequestMapingShortcutsIntegrationTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/RequestMapingShortcutsIntegrationTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/web/controller/RequestMapingShortcutsIntegrationTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/RequestMapingShortcutsIntegrationTest.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/web/controller/ResponseStatusRestControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/ResponseStatusRestControllerIntegrationTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/web/controller/ResponseStatusRestControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/ResponseStatusRestControllerIntegrationTest.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/web/controller/SampleControllerLiveTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/SampleControllerLiveTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/web/controller/SampleControllerLiveTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/SampleControllerLiveTest.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/web/controller/SimpleBookControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/SimpleBookControllerIntegrationTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/web/controller/SimpleBookControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/SimpleBookControllerIntegrationTest.java diff --git a/spring-mvc-basics/src/test/java/com/baeldung/web/controller/SimpleBookRestControllerIntegrationTest.java b/spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/SimpleBookRestControllerIntegrationTest.java similarity index 100% rename from spring-mvc-basics/src/test/java/com/baeldung/web/controller/SimpleBookRestControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-basics/src/test/java/com/baeldung/web/controller/SimpleBookRestControllerIntegrationTest.java diff --git a/spring-mvc-basics/src/test/resources/BeanNameUrlHandlerMappingConfig.xml b/spring-web-modules/spring-mvc-basics/src/test/resources/BeanNameUrlHandlerMappingConfig.xml similarity index 100% rename from spring-mvc-basics/src/test/resources/BeanNameUrlHandlerMappingConfig.xml rename to spring-web-modules/spring-mvc-basics/src/test/resources/BeanNameUrlHandlerMappingConfig.xml diff --git a/spring-mvc-basics/src/test/resources/ControllerClassNameHandlerMappingConfig.xml b/spring-web-modules/spring-mvc-basics/src/test/resources/ControllerClassNameHandlerMappingConfig.xml similarity index 100% rename from spring-mvc-basics/src/test/resources/ControllerClassNameHandlerMappingConfig.xml rename to spring-web-modules/spring-mvc-basics/src/test/resources/ControllerClassNameHandlerMappingConfig.xml diff --git a/spring-mvc-basics/src/test/resources/HandlerMappingConfiguringPriorities.xml b/spring-web-modules/spring-mvc-basics/src/test/resources/HandlerMappingConfiguringPriorities.xml similarity index 100% rename from spring-mvc-basics/src/test/resources/HandlerMappingConfiguringPriorities.xml rename to spring-web-modules/spring-mvc-basics/src/test/resources/HandlerMappingConfiguringPriorities.xml diff --git a/spring-mvc-basics/src/test/resources/SimpleUrlHandlerMappingConfig.xml b/spring-web-modules/spring-mvc-basics/src/test/resources/SimpleUrlHandlerMappingConfig.xml similarity index 100% rename from spring-mvc-basics/src/test/resources/SimpleUrlHandlerMappingConfig.xml rename to spring-web-modules/spring-mvc-basics/src/test/resources/SimpleUrlHandlerMappingConfig.xml diff --git a/spring-mvc-basics/.gitignore b/spring-web-modules/spring-mvc-crash/.gitignore similarity index 100% rename from spring-mvc-basics/.gitignore rename to spring-web-modules/spring-mvc-crash/.gitignore diff --git a/spring-mvc-crash/README.md b/spring-web-modules/spring-mvc-crash/README.md similarity index 100% rename from spring-mvc-crash/README.md rename to spring-web-modules/spring-mvc-crash/README.md diff --git a/spring-mvc-crash/pom.xml b/spring-web-modules/spring-mvc-crash/pom.xml similarity index 98% rename from spring-mvc-crash/pom.xml rename to spring-web-modules/spring-mvc-crash/pom.xml index 8a902d4937..9a0d97bae9 100644 --- a/spring-mvc-crash/pom.xml +++ b/spring-web-modules/spring-mvc-crash/pom.xml @@ -10,8 +10,8 @@ com.baeldung - parent-modules - 1.0.0-SNAPSHOT + spring-web-modules + 0.0.1-SNAPSHOT diff --git a/spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfig.java b/spring-web-modules/spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfig.java similarity index 100% rename from spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfig.java rename to spring-web-modules/spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfig.java diff --git a/spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfigJava.java b/spring-web-modules/spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfigJava.java similarity index 100% rename from spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfigJava.java rename to spring-web-modules/spring-mvc-crash/src/main/java/com/baeldung/spring/ClientWebConfigJava.java diff --git a/spring-mvc-crash/src/main/java/com/baeldung/spring/controller/WelcomeController.java b/spring-web-modules/spring-mvc-crash/src/main/java/com/baeldung/spring/controller/WelcomeController.java similarity index 100% rename from spring-mvc-crash/src/main/java/com/baeldung/spring/controller/WelcomeController.java rename to spring-web-modules/spring-mvc-crash/src/main/java/com/baeldung/spring/controller/WelcomeController.java diff --git a/spring-mvc-crash/src/main/resources/contentManagementWebMvcConfig.xml b/spring-web-modules/spring-mvc-crash/src/main/resources/contentManagementWebMvcConfig.xml similarity index 100% rename from spring-mvc-crash/src/main/resources/contentManagementWebMvcConfig.xml rename to spring-web-modules/spring-mvc-crash/src/main/resources/contentManagementWebMvcConfig.xml diff --git a/spring-mvc-crash/src/main/resources/logback.xml b/spring-web-modules/spring-mvc-crash/src/main/resources/logback.xml similarity index 100% rename from spring-mvc-crash/src/main/resources/logback.xml rename to spring-web-modules/spring-mvc-crash/src/main/resources/logback.xml diff --git a/spring-mvc-crash/src/main/resources/messages.properties b/spring-web-modules/spring-mvc-crash/src/main/resources/messages.properties similarity index 100% rename from spring-mvc-crash/src/main/resources/messages.properties rename to spring-web-modules/spring-mvc-crash/src/main/resources/messages.properties diff --git a/spring-mvc-crash/src/main/resources/webMvcConfig.xml b/spring-web-modules/spring-mvc-crash/src/main/resources/webMvcConfig.xml similarity index 100% rename from spring-mvc-crash/src/main/resources/webMvcConfig.xml rename to spring-web-modules/spring-mvc-crash/src/main/resources/webMvcConfig.xml diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message.groovy b/spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message.groovy similarity index 100% rename from spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message.groovy rename to spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message.groovy diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message2.java b/spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message2.java similarity index 100% rename from spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message2.java rename to spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/crash/commands/message2.java diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/crash/crash.properties b/spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/crash/crash.properties similarity index 100% rename from spring-mvc-crash/src/main/webapp/WEB-INF/crash/crash.properties rename to spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/crash/crash.properties diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/crash/telnet.properties b/spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/crash/telnet.properties similarity index 100% rename from spring-mvc-crash/src/main/webapp/WEB-INF/crash/telnet.properties rename to spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/crash/telnet.properties diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/mvc-servlet.xml similarity index 100% rename from spring-mvc-crash/src/main/webapp/WEB-INF/mvc-servlet.xml rename to spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/mvc-servlet.xml diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/view/error.jsp b/spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/view/error.jsp similarity index 100% rename from spring-mvc-crash/src/main/webapp/WEB-INF/view/error.jsp rename to spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/view/error.jsp diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/view/errorPage.jsp b/spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/view/errorPage.jsp similarity index 100% rename from spring-mvc-crash/src/main/webapp/WEB-INF/view/errorPage.jsp rename to spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/view/errorPage.jsp diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/view/welcome.jsp b/spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/view/welcome.jsp similarity index 100% rename from spring-mvc-crash/src/main/webapp/WEB-INF/view/welcome.jsp rename to spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/view/welcome.jsp diff --git a/spring-mvc-crash/src/main/webapp/WEB-INF/web.xml b/spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/web.xml similarity index 100% rename from spring-mvc-crash/src/main/webapp/WEB-INF/web.xml rename to spring-web-modules/spring-mvc-crash/src/main/webapp/WEB-INF/web.xml diff --git a/spring-mvc-crash/src/main/webapp/index.jsp b/spring-web-modules/spring-mvc-crash/src/main/webapp/index.jsp similarity index 100% rename from spring-mvc-crash/src/main/webapp/index.jsp rename to spring-web-modules/spring-mvc-crash/src/main/webapp/index.jsp diff --git a/spring-mvc-crash/src/main/webapp/jsp/ExampleThree.jsp b/spring-web-modules/spring-mvc-crash/src/main/webapp/jsp/ExampleThree.jsp similarity index 100% rename from spring-mvc-crash/src/main/webapp/jsp/ExampleThree.jsp rename to spring-web-modules/spring-mvc-crash/src/main/webapp/jsp/ExampleThree.jsp diff --git a/spring-mvc-crash/src/main/webapp/jsp/ExampleTwo.jsp b/spring-web-modules/spring-mvc-crash/src/main/webapp/jsp/ExampleTwo.jsp similarity index 100% rename from spring-mvc-crash/src/main/webapp/jsp/ExampleTwo.jsp rename to spring-web-modules/spring-mvc-crash/src/main/webapp/jsp/ExampleTwo.jsp diff --git a/spring-mvc-crash/src/main/webapp/jsp/index.jsp b/spring-web-modules/spring-mvc-crash/src/main/webapp/jsp/index.jsp similarity index 100% rename from spring-mvc-crash/src/main/webapp/jsp/index.jsp rename to spring-web-modules/spring-mvc-crash/src/main/webapp/jsp/index.jsp diff --git a/spring-mvc-crash/src/test/java/com/baeldung/SpringContextTest.java b/spring-web-modules/spring-mvc-crash/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-mvc-crash/src/test/java/com/baeldung/SpringContextTest.java rename to spring-web-modules/spring-mvc-crash/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-mvc-forms-jsp/README.md b/spring-web-modules/spring-mvc-forms-jsp/README.md similarity index 82% rename from spring-mvc-forms-jsp/README.md rename to spring-web-modules/spring-mvc-forms-jsp/README.md index 2c077f5171..afbf7afe40 100644 --- a/spring-mvc-forms-jsp/README.md +++ b/spring-web-modules/spring-mvc-forms-jsp/README.md @@ -7,3 +7,4 @@ This module contains articles about Spring MVC Forms using JSP - [Getting Started with Forms in Spring MVC](https://www.baeldung.com/spring-mvc-form-tutorial) - [Form Validation with AngularJS and Spring MVC](https://www.baeldung.com/validation-angularjs-spring-mvc) - [A Guide to the JSTL Library](https://www.baeldung.com/jstl) +- [Multiple Submit Buttons on a Form](https://www.baeldung.com/spring-form-multiple-submit-buttons) diff --git a/spring-mvc-forms-jsp/pom.xml b/spring-web-modules/spring-mvc-forms-jsp/pom.xml similarity index 96% rename from spring-mvc-forms-jsp/pom.xml rename to spring-web-modules/spring-mvc-forms-jsp/pom.xml index 4e1c2516f6..0ca23bd6cb 100644 --- a/spring-mvc-forms-jsp/pom.xml +++ b/spring-web-modules/spring-mvc-forms-jsp/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-spring-5 0.0.1-SNAPSHOT - ../parent-spring-5 + ../../parent-spring-5 @@ -54,7 +54,7 @@ commons-fileupload commons-fileupload - ${fileupload.version} + ${commons-fileupload.version} com.fasterxml.jackson.core @@ -98,7 +98,6 @@ 6.0.10.Final - 1.3.3 5.2.5.Final 6.0.6 diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/bundles/CustomMessage_en.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/bundles/CustomMessage_en.java similarity index 100% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/bundles/CustomMessage_en.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/bundles/CustomMessage_en.java diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/bundles/CustomMessage_fr_FR.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/bundles/CustomMessage_fr_FR.java similarity index 100% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/bundles/CustomMessage_fr_FR.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/bundles/CustomMessage_fr_FR.java diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/controllers/JSTLController.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/controllers/JSTLController.java similarity index 100% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/controllers/JSTLController.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/controllers/JSTLController.java diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/dbaccess/SQLConnection.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/dbaccess/SQLConnection.java similarity index 100% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/dbaccess/SQLConnection.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/jstl/dbaccess/SQLConnection.java diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/configuration/ApplicationConfiguration.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/configuration/ApplicationConfiguration.java similarity index 100% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/configuration/ApplicationConfiguration.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/configuration/ApplicationConfiguration.java diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java similarity index 100% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/configuration/WebInitializer.java diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/CustomerController.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/CustomerController.java similarity index 100% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/CustomerController.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/CustomerController.java diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/EmployeeController.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/EmployeeController.java similarity index 79% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/EmployeeController.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/EmployeeController.java index 3ece77bb18..478b3532fe 100644 --- a/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/EmployeeController.java +++ b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/EmployeeController.java @@ -26,7 +26,7 @@ public class EmployeeController { return employeeMap.get(Id); } - @RequestMapping(value = "/addEmployee", method = RequestMethod.POST) + @RequestMapping(value = "/addEmployee", method = RequestMethod.POST, params = "submit") public String submit(@Valid @ModelAttribute("employee") final Employee employee, final BindingResult result, final ModelMap model) { if (result.hasErrors()) { return "error"; @@ -37,5 +37,11 @@ public class EmployeeController { employeeMap.put(employee.getId(), employee); return "employeeView"; } + + @RequestMapping(value = "/addEmployee", method = RequestMethod.POST, params = "cancel") + public String cancel(@Valid @ModelAttribute("employee") final Employee employee, final BindingResult result, final ModelMap model) { + model.addAttribute("message", "You clicked cancel, please re-enter employee details:"); + return "employeeHome"; + } } diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/FileUploadController.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/FileUploadController.java similarity index 100% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/FileUploadController.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/FileUploadController.java diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/UserController.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/UserController.java similarity index 100% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/UserController.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/controller/UserController.java diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/Customer.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/Customer.java similarity index 100% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/Customer.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/Customer.java diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/Employee.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/Employee.java similarity index 100% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/Employee.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/Employee.java diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/User.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/User.java similarity index 100% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/User.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/domain/User.java diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/interceptor/FileUploadExceptionAdvice.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/interceptor/FileUploadExceptionAdvice.java similarity index 100% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/interceptor/FileUploadExceptionAdvice.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/interceptor/FileUploadExceptionAdvice.java diff --git a/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/validator/CustomerValidator.java b/spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/validator/CustomerValidator.java similarity index 100% rename from spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/validator/CustomerValidator.java rename to spring-web-modules/spring-mvc-forms-jsp/src/main/java/com/baeldung/springmvcforms/validator/CustomerValidator.java diff --git a/spring-reactive-kotlin/src/main/resources/logback.xml b/spring-web-modules/spring-mvc-forms-jsp/src/main/resources/logback.xml similarity index 100% rename from spring-reactive-kotlin/src/main/resources/logback.xml rename to spring-web-modules/spring-mvc-forms-jsp/src/main/resources/logback.xml diff --git a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/html/user.html b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/html/user.html similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/WEB-INF/html/user.html rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/html/user.html diff --git a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/items.xsl b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/items.xsl similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/WEB-INF/items.xsl rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/items.xsl diff --git a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/core_tags.jsp b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/core_tags.jsp similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/core_tags.jsp rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/core_tags.jsp diff --git a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/core_tags_redirect.jsp b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/core_tags_redirect.jsp similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/core_tags_redirect.jsp rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/core_tags_redirect.jsp diff --git a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/customerHome.jsp b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/customerHome.jsp similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/customerHome.jsp rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/customerHome.jsp diff --git a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/customerView.jsp b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/customerView.jsp similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/customerView.jsp rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/customerView.jsp diff --git a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/employeeHome.jsp b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/employeeHome.jsp similarity index 84% rename from spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/employeeHome.jsp rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/employeeHome.jsp index 5ed572000a..82f2cbae00 100644 --- a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/employeeHome.jsp +++ b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/employeeHome.jsp @@ -7,6 +7,7 @@

Welcome, Enter The Employee Details

+

${message}

@@ -23,7 +24,8 @@ - + +
diff --git a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/employeeView.jsp b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/employeeView.jsp similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/employeeView.jsp rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/employeeView.jsp diff --git a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/error.jsp b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/error.jsp similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/error.jsp rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/error.jsp diff --git a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/file.jsp b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/file.jsp similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/file.jsp rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/file.jsp diff --git a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/formatting_tags.jsp b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/formatting_tags.jsp similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/formatting_tags.jsp rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/formatting_tags.jsp diff --git a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/function_tags.jsp b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/function_tags.jsp similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/function_tags.jsp rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/function_tags.jsp diff --git a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/sql_tags.jsp b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/sql_tags.jsp similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/sql_tags.jsp rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/sql_tags.jsp diff --git a/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/xml_tags.jsp b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/xml_tags.jsp similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/xml_tags.jsp rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/WEB-INF/views/xml_tags.jsp diff --git a/spring-mvc-forms-jsp/src/main/webapp/css/user.css b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/css/user.css similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/css/user.css rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/css/user.css diff --git a/spring-mvc-forms-jsp/src/main/webapp/js/app.js b/spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/js/app.js similarity index 100% rename from spring-mvc-forms-jsp/src/main/webapp/js/app.js rename to spring-web-modules/spring-mvc-forms-jsp/src/main/webapp/js/app.js diff --git a/spring-mvc-forms-jsp/src/test/java/org/baeldung/SpringContextTest.java b/spring-web-modules/spring-mvc-forms-jsp/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-mvc-forms-jsp/src/test/java/org/baeldung/SpringContextTest.java rename to spring-web-modules/spring-mvc-forms-jsp/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-mvc-forms-thymeleaf/README.md b/spring-web-modules/spring-mvc-forms-thymeleaf/README.md similarity index 100% rename from spring-mvc-forms-thymeleaf/README.md rename to spring-web-modules/spring-mvc-forms-thymeleaf/README.md diff --git a/spring-mvc-forms-thymeleaf/pom.xml b/spring-web-modules/spring-mvc-forms-thymeleaf/pom.xml similarity index 96% rename from spring-mvc-forms-thymeleaf/pom.xml rename to spring-web-modules/spring-mvc-forms-thymeleaf/pom.xml index 2aed7f70ad..641f64b93c 100644 --- a/spring-mvc-forms-thymeleaf/pom.xml +++ b/spring-web-modules/spring-mvc-forms-thymeleaf/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 diff --git a/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/Book.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/Book.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/Book.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/Book.java diff --git a/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/BookService.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/BookService.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/BookService.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/BookService.java diff --git a/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/BooksCreationDto.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/BooksCreationDto.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/BooksCreationDto.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/BooksCreationDto.java diff --git a/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/Config.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/Config.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/Config.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/Config.java diff --git a/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/InMemoryBookService.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/InMemoryBookService.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/InMemoryBookService.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/InMemoryBookService.java diff --git a/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/ListBindingApplication.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/ListBindingApplication.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/ListBindingApplication.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/ListBindingApplication.java diff --git a/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/MultipleBooksController.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/MultipleBooksController.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/MultipleBooksController.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/listbindingexample/MultipleBooksController.java diff --git a/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/Config.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/Config.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/Config.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/Config.java diff --git a/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/SessionAttrsApplication.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/SessionAttrsApplication.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/SessionAttrsApplication.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/SessionAttrsApplication.java diff --git a/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxy.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxy.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxy.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxy.java diff --git a/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributes.java diff --git a/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoItem.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoItem.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoItem.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoItem.java diff --git a/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoList.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoList.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoList.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/java/com/baeldung/sessionattrs/TodoList.java diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/application.properties b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/application.properties similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/resources/application.properties rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/application.properties diff --git a/spring-rest-angular/src/main/resources/logback.xml b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/logback.xml similarity index 100% rename from spring-rest-angular/src/main/resources/logback.xml rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/logback.xml diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/templates/books/allBooks.html b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/books/allBooks.html similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/resources/templates/books/allBooks.html rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/books/allBooks.html diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/templates/books/createBooksForm.html b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/books/createBooksForm.html similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/resources/templates/books/createBooksForm.html rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/books/createBooksForm.html diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/templates/books/editBooksForm.html b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/books/editBooksForm.html similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/resources/templates/books/editBooksForm.html rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/books/editBooksForm.html diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/templates/books/index.html b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/books/index.html similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/resources/templates/books/index.html rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/books/index.html diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/index.html b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/index.html similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/index.html rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/index.html diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxyform.html b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxyform.html similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxyform.html rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxyform.html diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxytodos.html b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxytodos.html similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxytodos.html rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/scopedproxytodos.html diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributesform.html b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributesform.html similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributesform.html rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributesform.html diff --git a/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributestodos.html b/spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributestodos.html similarity index 100% rename from spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributestodos.html rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/main/resources/templates/sessionattrs/sessionattributestodos.html diff --git a/spring-mvc-forms-thymeleaf/src/test/java/org/baeldung/listbindingexample/SpringContextTest.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/listbindingexample/SpringContextTest.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/test/java/org/baeldung/listbindingexample/SpringContextTest.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/listbindingexample/SpringContextTest.java diff --git a/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/SessionAttrsApplicationIntegrationTest.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/SessionAttrsApplicationIntegrationTest.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/SessionAttrsApplicationIntegrationTest.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/SessionAttrsApplicationIntegrationTest.java diff --git a/spring-mvc-forms-thymeleaf/src/test/java/org/baeldung/sessionattrs/SpringContextTest.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/SpringContextTest.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/test/java/org/baeldung/sessionattrs/SpringContextTest.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/SpringContextTest.java diff --git a/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TestConfig.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TestConfig.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TestConfig.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TestConfig.java diff --git a/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxyIntegrationTest.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxyIntegrationTest.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxyIntegrationTest.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithScopedProxyIntegrationTest.java diff --git a/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributesIntegrationTest.java b/spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributesIntegrationTest.java similarity index 100% rename from spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributesIntegrationTest.java rename to spring-web-modules/spring-mvc-forms-thymeleaf/src/test/java/com/baeldung/sessionattrs/TodoControllerWithSessionAttributesIntegrationTest.java diff --git a/spring-mvc-crash/.gitignore b/spring-web-modules/spring-mvc-java-2/.gitignore similarity index 100% rename from spring-mvc-crash/.gitignore rename to spring-web-modules/spring-mvc-java-2/.gitignore diff --git a/spring-mvc-java-2/README.md b/spring-web-modules/spring-mvc-java-2/README.md similarity index 100% rename from spring-mvc-java-2/README.md rename to spring-web-modules/spring-mvc-java-2/README.md diff --git a/spring-mvc-java-2/pom.xml b/spring-web-modules/spring-mvc-java-2/pom.xml similarity index 97% rename from spring-mvc-java-2/pom.xml rename to spring-web-modules/spring-mvc-java-2/pom.xml index 533a24771a..8a025defac 100644 --- a/spring-mvc-java-2/pom.xml +++ b/spring-web-modules/spring-mvc-java-2/pom.xml @@ -12,7 +12,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/cache/CacheControlController.java b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/cache/CacheControlController.java similarity index 100% rename from spring-mvc-java-2/src/main/java/com/baeldung/cache/CacheControlController.java rename to spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/cache/CacheControlController.java diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/cache/CacheWebConfig.java b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/cache/CacheWebConfig.java similarity index 100% rename from spring-mvc-java-2/src/main/java/com/baeldung/cache/CacheWebConfig.java rename to spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/cache/CacheWebConfig.java diff --git a/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/datetime/DateTimeConfig.java b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/datetime/DateTimeConfig.java new file mode 100644 index 0000000000..c89b043486 --- /dev/null +++ b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/datetime/DateTimeConfig.java @@ -0,0 +1,36 @@ +package com.baeldung.datetime; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.format.datetime.DateFormatter; +import org.springframework.format.datetime.DateFormatterRegistrar; +import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar; +import org.springframework.format.number.NumberFormatAnnotationFormatterFactory; +import org.springframework.format.support.DefaultFormattingConversionService; +import org.springframework.format.support.FormattingConversionService; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; + +import java.time.format.DateTimeFormatter; + +@Configuration +public class DateTimeConfig extends WebMvcConfigurationSupport { + + @Bean + @Override + public FormattingConversionService mvcConversionService() { + DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false); + + conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory()); + + DateTimeFormatterRegistrar dateTimeRegistrar = new DateTimeFormatterRegistrar(); + dateTimeRegistrar.setDateFormatter(DateTimeFormatter.ofPattern("dd.MM.yyyy")); + dateTimeRegistrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss")); + dateTimeRegistrar.registerFormatters(conversionService); + + DateFormatterRegistrar dateRegistrar = new DateFormatterRegistrar(); + dateRegistrar.setFormatter(new DateFormatter("dd.MM.yyyy")); + dateRegistrar.registerFormatters(conversionService); + + return conversionService; + } +} \ No newline at end of file diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/datetime/DateTimeController.java b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/datetime/DateTimeController.java similarity index 100% rename from spring-mvc-java-2/src/main/java/com/baeldung/datetime/DateTimeController.java rename to spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/datetime/DateTimeController.java diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/matrix/config/MatrixWebConfig.java b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/matrix/config/MatrixWebConfig.java similarity index 100% rename from spring-mvc-java-2/src/main/java/com/baeldung/matrix/config/MatrixWebConfig.java rename to spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/matrix/config/MatrixWebConfig.java diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/CompanyController.java b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/CompanyController.java similarity index 100% rename from spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/CompanyController.java rename to spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/CompanyController.java diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/EmployeeController.java b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/EmployeeController.java similarity index 100% rename from spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/EmployeeController.java rename to spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/matrix/controller/EmployeeController.java diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/matrix/model/Company.java b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/matrix/model/Company.java similarity index 100% rename from spring-mvc-java-2/src/main/java/com/baeldung/matrix/model/Company.java rename to spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/matrix/model/Company.java diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/matrix/model/Employee.java b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/matrix/model/Employee.java similarity index 100% rename from spring-mvc-java-2/src/main/java/com/baeldung/matrix/model/Employee.java rename to spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/matrix/model/Employee.java diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/multiparttesting/MultipartPostRequestController.java b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/multiparttesting/MultipartPostRequestController.java similarity index 100% rename from spring-mvc-java-2/src/main/java/com/baeldung/multiparttesting/MultipartPostRequestController.java rename to spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/multiparttesting/MultipartPostRequestController.java diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/pathvariable.dottruncated/CustomWebMvcConfigurationSupport.java b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/pathvariable.dottruncated/CustomWebMvcConfigurationSupport.java similarity index 100% rename from spring-mvc-java-2/src/main/java/com/baeldung/pathvariable.dottruncated/CustomWebMvcConfigurationSupport.java rename to spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/pathvariable.dottruncated/CustomWebMvcConfigurationSupport.java diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/pathvariable.dottruncated/SiteController.java b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/pathvariable.dottruncated/SiteController.java similarity index 100% rename from spring-mvc-java-2/src/main/java/com/baeldung/pathvariable.dottruncated/SiteController.java rename to spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/pathvariable.dottruncated/SiteController.java diff --git a/spring-mvc-java-2/src/main/java/com/baeldung/pathvariable/PathVariableAnnotationController.java b/spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/pathvariable/PathVariableAnnotationController.java similarity index 100% rename from spring-mvc-java-2/src/main/java/com/baeldung/pathvariable/PathVariableAnnotationController.java rename to spring-web-modules/spring-mvc-java-2/src/main/java/com/baeldung/pathvariable/PathVariableAnnotationController.java diff --git a/spring-mvc-java-2/src/main/resources/targetFile.tmp b/spring-web-modules/spring-mvc-java-2/src/main/resources/targetFile.tmp similarity index 100% rename from spring-mvc-java-2/src/main/resources/targetFile.tmp rename to spring-web-modules/spring-mvc-java-2/src/main/resources/targetFile.tmp diff --git a/spring-mvc-java-2/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-web-modules/spring-mvc-java-2/src/main/webapp/WEB-INF/mvc-servlet.xml similarity index 100% rename from spring-mvc-java-2/src/main/webapp/WEB-INF/mvc-servlet.xml rename to spring-web-modules/spring-mvc-java-2/src/main/webapp/WEB-INF/mvc-servlet.xml diff --git a/spring-mvc-java-2/src/main/webapp/WEB-INF/view/companyHome.jsp b/spring-web-modules/spring-mvc-java-2/src/main/webapp/WEB-INF/view/companyHome.jsp similarity index 100% rename from spring-mvc-java-2/src/main/webapp/WEB-INF/view/companyHome.jsp rename to spring-web-modules/spring-mvc-java-2/src/main/webapp/WEB-INF/view/companyHome.jsp diff --git a/spring-mvc-java-2/src/main/webapp/WEB-INF/view/companyView.jsp b/spring-web-modules/spring-mvc-java-2/src/main/webapp/WEB-INF/view/companyView.jsp similarity index 100% rename from spring-mvc-java-2/src/main/webapp/WEB-INF/view/companyView.jsp rename to spring-web-modules/spring-mvc-java-2/src/main/webapp/WEB-INF/view/companyView.jsp diff --git a/spring-mvc-java-2/src/main/webapp/WEB-INF/view/employeeHome.jsp b/spring-web-modules/spring-mvc-java-2/src/main/webapp/WEB-INF/view/employeeHome.jsp similarity index 100% rename from spring-mvc-java-2/src/main/webapp/WEB-INF/view/employeeHome.jsp rename to spring-web-modules/spring-mvc-java-2/src/main/webapp/WEB-INF/view/employeeHome.jsp diff --git a/spring-mvc-java-2/src/main/webapp/WEB-INF/view/employeeView.jsp b/spring-web-modules/spring-mvc-java-2/src/main/webapp/WEB-INF/view/employeeView.jsp similarity index 100% rename from spring-mvc-java-2/src/main/webapp/WEB-INF/view/employeeView.jsp rename to spring-web-modules/spring-mvc-java-2/src/main/webapp/WEB-INF/view/employeeView.jsp diff --git a/spring-mvc-java-2/src/main/webapp/WEB-INF/web.xml b/spring-web-modules/spring-mvc-java-2/src/main/webapp/WEB-INF/web.xml similarity index 100% rename from spring-mvc-java-2/src/main/webapp/WEB-INF/web.xml rename to spring-web-modules/spring-mvc-java-2/src/main/webapp/WEB-INF/web.xml diff --git a/spring-web-modules/spring-mvc-java-2/src/main/webapp/resources/hello.css b/spring-web-modules/spring-mvc-java-2/src/main/webapp/resources/hello.css new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-mvc-java-2/src/test/java/com/baeldung/cache/CacheControlControllerIntegrationTest.java b/spring-web-modules/spring-mvc-java-2/src/test/java/com/baeldung/cache/CacheControlControllerIntegrationTest.java similarity index 100% rename from spring-mvc-java-2/src/test/java/com/baeldung/cache/CacheControlControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-java-2/src/test/java/com/baeldung/cache/CacheControlControllerIntegrationTest.java diff --git a/spring-mvc-java-2/src/test/java/com/baeldung/matrix/EmployeeMvcIntegrationTest.java b/spring-web-modules/spring-mvc-java-2/src/test/java/com/baeldung/matrix/EmployeeMvcIntegrationTest.java similarity index 100% rename from spring-mvc-java-2/src/test/java/com/baeldung/matrix/EmployeeMvcIntegrationTest.java rename to spring-web-modules/spring-mvc-java-2/src/test/java/com/baeldung/matrix/EmployeeMvcIntegrationTest.java diff --git a/spring-mvc-java-2/src/test/java/com/baeldung/matrix/EmployeeNoMvcIntegrationTest.java b/spring-web-modules/spring-mvc-java-2/src/test/java/com/baeldung/matrix/EmployeeNoMvcIntegrationTest.java similarity index 100% rename from spring-mvc-java-2/src/test/java/com/baeldung/matrix/EmployeeNoMvcIntegrationTest.java rename to spring-web-modules/spring-mvc-java-2/src/test/java/com/baeldung/matrix/EmployeeNoMvcIntegrationTest.java diff --git a/spring-mvc-java-2/src/test/java/com/baeldung/multipart/file/ConvertMultipartFileUnitTest.java b/spring-web-modules/spring-mvc-java-2/src/test/java/com/baeldung/multipart/file/ConvertMultipartFileUnitTest.java similarity index 100% rename from spring-mvc-java-2/src/test/java/com/baeldung/multipart/file/ConvertMultipartFileUnitTest.java rename to spring-web-modules/spring-mvc-java-2/src/test/java/com/baeldung/multipart/file/ConvertMultipartFileUnitTest.java diff --git a/spring-mvc-java-2/src/test/java/com/baeldung/multiparttesting/MultipartPostRequestControllerUnitTest.java b/spring-web-modules/spring-mvc-java-2/src/test/java/com/baeldung/multiparttesting/MultipartPostRequestControllerUnitTest.java similarity index 100% rename from spring-mvc-java-2/src/test/java/com/baeldung/multiparttesting/MultipartPostRequestControllerUnitTest.java rename to spring-web-modules/spring-mvc-java-2/src/test/java/com/baeldung/multiparttesting/MultipartPostRequestControllerUnitTest.java diff --git a/spring-mvc-java-2/.gitignore b/spring-web-modules/spring-mvc-java/.gitignore similarity index 100% rename from spring-mvc-java-2/.gitignore rename to spring-web-modules/spring-mvc-java/.gitignore diff --git a/spring-mvc-java/README.md b/spring-web-modules/spring-mvc-java/README.md similarity index 92% rename from spring-mvc-java/README.md rename to spring-web-modules/spring-mvc-java/README.md index 877d92901a..afd1aea3bf 100644 --- a/spring-mvc-java/README.md +++ b/spring-web-modules/spring-mvc-java/README.md @@ -4,7 +4,7 @@ This module contains articles about Spring MVC with Java configuration ### The Course -The "REST With Spring" Classes: http://bit.ly/restwithspring +The "REST With Spring" Classes: https://bit.ly/restwithspring ### Relevant Articles: - [Integration Testing in Spring](https://www.baeldung.com/integration-testing-in-spring) diff --git a/spring-mvc-java/persons.xls b/spring-web-modules/spring-mvc-java/persons.xls similarity index 100% rename from spring-mvc-java/persons.xls rename to spring-web-modules/spring-mvc-java/persons.xls diff --git a/spring-mvc-java/persons.xlsx b/spring-web-modules/spring-mvc-java/persons.xlsx similarity index 100% rename from spring-mvc-java/persons.xlsx rename to spring-web-modules/spring-mvc-java/persons.xlsx diff --git a/spring-mvc-java/pom.xml b/spring-web-modules/spring-mvc-java/pom.xml similarity index 97% rename from spring-mvc-java/pom.xml rename to spring-web-modules/spring-mvc-java/pom.xml index a45e9c8521..1324511215 100644 --- a/spring-mvc-java/pom.xml +++ b/spring-web-modules/spring-mvc-java/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 @@ -234,10 +234,6 @@ 19.0 - 3.5 - 1.3.2 - 2.5 - 1.4 2.2.0 diff --git a/spring-mvc-java/src/main/java/com/baeldung/SpringMVCApplication.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/SpringMVCApplication.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/SpringMVCApplication.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/SpringMVCApplication.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/accessparamsjs/App.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/accessparamsjs/App.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/accessparamsjs/App.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/accessparamsjs/App.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/accessparamsjs/Controller.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/accessparamsjs/Controller.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/accessparamsjs/Controller.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/accessparamsjs/Controller.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/cache/BookService.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/cache/BookService.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/cache/BookService.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/cache/BookService.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/cache/CustomKeyGenerator.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/cache/CustomKeyGenerator.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/cache/CustomKeyGenerator.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/cache/CustomKeyGenerator.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/excel/ExcelPOIHelper.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/excel/ExcelPOIHelper.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/excel/ExcelPOIHelper.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/excel/ExcelPOIHelper.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/excel/MyCell.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/excel/MyCell.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/excel/MyCell.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/excel/MyCell.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/filters/EmptyParamFilter.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/filters/EmptyParamFilter.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/filters/EmptyParamFilter.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/filters/EmptyParamFilter.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/listeners/AppListener.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/listeners/AppListener.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/listeners/AppListener.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/listeners/AppListener.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/listeners/RequestListener.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/listeners/RequestListener.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/listeners/RequestListener.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/listeners/RequestListener.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/Article.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/model/Article.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/model/Article.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/model/Article.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/Book.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/model/Book.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/model/Book.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/model/Book.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/FormDataWithFile.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/model/FormDataWithFile.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/model/FormDataWithFile.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/model/FormDataWithFile.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/Greeting.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/model/Greeting.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/model/Greeting.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/model/Greeting.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/model/User.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/model/User.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/model/User.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/model/User.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/servlets/CounterServlet.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/servlets/CounterServlet.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/servlets/CounterServlet.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/servlets/CounterServlet.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/servlets/UppercaseServlet.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/servlets/UppercaseServlet.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/servlets/UppercaseServlet.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/servlets/UppercaseServlet.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ApplicationCacheConfig.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ApplicationCacheConfig.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ApplicationCacheConfig.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/ApplicationCacheConfig.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/MainWebAppInitializer.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/spring/web/config/WebConfig.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/BeanA.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/BeanA.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/BeanA.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/BeanA.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/BeanB.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/BeanB.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/BeanB.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/BeanB.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/ExcelController.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/ExcelController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/ExcelController.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/ExcelController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/FileUploadController.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/FileUploadController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/FileUploadController.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/FileUploadController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/GreetController.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/GreetController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/GreetController.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/GreetController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/ImageController.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/ImageController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/ImageController.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/ImageController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/MultipartFileUploadStubController.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/MultipartFileUploadStubController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/MultipartFileUploadStubController.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/MultipartFileUploadStubController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/SampleController.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/SampleController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/SampleController.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/SampleController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/UserController.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/UserController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/UserController.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/UserController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/message/MessageController.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/message/MessageController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/message/MessageController.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/message/MessageController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerController.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerController.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithMapParamController.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithMapParamController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithMapParamController.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithMapParamController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithOptionalParamController.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithOptionalParamController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithOptionalParamController.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithOptionalParamController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithRequiredAttributeController.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithRequiredAttributeController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithRequiredAttributeController.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithRequiredAttributeController.java diff --git a/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java b/spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java similarity index 100% rename from spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java rename to spring-web-modules/spring-mvc-java/src/main/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsController.java diff --git a/spring-mvc-java/src/main/resources/annotations.properties b/spring-web-modules/spring-mvc-java/src/main/resources/annotations.properties similarity index 100% rename from spring-mvc-java/src/main/resources/annotations.properties rename to spring-web-modules/spring-mvc-java/src/main/resources/annotations.properties diff --git a/spring-mvc-java/src/main/resources/annotations.xml b/spring-web-modules/spring-mvc-java/src/main/resources/annotations.xml similarity index 100% rename from spring-mvc-java/src/main/resources/annotations.xml rename to spring-web-modules/spring-mvc-java/src/main/resources/annotations.xml diff --git a/spring-mvc-java/src/main/resources/application.properties b/spring-web-modules/spring-mvc-java/src/main/resources/application.properties similarity index 100% rename from spring-mvc-java/src/main/resources/application.properties rename to spring-web-modules/spring-mvc-java/src/main/resources/application.properties diff --git a/spring-mvc-java/src/main/resources/logback.xml b/spring-web-modules/spring-mvc-java/src/main/resources/logback.xml similarity index 100% rename from spring-mvc-java/src/main/resources/logback.xml rename to spring-web-modules/spring-mvc-java/src/main/resources/logback.xml diff --git a/spring-mvc-java/src/main/resources/messages_en.properties b/spring-web-modules/spring-mvc-java/src/main/resources/messages_en.properties similarity index 100% rename from spring-mvc-java/src/main/resources/messages_en.properties rename to spring-web-modules/spring-mvc-java/src/main/resources/messages_en.properties diff --git a/spring-mvc-java/src/main/resources/mvc-configuration.xml b/spring-web-modules/spring-mvc-java/src/main/resources/mvc-configuration.xml similarity index 100% rename from spring-mvc-java/src/main/resources/mvc-configuration.xml rename to spring-web-modules/spring-mvc-java/src/main/resources/mvc-configuration.xml diff --git a/spring-mvc-java/src/main/resources/templates/thymeleaf/index.html b/spring-web-modules/spring-mvc-java/src/main/resources/templates/thymeleaf/index.html similarity index 100% rename from spring-mvc-java/src/main/resources/templates/thymeleaf/index.html rename to spring-web-modules/spring-mvc-java/src/main/resources/templates/thymeleaf/index.html diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/images/image-example.jpg b/spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/images/image-example.jpg similarity index 100% rename from spring-mvc-java/src/main/webapp/WEB-INF/images/image-example.jpg rename to spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/images/image-example.jpg diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/jsp/index.jsp b/spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/jsp/index.jsp similarity index 100% rename from spring-mvc-java/src/main/webapp/WEB-INF/jsp/index.jsp rename to spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/jsp/index.jsp diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/mvc-servlet.xml similarity index 100% rename from spring-mvc-java/src/main/webapp/WEB-INF/mvc-servlet.xml rename to spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/mvc-servlet.xml diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/templates/footer.html b/spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/templates/footer.html similarity index 100% rename from spring-mvc-java/src/main/webapp/WEB-INF/templates/footer.html rename to spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/templates/footer.html diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/templates/hello.html b/spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/templates/hello.html similarity index 100% rename from spring-mvc-java/src/main/webapp/WEB-INF/templates/hello.html rename to spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/templates/hello.html diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/templates/index.html b/spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/templates/index.html similarity index 100% rename from spring-mvc-java/src/main/webapp/WEB-INF/templates/index.html rename to spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/templates/index.html diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/templates/message.html b/spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/templates/message.html similarity index 100% rename from spring-mvc-java/src/main/webapp/WEB-INF/templates/message.html rename to spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/templates/message.html diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/excel.jsp b/spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/view/excel.jsp similarity index 100% rename from spring-mvc-java/src/main/webapp/WEB-INF/view/excel.jsp rename to spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/view/excel.jsp diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadForm.jsp b/spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadForm.jsp similarity index 100% rename from spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadForm.jsp rename to spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadForm.jsp diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadView.jsp b/spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadView.jsp similarity index 100% rename from spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadView.jsp rename to spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/view/fileUploadView.jsp diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/index.jsp b/spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/view/index.jsp similarity index 100% rename from spring-mvc-java/src/main/webapp/WEB-INF/view/index.jsp rename to spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/view/index.jsp diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/view/sample.jsp b/spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/view/sample.jsp similarity index 100% rename from spring-mvc-java/src/main/webapp/WEB-INF/view/sample.jsp rename to spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/view/sample.jsp diff --git a/spring-mvc-java/src/main/webapp/WEB-INF/web_old.xml b/spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/web_old.xml similarity index 100% rename from spring-mvc-java/src/main/webapp/WEB-INF/web_old.xml rename to spring-web-modules/spring-mvc-java/src/main/webapp/WEB-INF/web_old.xml diff --git a/spring-mvc-java/src/main/webapp/js/jquery.js b/spring-web-modules/spring-mvc-java/src/main/webapp/js/jquery.js similarity index 100% rename from spring-mvc-java/src/main/webapp/js/jquery.js rename to spring-web-modules/spring-mvc-java/src/main/webapp/js/jquery.js diff --git a/spring-mvc-java/src/main/webapp/js/script-async-jquery.js b/spring-web-modules/spring-mvc-java/src/main/webapp/js/script-async-jquery.js similarity index 100% rename from spring-mvc-java/src/main/webapp/js/script-async-jquery.js rename to spring-web-modules/spring-mvc-java/src/main/webapp/js/script-async-jquery.js diff --git a/spring-mvc-java/src/main/webapp/js/script-async.js b/spring-web-modules/spring-mvc-java/src/main/webapp/js/script-async.js similarity index 100% rename from spring-mvc-java/src/main/webapp/js/script-async.js rename to spring-web-modules/spring-mvc-java/src/main/webapp/js/script-async.js diff --git a/spring-mvc-java/src/main/webapp/js/script.js b/spring-web-modules/spring-mvc-java/src/main/webapp/js/script.js similarity index 100% rename from spring-mvc-java/src/main/webapp/js/script.js rename to spring-web-modules/spring-mvc-java/src/main/webapp/js/script.js diff --git a/spring-mvc-java/src/test/java/com/baeldung/accessparamsjs/ControllerUnitTest.java b/spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/accessparamsjs/ControllerUnitTest.java similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/accessparamsjs/ControllerUnitTest.java rename to spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/accessparamsjs/ControllerUnitTest.java diff --git a/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitAndJUnitLiveTest.java b/spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitAndJUnitLiveTest.java similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitAndJUnitLiveTest.java rename to spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitAndJUnitLiveTest.java diff --git a/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitAndSpringLiveTest.java b/spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitAndSpringLiveTest.java similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitAndSpringLiveTest.java rename to spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitAndSpringLiveTest.java diff --git a/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitWebScrapingLiveTest.java b/spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitWebScrapingLiveTest.java similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitWebScrapingLiveTest.java rename to spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/htmlunit/HtmlUnitWebScrapingLiveTest.java diff --git a/spring-mvc-java/src/test/java/com/baeldung/htmlunit/TestConfig.java b/spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/htmlunit/TestConfig.java similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/htmlunit/TestConfig.java rename to spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/htmlunit/TestConfig.java diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java b/spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerRealIntegrationTest.java b/spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerRealIntegrationTest.java similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerRealIntegrationTest.java rename to spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerRealIntegrationTest.java diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerUnitTest.java b/spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerUnitTest.java similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerUnitTest.java rename to spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerUnitTest.java diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/README.md b/spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/README.md similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/web/controller/README.md rename to spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/README.md diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerControllerIntegrationTest.java b/spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerControllerIntegrationTest.java similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerControllerIntegrationTest.java diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java b/spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java rename to spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerControllerWithOptionalParamIntegrationTest.java diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java b/spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java rename to spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerControllerWithRequiredAttributeIntegrationTest.java diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java b/spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java rename to spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithMapParamIntegrationTest.java diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java b/spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java similarity index 100% rename from spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java rename to spring-web-modules/spring-mvc-java/src/test/java/com/baeldung/web/controller/optionalpathvars/ArticleViewerWithTwoSeparateMethodsIntegrationTest.java diff --git a/spring-mvc-java/.gitignore b/spring-web-modules/spring-mvc-java/src/test/resources/.gitignore similarity index 100% rename from spring-mvc-java/.gitignore rename to spring-web-modules/spring-mvc-java/src/test/resources/.gitignore diff --git a/spring-mvc-java/src/test/resources/logback-test.xml b/spring-web-modules/spring-mvc-java/src/test/resources/logback-test.xml similarity index 100% rename from spring-mvc-java/src/test/resources/logback-test.xml rename to spring-web-modules/spring-mvc-java/src/test/resources/logback-test.xml diff --git a/spring-mvc-velocity/README.md b/spring-web-modules/spring-mvc-velocity/README.md similarity index 100% rename from spring-mvc-velocity/README.md rename to spring-web-modules/spring-mvc-velocity/README.md diff --git a/spring-mvc-velocity/pom.xml b/spring-web-modules/spring-mvc-velocity/pom.xml similarity index 98% rename from spring-mvc-velocity/pom.xml rename to spring-web-modules/spring-mvc-velocity/pom.xml index 2269f05fa4..05016962a5 100644 --- a/spring-mvc-velocity/pom.xml +++ b/spring-web-modules/spring-mvc-velocity/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-spring-4 0.0.1-SNAPSHOT - ../parent-spring-4 + ../../parent-spring-4 diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java b/spring-web-modules/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java similarity index 100% rename from spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java rename to spring-web-modules/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/controller/MainController.java diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java b/spring-web-modules/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java similarity index 100% rename from spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java rename to spring-web-modules/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/domain/Tutorial.java diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/ITutorialsService.java b/spring-web-modules/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/ITutorialsService.java similarity index 100% rename from spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/ITutorialsService.java rename to spring-web-modules/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/ITutorialsService.java diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java b/spring-web-modules/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java similarity index 100% rename from spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java rename to spring-web-modules/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/service/TutorialsService.java diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/spring/config/MainWebAppInitializer.java b/spring-web-modules/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/spring/config/MainWebAppInitializer.java similarity index 100% rename from spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/spring/config/MainWebAppInitializer.java rename to spring-web-modules/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/spring/config/MainWebAppInitializer.java diff --git a/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/spring/config/WebConfig.java b/spring-web-modules/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/spring/config/WebConfig.java similarity index 100% rename from spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/spring/config/WebConfig.java rename to spring-web-modules/spring-mvc-velocity/src/main/java/com/baeldung/mvc/velocity/spring/config/WebConfig.java diff --git a/spring-rest-shell/src/main/resources/logback.xml b/spring-web-modules/spring-mvc-velocity/src/main/resources/logback.xml similarity index 100% rename from spring-rest-shell/src/main/resources/logback.xml rename to spring-web-modules/spring-mvc-velocity/src/main/resources/logback.xml diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/footer.vm b/spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/footer.vm similarity index 100% rename from spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/footer.vm rename to spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/footer.vm diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/header.vm b/spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/header.vm similarity index 100% rename from spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/header.vm rename to spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/fragments/header.vm diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/layouts/layout.vm b/spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/layouts/layout.vm similarity index 100% rename from spring-mvc-velocity/src/main/webapp/WEB-INF/layouts/layout.vm rename to spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/layouts/layout.vm diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/mvc-servlet.xml similarity index 100% rename from spring-mvc-velocity/src/main/webapp/WEB-INF/mvc-servlet.xml rename to spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/mvc-servlet.xml diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/spring-context.xml b/spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/spring-context.xml similarity index 100% rename from spring-mvc-velocity/src/main/webapp/WEB-INF/spring-context.xml rename to spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/spring-context.xml diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/views/index.vm b/spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/views/index.vm similarity index 100% rename from spring-mvc-velocity/src/main/webapp/WEB-INF/views/index.vm rename to spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/views/index.vm diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/views/list.vm b/spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/views/list.vm similarity index 100% rename from spring-mvc-velocity/src/main/webapp/WEB-INF/views/list.vm rename to spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/views/list.vm diff --git a/spring-mvc-velocity/src/main/webapp/WEB-INF/web_old.xml b/spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/web_old.xml similarity index 100% rename from spring-mvc-velocity/src/main/webapp/WEB-INF/web_old.xml rename to spring-web-modules/spring-mvc-velocity/src/main/webapp/WEB-INF/web_old.xml diff --git a/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/DataContentControllerIntegrationTest.java b/spring-web-modules/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/DataContentControllerIntegrationTest.java similarity index 100% rename from spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/DataContentControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/DataContentControllerIntegrationTest.java diff --git a/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/config/TestConfig.java b/spring-web-modules/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/config/TestConfig.java similarity index 100% rename from spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/config/TestConfig.java rename to spring-web-modules/spring-mvc-velocity/src/test/java/com/baeldung/mvc/velocity/test/config/TestConfig.java diff --git a/spring-mvc-velocity/src/test/java/org/baeldung/SpringContextTest.java b/spring-web-modules/spring-mvc-velocity/src/test/java/org/baeldung/SpringContextTest.java similarity index 100% rename from spring-mvc-velocity/src/test/java/org/baeldung/SpringContextTest.java rename to spring-web-modules/spring-mvc-velocity/src/test/java/org/baeldung/SpringContextTest.java diff --git a/spring-mvc-velocity/src/test/resources/mvc-servlet.xml b/spring-web-modules/spring-mvc-velocity/src/test/resources/mvc-servlet.xml similarity index 100% rename from spring-mvc-velocity/src/test/resources/mvc-servlet.xml rename to spring-web-modules/spring-mvc-velocity/src/test/resources/mvc-servlet.xml diff --git a/spring-mvc-views/README.md b/spring-web-modules/spring-mvc-views/README.md similarity index 100% rename from spring-mvc-views/README.md rename to spring-web-modules/spring-mvc-views/README.md diff --git a/spring-mvc-views/pom.xml b/spring-web-modules/spring-mvc-views/pom.xml similarity index 98% rename from spring-mvc-views/pom.xml rename to spring-web-modules/spring-mvc-views/pom.xml index 452805bd53..2c3be5a33e 100644 --- a/spring-mvc-views/pom.xml +++ b/spring-web-modules/spring-mvc-views/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-spring-5 0.0.1-SNAPSHOT - ../parent-spring-5 + parent-spring-5/pom.xml diff --git a/spring-mvc-views/src/main/java/com/baeldung/themes/config/DataSourceConfig.java b/spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/config/DataSourceConfig.java similarity index 100% rename from spring-mvc-views/src/main/java/com/baeldung/themes/config/DataSourceConfig.java rename to spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/config/DataSourceConfig.java diff --git a/spring-mvc-views/src/main/java/com/baeldung/themes/config/InitSecurity.java b/spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/config/InitSecurity.java similarity index 100% rename from spring-mvc-views/src/main/java/com/baeldung/themes/config/InitSecurity.java rename to spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/config/InitSecurity.java diff --git a/spring-mvc-views/src/main/java/com/baeldung/themes/config/SecurityConfig.java b/spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/config/SecurityConfig.java similarity index 100% rename from spring-mvc-views/src/main/java/com/baeldung/themes/config/SecurityConfig.java rename to spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/config/SecurityConfig.java diff --git a/spring-mvc-views/src/main/java/com/baeldung/themes/config/ThemeMVCConfig.java b/spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/config/ThemeMVCConfig.java similarity index 100% rename from spring-mvc-views/src/main/java/com/baeldung/themes/config/ThemeMVCConfig.java rename to spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/config/ThemeMVCConfig.java diff --git a/spring-mvc-views/src/main/java/com/baeldung/themes/config/TilesApplicationConfiguration.java b/spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/config/TilesApplicationConfiguration.java similarity index 100% rename from spring-mvc-views/src/main/java/com/baeldung/themes/config/TilesApplicationConfiguration.java rename to spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/config/TilesApplicationConfiguration.java diff --git a/spring-mvc-views/src/main/java/com/baeldung/themes/config/WebInitializer.java b/spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/config/WebInitializer.java similarity index 100% rename from spring-mvc-views/src/main/java/com/baeldung/themes/config/WebInitializer.java rename to spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/config/WebInitializer.java diff --git a/spring-mvc-views/src/main/java/com/baeldung/themes/controllers/AppController.java b/spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/controllers/AppController.java similarity index 100% rename from spring-mvc-views/src/main/java/com/baeldung/themes/controllers/AppController.java rename to spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/controllers/AppController.java diff --git a/spring-mvc-views/src/main/java/com/baeldung/themes/controllers/TilesController.java b/spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/controllers/TilesController.java similarity index 100% rename from spring-mvc-views/src/main/java/com/baeldung/themes/controllers/TilesController.java rename to spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/controllers/TilesController.java diff --git a/spring-mvc-views/src/main/java/com/baeldung/themes/domain/UserPreference.java b/spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/domain/UserPreference.java similarity index 100% rename from spring-mvc-views/src/main/java/com/baeldung/themes/domain/UserPreference.java rename to spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/domain/UserPreference.java diff --git a/spring-mvc-views/src/main/java/com/baeldung/themes/repository/UserPreferenceRepository.java b/spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/repository/UserPreferenceRepository.java similarity index 100% rename from spring-mvc-views/src/main/java/com/baeldung/themes/repository/UserPreferenceRepository.java rename to spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/repository/UserPreferenceRepository.java diff --git a/spring-mvc-views/src/main/java/com/baeldung/themes/resolver/UserPreferenceThemeResolver.java b/spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/resolver/UserPreferenceThemeResolver.java similarity index 100% rename from spring-mvc-views/src/main/java/com/baeldung/themes/resolver/UserPreferenceThemeResolver.java rename to spring-web-modules/spring-mvc-views/src/main/java/com/baeldung/themes/resolver/UserPreferenceThemeResolver.java diff --git a/spring-mvc-views/src/main/resources/dark.properties b/spring-web-modules/spring-mvc-views/src/main/resources/dark.properties similarity index 100% rename from spring-mvc-views/src/main/resources/dark.properties rename to spring-web-modules/spring-mvc-views/src/main/resources/dark.properties diff --git a/spring-mvc-views/src/main/resources/dark_en_US.properties b/spring-web-modules/spring-mvc-views/src/main/resources/dark_en_US.properties similarity index 100% rename from spring-mvc-views/src/main/resources/dark_en_US.properties rename to spring-web-modules/spring-mvc-views/src/main/resources/dark_en_US.properties diff --git a/spring-mvc-views/src/main/resources/db/sql/create-db.sql b/spring-web-modules/spring-mvc-views/src/main/resources/db/sql/create-db.sql similarity index 100% rename from spring-mvc-views/src/main/resources/db/sql/create-db.sql rename to spring-web-modules/spring-mvc-views/src/main/resources/db/sql/create-db.sql diff --git a/spring-mvc-views/src/main/resources/db/sql/insert-data.sql b/spring-web-modules/spring-mvc-views/src/main/resources/db/sql/insert-data.sql similarity index 100% rename from spring-mvc-views/src/main/resources/db/sql/insert-data.sql rename to spring-web-modules/spring-mvc-views/src/main/resources/db/sql/insert-data.sql diff --git a/spring-mvc-views/src/main/resources/light.properties b/spring-web-modules/spring-mvc-views/src/main/resources/light.properties similarity index 100% rename from spring-mvc-views/src/main/resources/light.properties rename to spring-web-modules/spring-mvc-views/src/main/resources/light.properties diff --git a/spring-mvc-views/src/main/resources/light_en_US.properties b/spring-web-modules/spring-mvc-views/src/main/resources/light_en_US.properties similarity index 100% rename from spring-mvc-views/src/main/resources/light_en_US.properties rename to spring-web-modules/spring-mvc-views/src/main/resources/light_en_US.properties diff --git a/spring-mvc-views/src/main/resources/themes/black.css b/spring-web-modules/spring-mvc-views/src/main/resources/themes/black.css similarity index 100% rename from spring-mvc-views/src/main/resources/themes/black.css rename to spring-web-modules/spring-mvc-views/src/main/resources/themes/black.css diff --git a/spring-mvc-views/src/main/resources/themes/white.css b/spring-web-modules/spring-mvc-views/src/main/resources/themes/white.css similarity index 100% rename from spring-mvc-views/src/main/resources/themes/white.css rename to spring-web-modules/spring-mvc-views/src/main/resources/themes/white.css diff --git a/spring-mvc-views/src/main/webapp/WEB-INF/index.jsp b/spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/index.jsp similarity index 100% rename from spring-mvc-views/src/main/webapp/WEB-INF/index.jsp rename to spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/index.jsp diff --git a/spring-mvc-views/src/main/webapp/WEB-INF/views/pages/apachetiles.jsp b/spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/pages/apachetiles.jsp similarity index 100% rename from spring-mvc-views/src/main/webapp/WEB-INF/views/pages/apachetiles.jsp rename to spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/pages/apachetiles.jsp diff --git a/spring-mvc-views/src/main/webapp/WEB-INF/views/pages/home.jsp b/spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/pages/home.jsp similarity index 100% rename from spring-mvc-views/src/main/webapp/WEB-INF/views/pages/home.jsp rename to spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/pages/home.jsp diff --git a/spring-mvc-views/src/main/webapp/WEB-INF/views/pages/springmvc.jsp b/spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/pages/springmvc.jsp similarity index 100% rename from spring-mvc-views/src/main/webapp/WEB-INF/views/pages/springmvc.jsp rename to spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/pages/springmvc.jsp diff --git a/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/layouts/defaultLayout.jsp b/spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/layouts/defaultLayout.jsp similarity index 100% rename from spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/layouts/defaultLayout.jsp rename to spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/layouts/defaultLayout.jsp diff --git a/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/templates/defaultFooter.jsp b/spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/templates/defaultFooter.jsp similarity index 100% rename from spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/templates/defaultFooter.jsp rename to spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/templates/defaultFooter.jsp diff --git a/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/templates/defaultHeader.jsp b/spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/templates/defaultHeader.jsp similarity index 100% rename from spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/templates/defaultHeader.jsp rename to spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/templates/defaultHeader.jsp diff --git a/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/templates/defaultMenu.jsp b/spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/templates/defaultMenu.jsp similarity index 100% rename from spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/templates/defaultMenu.jsp rename to spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/templates/defaultMenu.jsp diff --git a/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/tiles.xml b/spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/tiles.xml similarity index 100% rename from spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/tiles.xml rename to spring-web-modules/spring-mvc-views/src/main/webapp/WEB-INF/views/tiles/tiles.xml diff --git a/spring-mvc-views/src/main/webapp/static/css/app.css b/spring-web-modules/spring-mvc-views/src/main/webapp/static/css/app.css similarity index 100% rename from spring-mvc-views/src/main/webapp/static/css/app.css rename to spring-web-modules/spring-mvc-views/src/main/webapp/static/css/app.css diff --git a/spring-mvc-webflow/README.md b/spring-web-modules/spring-mvc-webflow/README.md similarity index 100% rename from spring-mvc-webflow/README.md rename to spring-web-modules/spring-mvc-webflow/README.md diff --git a/spring-mvc-webflow/pom.xml b/spring-web-modules/spring-mvc-webflow/pom.xml similarity index 100% rename from spring-mvc-webflow/pom.xml rename to spring-web-modules/spring-mvc-webflow/pom.xml diff --git a/spring-mvc-webflow/src/main/java/org/baeldung/servlet/WebInitializer.java b/spring-web-modules/spring-mvc-webflow/src/main/java/org/baeldung/servlet/WebInitializer.java similarity index 100% rename from spring-mvc-webflow/src/main/java/org/baeldung/servlet/WebInitializer.java rename to spring-web-modules/spring-mvc-webflow/src/main/java/org/baeldung/servlet/WebInitializer.java diff --git a/spring-mvc-webflow/src/main/java/org/baeldung/spring/WebFlowConfig.java b/spring-web-modules/spring-mvc-webflow/src/main/java/org/baeldung/spring/WebFlowConfig.java similarity index 100% rename from spring-mvc-webflow/src/main/java/org/baeldung/spring/WebFlowConfig.java rename to spring-web-modules/spring-mvc-webflow/src/main/java/org/baeldung/spring/WebFlowConfig.java diff --git a/spring-mvc-webflow/src/main/java/org/baeldung/spring/WebMvcConfig.java b/spring-web-modules/spring-mvc-webflow/src/main/java/org/baeldung/spring/WebMvcConfig.java similarity index 100% rename from spring-mvc-webflow/src/main/java/org/baeldung/spring/WebMvcConfig.java rename to spring-web-modules/spring-mvc-webflow/src/main/java/org/baeldung/spring/WebMvcConfig.java diff --git a/spring-mvc-webflow/src/main/resources/flow-definition.xml b/spring-web-modules/spring-mvc-webflow/src/main/resources/flow-definition.xml similarity index 100% rename from spring-mvc-webflow/src/main/resources/flow-definition.xml rename to spring-web-modules/spring-mvc-webflow/src/main/resources/flow-definition.xml diff --git a/spring-mvc-webflow/src/main/resources/logback.xml b/spring-web-modules/spring-mvc-webflow/src/main/resources/logback.xml similarity index 100% rename from spring-mvc-webflow/src/main/resources/logback.xml rename to spring-web-modules/spring-mvc-webflow/src/main/resources/logback.xml diff --git a/spring-mvc-webflow/src/main/webapp/WEB-INF/flows/activation-flow.xml b/spring-web-modules/spring-mvc-webflow/src/main/webapp/WEB-INF/flows/activation-flow.xml similarity index 100% rename from spring-mvc-webflow/src/main/webapp/WEB-INF/flows/activation-flow.xml rename to spring-web-modules/spring-mvc-webflow/src/main/webapp/WEB-INF/flows/activation-flow.xml diff --git a/spring-mvc-webflow/src/main/webapp/WEB-INF/view/activation.jsp b/spring-web-modules/spring-mvc-webflow/src/main/webapp/WEB-INF/view/activation.jsp similarity index 100% rename from spring-mvc-webflow/src/main/webapp/WEB-INF/view/activation.jsp rename to spring-web-modules/spring-mvc-webflow/src/main/webapp/WEB-INF/view/activation.jsp diff --git a/spring-mvc-webflow/src/main/webapp/WEB-INF/view/failure.jsp b/spring-web-modules/spring-mvc-webflow/src/main/webapp/WEB-INF/view/failure.jsp similarity index 100% rename from spring-mvc-webflow/src/main/webapp/WEB-INF/view/failure.jsp rename to spring-web-modules/spring-mvc-webflow/src/main/webapp/WEB-INF/view/failure.jsp diff --git a/spring-mvc-webflow/src/main/webapp/WEB-INF/view/sample.jsp b/spring-web-modules/spring-mvc-webflow/src/main/webapp/WEB-INF/view/sample.jsp similarity index 100% rename from spring-mvc-webflow/src/main/webapp/WEB-INF/view/sample.jsp rename to spring-web-modules/spring-mvc-webflow/src/main/webapp/WEB-INF/view/sample.jsp diff --git a/spring-mvc-webflow/src/main/webapp/WEB-INF/view/success.jsp b/spring-web-modules/spring-mvc-webflow/src/main/webapp/WEB-INF/view/success.jsp similarity index 100% rename from spring-mvc-webflow/src/main/webapp/WEB-INF/view/success.jsp rename to spring-web-modules/spring-mvc-webflow/src/main/webapp/WEB-INF/view/success.jsp diff --git a/spring-mvc-webflow/src/test/java/org/baeldung/SpringContextTest.java b/spring-web-modules/spring-mvc-webflow/src/test/java/org/baeldung/SpringContextTest.java similarity index 100% rename from spring-mvc-webflow/src/test/java/org/baeldung/SpringContextTest.java rename to spring-web-modules/spring-mvc-webflow/src/test/java/org/baeldung/SpringContextTest.java diff --git a/spring-mvc-java/src/test/resources/.gitignore b/spring-web-modules/spring-mvc-xml/.gitignore similarity index 100% rename from spring-mvc-java/src/test/resources/.gitignore rename to spring-web-modules/spring-mvc-xml/.gitignore diff --git a/spring-mvc-xml/README.md b/spring-web-modules/spring-mvc-xml/README.md similarity index 91% rename from spring-mvc-xml/README.md rename to spring-web-modules/spring-mvc-xml/README.md index 0adf127aaa..3fbea3626b 100644 --- a/spring-mvc-xml/README.md +++ b/spring-web-modules/spring-mvc-xml/README.md @@ -17,6 +17,7 @@ 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) +- [Introduction to Servlets and Servlet Containers](https://www.baeldung.com/java-servlets-containers-intro) ## Spring MVC with XML Configuration Example Project diff --git a/spring-mvc-xml/pom.xml b/spring-web-modules/spring-mvc-xml/pom.xml similarity index 100% rename from spring-mvc-xml/pom.xml rename to spring-web-modules/spring-mvc-xml/pom.xml diff --git a/spring-mvc-xml/src/main/java/com/baeldung/jsp/ExampleOne.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/jsp/ExampleOne.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/jsp/ExampleOne.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/jsp/ExampleOne.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/jsp/ExampleThree.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/jsp/ExampleThree.java similarity index 83% rename from spring-mvc-xml/src/main/java/com/baeldung/jsp/ExampleThree.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/jsp/ExampleThree.java index 7269f917b4..73132704c8 100644 --- a/spring-mvc-xml/src/main/java/com/baeldung/jsp/ExampleThree.java +++ b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/jsp/ExampleThree.java @@ -10,11 +10,15 @@ import javax.servlet.http.HttpServletResponse; @WebServlet(name = "ExampleThree", description = "JSP Servlet With Annotations", urlPatterns = { "/ExampleThree" }) public class ExampleThree extends HttpServlet { private static final long serialVersionUID = 1L; + + private String instanceMessage; @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String message = request.getParameter("message"); + instanceMessage = request.getParameter("message"); request.setAttribute("text", message); + request.setAttribute("unsafeText", instanceMessage); request.getRequestDispatcher("/jsp/ExampleThree.jsp").forward(request, response); } } diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfig.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfig.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfig.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfig.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/ClientWebConfigJava.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ConstraintViolationExceptionHandler.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ConstraintViolationExceptionHandler.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ConstraintViolationExceptionHandler.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ConstraintViolationExceptionHandler.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ErrorController.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ErrorController.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ErrorController.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ErrorController.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/GeoIPTestController.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/GeoIPTestController.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/controller/GeoIPTestController.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/GeoIPTestController.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/GreetingController.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/GreetingController.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/controller/GreetingController.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/GreetingController.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloController.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloController.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloController.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloController.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloGuestController.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloGuestController.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloGuestController.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloGuestController.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloWorldController.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloWorldController.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloWorldController.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/HelloWorldController.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ImageController.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ImageController.java similarity index 97% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ImageController.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ImageController.java index fc46c07e06..c02e76d4c0 100644 --- a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ImageController.java +++ b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/ImageController.java @@ -1,61 +1,61 @@ -package com.baeldung.spring.controller; - -import org.apache.commons.io.IOUtils; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.io.Resource; -import org.springframework.http.*; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.context.support.ServletContextResource; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.io.InputStream; - -@Controller -public class ImageController { - - @Autowired - private ServletContext servletContext; - - @RequestMapping(value = "/image-view", method = RequestMethod.GET) - public String imageView() throws IOException { - return "image-download"; - } - - @RequestMapping(value = "/image-manual-response", method = RequestMethod.GET) - public void getImageAsByteArray(HttpServletResponse response) throws IOException { - final InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); - response.setContentType(MediaType.IMAGE_JPEG_VALUE); - IOUtils.copy(in, response.getOutputStream()); - } - - @RequestMapping(value = "/image-byte-array", method = RequestMethod.GET) - @ResponseBody - public byte[] getImageAsByteArray() throws IOException { - final InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); - return IOUtils.toByteArray(in); - } - - @RequestMapping(value = "/image-response-entity", method = RequestMethod.GET) - public ResponseEntity getImageAsResponseEntity() throws IOException { - ResponseEntity responseEntity; - final HttpHeaders headers = new HttpHeaders(); - final InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); - byte[] media = IOUtils.toByteArray(in); - headers.setCacheControl(CacheControl.noCache().getHeaderValue()); - responseEntity = new ResponseEntity<>(media, headers, HttpStatus.OK); - return responseEntity; - } - - @RequestMapping(value = "/image-resource", method = RequestMethod.GET) - @ResponseBody - public ResponseEntity getImageAsResource() { - final HttpHeaders headers = new HttpHeaders(); - Resource resource = new ServletContextResource(servletContext, "/WEB-INF/images/image-example.jpg"); - return new ResponseEntity<>(resource, headers, HttpStatus.OK); - } -} +package com.baeldung.spring.controller; + +import org.apache.commons.io.IOUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.Resource; +import org.springframework.http.*; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.context.support.ServletContextResource; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; + +@Controller +public class ImageController { + + @Autowired + private ServletContext servletContext; + + @RequestMapping(value = "/image-view", method = RequestMethod.GET) + public String imageView() throws IOException { + return "image-download"; + } + + @RequestMapping(value = "/image-manual-response", method = RequestMethod.GET) + public void getImageAsByteArray(HttpServletResponse response) throws IOException { + final InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); + response.setContentType(MediaType.IMAGE_JPEG_VALUE); + IOUtils.copy(in, response.getOutputStream()); + } + + @RequestMapping(value = "/image-byte-array", method = RequestMethod.GET) + @ResponseBody + public byte[] getImageAsByteArray() throws IOException { + final InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); + return IOUtils.toByteArray(in); + } + + @RequestMapping(value = "/image-response-entity", method = RequestMethod.GET) + public ResponseEntity getImageAsResponseEntity() throws IOException { + ResponseEntity responseEntity; + final HttpHeaders headers = new HttpHeaders(); + final InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg"); + byte[] media = IOUtils.toByteArray(in); + headers.setCacheControl(CacheControl.noCache().getHeaderValue()); + responseEntity = new ResponseEntity<>(media, headers, HttpStatus.OK); + return responseEntity; + } + + @RequestMapping(value = "/image-resource", method = RequestMethod.GET) + @ResponseBody + public ResponseEntity getImageAsResource() { + final HttpHeaders headers = new HttpHeaders(); + Resource resource = new ServletContextResource(servletContext, "/WEB-INF/images/image-example.jpg"); + return new ResponseEntity<>(resource, headers, HttpStatus.OK); + } +} diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/PersonController.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/PersonController.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/controller/PersonController.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/PersonController.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/RequestAndPathVariableValidationController.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/WelcomeController.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/WelcomeController.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/controller/WelcomeController.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/controller/WelcomeController.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/form/GeoIP.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/form/GeoIP.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/form/GeoIP.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/form/GeoIP.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Person.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Person.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/form/Person.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/form/Person.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/service/RawDBDemoGeoIPLocationService.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/service/RawDBDemoGeoIPLocationService.java similarity index 100% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/service/RawDBDemoGeoIPLocationService.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/service/RawDBDemoGeoIPLocationService.java diff --git a/spring-mvc-xml/src/main/java/com/baeldung/spring/validator/PersonValidator.java b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/validator/PersonValidator.java similarity index 96% rename from spring-mvc-xml/src/main/java/com/baeldung/spring/validator/PersonValidator.java rename to spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/validator/PersonValidator.java index f7625bacd9..cda756cdfc 100644 --- a/spring-mvc-xml/src/main/java/com/baeldung/spring/validator/PersonValidator.java +++ b/spring-web-modules/spring-mvc-xml/src/main/java/com/baeldung/spring/validator/PersonValidator.java @@ -1,22 +1,22 @@ -package com.baeldung.spring.validator; - -import com.baeldung.spring.form.Person; -import org.springframework.stereotype.Component; -import org.springframework.validation.Errors; -import org.springframework.validation.ValidationUtils; -import org.springframework.validation.Validator; - -@Component -public class PersonValidator implements Validator { - - @Override - public boolean supports(final Class calzz) { - return Person.class.isAssignableFrom(calzz); - } - - @Override - public void validate(final Object obj, final Errors errors) { - - ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "required.name"); - } +package com.baeldung.spring.validator; + +import com.baeldung.spring.form.Person; +import org.springframework.stereotype.Component; +import org.springframework.validation.Errors; +import org.springframework.validation.ValidationUtils; +import org.springframework.validation.Validator; + +@Component +public class PersonValidator implements Validator { + + @Override + public boolean supports(final Class calzz) { + return Person.class.isAssignableFrom(calzz); + } + + @Override + public void validate(final Object obj, final Errors errors) { + + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "required.name"); + } } \ No newline at end of file diff --git a/spring-mvc-xml/src/main/resources/contentManagementWebMvcConfig.xml b/spring-web-modules/spring-mvc-xml/src/main/resources/contentManagementWebMvcConfig.xml similarity index 100% rename from spring-mvc-xml/src/main/resources/contentManagementWebMvcConfig.xml rename to spring-web-modules/spring-mvc-xml/src/main/resources/contentManagementWebMvcConfig.xml diff --git a/spring-mvc-xml/src/main/resources/logback.xml b/spring-web-modules/spring-mvc-xml/src/main/resources/logback.xml similarity index 100% rename from spring-mvc-xml/src/main/resources/logback.xml rename to spring-web-modules/spring-mvc-xml/src/main/resources/logback.xml diff --git a/spring-web-modules/spring-mvc-xml/src/main/resources/messages.properties b/spring-web-modules/spring-mvc-xml/src/main/resources/messages.properties new file mode 100644 index 0000000000..8d886c8449 --- /dev/null +++ b/spring-web-modules/spring-mvc-xml/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-xml/src/main/resources/webMvcConfig.xml b/spring-web-modules/spring-mvc-xml/src/main/resources/webMvcConfig.xml similarity index 100% rename from spring-mvc-xml/src/main/resources/webMvcConfig.xml rename to spring-web-modules/spring-mvc-xml/src/main/resources/webMvcConfig.xml diff --git a/spring-mvc-xml/src/main/webapp/GeoIpTest.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/GeoIpTest.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/GeoIpTest.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/GeoIpTest.jsp diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/crash/commands/message.groovy b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/crash/commands/message.groovy similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/crash/commands/message.groovy rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/crash/commands/message.groovy diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/crash/commands/message2.java b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/crash/commands/message2.java similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/crash/commands/message2.java rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/crash/commands/message2.java diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/crash/crash.properties b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/crash/crash.properties similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/crash/crash.properties rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/crash/crash.properties diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/crash/telnet.properties b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/crash/telnet.properties similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/crash/telnet.properties rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/crash/telnet.properties diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/images/image-example.jpg b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/images/image-example.jpg similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/images/image-example.jpg rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/images/image-example.jpg diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/mvc-servlet.xml similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/mvc-servlet.xml rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/mvc-servlet.xml diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/error.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/error.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/view/error.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/error.jsp diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/errorPage.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/errorPage.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/view/errorPage.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/errorPage.jsp diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/greeting.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/greeting.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/view/greeting.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/greeting.jsp diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/hello.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/hello.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/view/hello.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/hello.jsp diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/helloworld.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/helloworld.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/view/helloworld.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/helloworld.jsp diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/image-download.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/image-download.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/view/image-download.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/image-download.jsp diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/personForm.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/personForm.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/view/personForm.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/personForm.jsp diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/personView.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/personView.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/view/personView.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/personView.jsp diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/sample.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/sample.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/view/sample.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/sample.jsp diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/view/welcome.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/welcome.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/view/welcome.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/view/welcome.jsp diff --git a/spring-mvc-xml/src/main/webapp/WEB-INF/web.xml b/spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/web.xml similarity index 100% rename from spring-mvc-xml/src/main/webapp/WEB-INF/web.xml rename to spring-web-modules/spring-mvc-xml/src/main/webapp/WEB-INF/web.xml diff --git a/spring-mvc-xml/src/main/webapp/index.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/index.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/index.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/index.jsp diff --git a/spring-mvc-xml/src/main/webapp/jsp/ExampleThree.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/jsp/ExampleThree.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/jsp/ExampleThree.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/jsp/ExampleThree.jsp diff --git a/spring-mvc-xml/src/main/webapp/jsp/ExampleTwo.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/jsp/ExampleTwo.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/jsp/ExampleTwo.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/jsp/ExampleTwo.jsp diff --git a/spring-mvc-xml/src/main/webapp/jsp/index.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/jsp/index.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/jsp/index.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/jsp/index.jsp diff --git a/spring-mvc-xml/src/main/webapp/spring-handler-index.jsp b/spring-web-modules/spring-mvc-xml/src/main/webapp/spring-handler-index.jsp similarity index 100% rename from spring-mvc-xml/src/main/webapp/spring-handler-index.jsp rename to spring-web-modules/spring-mvc-xml/src/main/webapp/spring-handler-index.jsp diff --git a/spring-mvc-xml/src/test/java/org/baeldung/SpringContextTest.java b/spring-web-modules/spring-mvc-xml/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-mvc-xml/src/test/java/org/baeldung/SpringContextTest.java rename to spring-web-modules/spring-mvc-xml/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-mvc-xml/src/test/java/com/baeldung/geoip/GeoIpIntegrationTest.java b/spring-web-modules/spring-mvc-xml/src/test/java/com/baeldung/geoip/GeoIpIntegrationTest.java similarity index 100% rename from spring-mvc-xml/src/test/java/com/baeldung/geoip/GeoIpIntegrationTest.java rename to spring-web-modules/spring-mvc-xml/src/test/java/com/baeldung/geoip/GeoIpIntegrationTest.java diff --git a/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java b/spring-web-modules/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java similarity index 100% rename from spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java rename to spring-web-modules/spring-mvc-xml/src/test/java/com/baeldung/spring/controller/RequestAndPathVariableValidationControllerIntegrationTest.java diff --git a/spring-rest-angular/README.md b/spring-web-modules/spring-rest-angular/README.md similarity index 100% rename from spring-rest-angular/README.md rename to spring-web-modules/spring-rest-angular/README.md diff --git a/spring-rest-angular/pom.xml b/spring-web-modules/spring-rest-angular/pom.xml similarity index 97% rename from spring-rest-angular/pom.xml rename to spring-web-modules/spring-rest-angular/pom.xml index 1d50b4c76c..eb1ec8696c 100644 --- a/spring-rest-angular/pom.xml +++ b/spring-web-modules/spring-rest-angular/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 diff --git a/spring-rest-angular/src/main/java/com/baeldung/web/dao/StudentRepository.java b/spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/dao/StudentRepository.java similarity index 100% rename from spring-rest-angular/src/main/java/com/baeldung/web/dao/StudentRepository.java rename to spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/dao/StudentRepository.java diff --git a/spring-rest-angular/src/main/java/com/baeldung/web/entity/Student.java b/spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/entity/Student.java similarity index 100% rename from spring-rest-angular/src/main/java/com/baeldung/web/entity/Student.java rename to spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/entity/Student.java diff --git a/spring-rest-angular/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java b/spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java similarity index 100% rename from spring-rest-angular/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java rename to spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java diff --git a/spring-rest-angular/src/main/java/com/baeldung/web/main/Application.java b/spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/main/Application.java similarity index 100% rename from spring-rest-angular/src/main/java/com/baeldung/web/main/Application.java rename to spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/main/Application.java diff --git a/spring-rest-angular/src/main/java/com/baeldung/web/main/PersistenceConfig.java b/spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/main/PersistenceConfig.java similarity index 100% rename from spring-rest-angular/src/main/java/com/baeldung/web/main/PersistenceConfig.java rename to spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/main/PersistenceConfig.java diff --git a/spring-rest-angular/src/main/java/com/baeldung/web/rest/StudentDirectoryRestController.java b/spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/rest/StudentDirectoryRestController.java similarity index 100% rename from spring-rest-angular/src/main/java/com/baeldung/web/rest/StudentDirectoryRestController.java rename to spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/rest/StudentDirectoryRestController.java diff --git a/spring-rest-angular/src/main/java/com/baeldung/web/service/IOperations.java b/spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/service/IOperations.java similarity index 100% rename from spring-rest-angular/src/main/java/com/baeldung/web/service/IOperations.java rename to spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/service/IOperations.java diff --git a/spring-rest-angular/src/main/java/com/baeldung/web/service/StudentService.java b/spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/service/StudentService.java similarity index 100% rename from spring-rest-angular/src/main/java/com/baeldung/web/service/StudentService.java rename to spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/service/StudentService.java diff --git a/spring-rest-angular/src/main/java/com/baeldung/web/service/StudentServiceImpl.java b/spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/service/StudentServiceImpl.java similarity index 100% rename from spring-rest-angular/src/main/java/com/baeldung/web/service/StudentServiceImpl.java rename to spring-web-modules/spring-rest-angular/src/main/java/com/baeldung/web/service/StudentServiceImpl.java diff --git a/spring-rest-angular/src/main/resources/application.properties b/spring-web-modules/spring-rest-angular/src/main/resources/application.properties similarity index 100% rename from spring-rest-angular/src/main/resources/application.properties rename to spring-web-modules/spring-rest-angular/src/main/resources/application.properties diff --git a/spring-rest-angular/src/main/resources/data.sql b/spring-web-modules/spring-rest-angular/src/main/resources/data.sql similarity index 100% rename from spring-rest-angular/src/main/resources/data.sql rename to spring-web-modules/spring-rest-angular/src/main/resources/data.sql diff --git a/spring-session/spring-session-jdbc/src/main/resources/logback.xml b/spring-web-modules/spring-rest-angular/src/main/resources/logback.xml similarity index 100% rename from spring-session/spring-session-jdbc/src/main/resources/logback.xml rename to spring-web-modules/spring-rest-angular/src/main/resources/logback.xml diff --git a/spring-rest-angular/src/main/webapp/WEB-INF/web.xml b/spring-web-modules/spring-rest-angular/src/main/webapp/WEB-INF/web.xml similarity index 100% rename from spring-rest-angular/src/main/webapp/WEB-INF/web.xml rename to spring-web-modules/spring-rest-angular/src/main/webapp/WEB-INF/web.xml diff --git a/spring-rest-angular/src/main/webapp/index.html b/spring-web-modules/spring-rest-angular/src/main/webapp/index.html similarity index 100% rename from spring-rest-angular/src/main/webapp/index.html rename to spring-web-modules/spring-rest-angular/src/main/webapp/index.html diff --git a/spring-rest-angular/src/main/webapp/view/app.js b/spring-web-modules/spring-rest-angular/src/main/webapp/view/app.js similarity index 100% rename from spring-rest-angular/src/main/webapp/view/app.js rename to spring-web-modules/spring-rest-angular/src/main/webapp/view/app.js diff --git a/spring-rest-angular/src/test/java/com/baeldung/SpringContextTest.java b/spring-web-modules/spring-rest-angular/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-rest-angular/src/test/java/com/baeldung/SpringContextTest.java rename to spring-web-modules/spring-rest-angular/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-rest-angular/src/test/java/com/baeldung/web/service/StudentServiceIntegrationTest.java b/spring-web-modules/spring-rest-angular/src/test/java/com/baeldung/web/service/StudentServiceIntegrationTest.java similarity index 100% rename from spring-rest-angular/src/test/java/com/baeldung/web/service/StudentServiceIntegrationTest.java rename to spring-web-modules/spring-rest-angular/src/test/java/com/baeldung/web/service/StudentServiceIntegrationTest.java diff --git a/spring-rest-http-2/README.md b/spring-web-modules/spring-rest-http-2/README.md similarity index 75% rename from spring-rest-http-2/README.md rename to spring-web-modules/spring-rest-http-2/README.md index 97cdc2d068..b5358f888f 100644 --- a/spring-rest-http-2/README.md +++ b/spring-web-modules/spring-rest-http-2/README.md @@ -8,3 +8,4 @@ The "REST With Spring 2" Classes: http://bit.ly/restwithspring ### Relevant Articles: - [How to Turn Off Swagger-ui in Production](https://www.baeldung.com/swagger-ui-turn-off-in-production) +- [Setting a Request Timeout for a Spring REST API](https://www.baeldung.com/spring-rest-timeout) diff --git a/spring-rest-http-2/pom.xml b/spring-web-modules/spring-rest-http-2/pom.xml similarity index 95% rename from spring-rest-http-2/pom.xml rename to spring-web-modules/spring-rest-http-2/pom.xml index 8678d7243d..6aa8be365c 100644 --- a/spring-rest-http-2/pom.xml +++ b/spring-web-modules/spring-rest-http-2/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 diff --git a/spring-rest-http-2/src/main/java/com/baeldung/SpringBootRest2Application.java b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/SpringBootRest2Application.java similarity index 100% rename from spring-rest-http-2/src/main/java/com/baeldung/SpringBootRest2Application.java rename to spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/SpringBootRest2Application.java diff --git a/spring-rest-http-2/src/main/java/com/baeldung/swaggerui/disable/config/SwaggerConfig.java b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/swaggerui/disable/config/SwaggerConfig.java similarity index 100% rename from spring-rest-http-2/src/main/java/com/baeldung/swaggerui/disable/config/SwaggerConfig.java rename to spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/swaggerui/disable/config/SwaggerConfig.java diff --git a/spring-rest-http-2/src/main/java/com/baeldung/swaggerui/disable/controllers/VersionController.java b/spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/swaggerui/disable/controllers/VersionController.java similarity index 100% rename from spring-rest-http-2/src/main/java/com/baeldung/swaggerui/disable/controllers/VersionController.java rename to spring-web-modules/spring-rest-http-2/src/main/java/com/baeldung/swaggerui/disable/controllers/VersionController.java diff --git a/spring-rest-http/README.md b/spring-web-modules/spring-rest-http/README.md similarity index 100% rename from spring-rest-http/README.md rename to spring-web-modules/spring-rest-http/README.md diff --git a/spring-rest-http/pom.xml b/spring-web-modules/spring-rest-http/pom.xml similarity index 97% rename from spring-rest-http/pom.xml rename to spring-web-modules/spring-rest-http/pom.xml index 18b7e0af05..422bcd32f7 100644 --- a/spring-rest-http/pom.xml +++ b/spring-web-modules/spring-rest-http/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 diff --git a/spring-rest-http/src/main/java/com/baeldung/CustomerSpringBootRestApplication.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/CustomerSpringBootRestApplication.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/CustomerSpringBootRestApplication.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/CustomerSpringBootRestApplication.java diff --git a/spring-rest-http/src/main/java/com/baeldung/config/MvcConfig.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/config/MvcConfig.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/config/MvcConfig.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/config/MvcConfig.java diff --git a/spring-rest-http/src/main/java/com/baeldung/controllers/DeferredResultController.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/controllers/DeferredResultController.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/controllers/DeferredResultController.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/controllers/DeferredResultController.java diff --git a/spring-rest-http/src/main/java/com/baeldung/model/Customer.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/model/Customer.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/model/Customer.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/model/Customer.java diff --git a/spring-rest-http/src/main/java/com/baeldung/requestmapping/BarMappingExamplesController.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/requestmapping/BarMappingExamplesController.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/requestmapping/BarMappingExamplesController.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/requestmapping/BarMappingExamplesController.java diff --git a/spring-rest-http/src/main/java/com/baeldung/requestmapping/BazzNewMappingsExampleController.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/requestmapping/BazzNewMappingsExampleController.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/requestmapping/BazzNewMappingsExampleController.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/requestmapping/BazzNewMappingsExampleController.java diff --git a/spring-rest-http/src/main/java/com/baeldung/requestmapping/FooMappingExamplesController.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/requestmapping/FooMappingExamplesController.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/requestmapping/FooMappingExamplesController.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/requestmapping/FooMappingExamplesController.java diff --git a/spring-rest-http/src/main/java/com/baeldung/service/CustomerIdGenerator.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/service/CustomerIdGenerator.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/service/CustomerIdGenerator.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/service/CustomerIdGenerator.java diff --git a/spring-rest-http/src/main/java/com/baeldung/service/CustomerService.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/service/CustomerService.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/service/CustomerService.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/service/CustomerService.java diff --git a/spring-rest-http/src/main/java/com/baeldung/service/impl/CustomerIdGeneratorImpl.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/service/impl/CustomerIdGeneratorImpl.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/service/impl/CustomerIdGeneratorImpl.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/service/impl/CustomerIdGeneratorImpl.java diff --git a/spring-rest-http/src/main/java/com/baeldung/service/impl/CustomerServiceImpl.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/service/impl/CustomerServiceImpl.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/service/impl/CustomerServiceImpl.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/service/impl/CustomerServiceImpl.java diff --git a/spring-rest-http/src/main/java/com/baeldung/web/controller/customer/CustomerRestController.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/web/controller/customer/CustomerRestController.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/web/controller/customer/CustomerRestController.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/web/controller/customer/CustomerRestController.java diff --git a/spring-rest-http/src/main/java/com/baeldung/web/controller/status/ExampleController.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/web/controller/status/ExampleController.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/web/controller/status/ExampleController.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/web/controller/status/ExampleController.java diff --git a/spring-rest-http/src/main/java/com/baeldung/web/controller/status/ForbiddenException.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/web/controller/status/ForbiddenException.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/web/controller/status/ForbiddenException.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/web/controller/status/ForbiddenException.java diff --git a/spring-rest-http/src/main/java/com/baeldung/web/dto/Bazz.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/web/dto/Bazz.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/web/dto/Bazz.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/web/dto/Bazz.java diff --git a/spring-rest-http/src/main/java/com/baeldung/web/dto/Foo.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/web/dto/Foo.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/web/dto/Foo.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/web/dto/Foo.java diff --git a/spring-rest-http/src/main/java/com/baeldung/web/exception/CustomerNotFoundException.java b/spring-web-modules/spring-rest-http/src/main/java/com/baeldung/web/exception/CustomerNotFoundException.java similarity index 100% rename from spring-rest-http/src/main/java/com/baeldung/web/exception/CustomerNotFoundException.java rename to spring-web-modules/spring-rest-http/src/main/java/com/baeldung/web/exception/CustomerNotFoundException.java diff --git a/spring-rest-http/src/main/resources/openapi-dates-definitions/openapi-3-date-format.yaml b/spring-web-modules/spring-rest-http/src/main/resources/openapi-dates-definitions/openapi-3-date-format.yaml similarity index 100% rename from spring-rest-http/src/main/resources/openapi-dates-definitions/openapi-3-date-format.yaml rename to spring-web-modules/spring-rest-http/src/main/resources/openapi-dates-definitions/openapi-3-date-format.yaml diff --git a/spring-rest-http/src/main/resources/openapi-dates-definitions/openapi-3-date-pattern.yaml b/spring-web-modules/spring-rest-http/src/main/resources/openapi-dates-definitions/openapi-3-date-pattern.yaml similarity index 100% rename from spring-rest-http/src/main/resources/openapi-dates-definitions/openapi-3-date-pattern.yaml rename to spring-web-modules/spring-rest-http/src/main/resources/openapi-dates-definitions/openapi-3-date-pattern.yaml diff --git a/spring-rest-http/src/main/resources/openapi-dates-definitions/openapi-3-datetime-format.yaml b/spring-web-modules/spring-rest-http/src/main/resources/openapi-dates-definitions/openapi-3-datetime-format.yaml similarity index 100% rename from spring-rest-http/src/main/resources/openapi-dates-definitions/openapi-3-datetime-format.yaml rename to spring-web-modules/spring-rest-http/src/main/resources/openapi-dates-definitions/openapi-3-datetime-format.yaml diff --git a/spring-rest-http/src/main/resources/openapi-queryparam-definitions/openapi-2.yaml b/spring-web-modules/spring-rest-http/src/main/resources/openapi-queryparam-definitions/openapi-2.yaml similarity index 100% rename from spring-rest-http/src/main/resources/openapi-queryparam-definitions/openapi-2.yaml rename to spring-web-modules/spring-rest-http/src/main/resources/openapi-queryparam-definitions/openapi-2.yaml diff --git a/spring-rest-http/src/main/resources/openapi-queryparam-definitions/openapi-3.yaml b/spring-web-modules/spring-rest-http/src/main/resources/openapi-queryparam-definitions/openapi-3.yaml similarity index 100% rename from spring-rest-http/src/main/resources/openapi-queryparam-definitions/openapi-3.yaml rename to spring-web-modules/spring-rest-http/src/main/resources/openapi-queryparam-definitions/openapi-3.yaml diff --git a/spring-rest-http/src/test/java/com/baeldung/requestmapping/BazzNewMappingsExampleIntegrationTest.java b/spring-web-modules/spring-rest-http/src/test/java/com/baeldung/requestmapping/BazzNewMappingsExampleIntegrationTest.java similarity index 100% rename from spring-rest-http/src/test/java/com/baeldung/requestmapping/BazzNewMappingsExampleIntegrationTest.java rename to spring-web-modules/spring-rest-http/src/test/java/com/baeldung/requestmapping/BazzNewMappingsExampleIntegrationTest.java diff --git a/spring-rest-http/src/test/java/com/baeldung/requestmapping/FooMappingExamplesControllerUnitTest.java b/spring-web-modules/spring-rest-http/src/test/java/com/baeldung/requestmapping/FooMappingExamplesControllerUnitTest.java similarity index 100% rename from spring-rest-http/src/test/java/com/baeldung/requestmapping/FooMappingExamplesControllerUnitTest.java rename to spring-web-modules/spring-rest-http/src/test/java/com/baeldung/requestmapping/FooMappingExamplesControllerUnitTest.java diff --git a/spring-rest-http/src/test/java/com/baeldung/responseheaders/ResponseHeaderLiveTest.java b/spring-web-modules/spring-rest-http/src/test/java/com/baeldung/responseheaders/ResponseHeaderLiveTest.java similarity index 100% rename from spring-rest-http/src/test/java/com/baeldung/responseheaders/ResponseHeaderLiveTest.java rename to spring-web-modules/spring-rest-http/src/test/java/com/baeldung/responseheaders/ResponseHeaderLiveTest.java diff --git a/spring-rest-http/src/test/java/com/baeldung/service/impl/CustomerIdGeneratorImplUnitTest.java b/spring-web-modules/spring-rest-http/src/test/java/com/baeldung/service/impl/CustomerIdGeneratorImplUnitTest.java similarity index 100% rename from spring-rest-http/src/test/java/com/baeldung/service/impl/CustomerIdGeneratorImplUnitTest.java rename to spring-web-modules/spring-rest-http/src/test/java/com/baeldung/service/impl/CustomerIdGeneratorImplUnitTest.java diff --git a/spring-rest-http/src/test/java/com/baeldung/service/impl/CustomerServiceImplUnitTest.java b/spring-web-modules/spring-rest-http/src/test/java/com/baeldung/service/impl/CustomerServiceImplUnitTest.java similarity index 100% rename from spring-rest-http/src/test/java/com/baeldung/service/impl/CustomerServiceImplUnitTest.java rename to spring-web-modules/spring-rest-http/src/test/java/com/baeldung/service/impl/CustomerServiceImplUnitTest.java diff --git a/spring-rest-http/src/test/java/com/baeldung/uribuilder/SpringUriBuilderIntegrationTest.java b/spring-web-modules/spring-rest-http/src/test/java/com/baeldung/uribuilder/SpringUriBuilderIntegrationTest.java similarity index 100% rename from spring-rest-http/src/test/java/com/baeldung/uribuilder/SpringUriBuilderIntegrationTest.java rename to spring-web-modules/spring-rest-http/src/test/java/com/baeldung/uribuilder/SpringUriBuilderIntegrationTest.java diff --git a/spring-rest-http/src/test/java/com/baeldung/web/controller/customer/CustomerRestControllerIntegrationTest.java b/spring-web-modules/spring-rest-http/src/test/java/com/baeldung/web/controller/customer/CustomerRestControllerIntegrationTest.java similarity index 100% rename from spring-rest-http/src/test/java/com/baeldung/web/controller/customer/CustomerRestControllerIntegrationTest.java rename to spring-web-modules/spring-rest-http/src/test/java/com/baeldung/web/controller/customer/CustomerRestControllerIntegrationTest.java diff --git a/spring-rest-http/src/test/java/com/baeldung/web/controller/customer/CustomerRestControllerUnitTest.java b/spring-web-modules/spring-rest-http/src/test/java/com/baeldung/web/controller/customer/CustomerRestControllerUnitTest.java similarity index 100% rename from spring-rest-http/src/test/java/com/baeldung/web/controller/customer/CustomerRestControllerUnitTest.java rename to spring-web-modules/spring-rest-http/src/test/java/com/baeldung/web/controller/customer/CustomerRestControllerUnitTest.java diff --git a/spring-rest-http/src/test/java/com/baeldung/web/controller/status/ExampleControllerIntegrationTest.java b/spring-web-modules/spring-rest-http/src/test/java/com/baeldung/web/controller/status/ExampleControllerIntegrationTest.java similarity index 100% rename from spring-rest-http/src/test/java/com/baeldung/web/controller/status/ExampleControllerIntegrationTest.java rename to spring-web-modules/spring-rest-http/src/test/java/com/baeldung/web/controller/status/ExampleControllerIntegrationTest.java diff --git a/spring-mvc-xml/.gitignore b/spring-web-modules/spring-rest-query-language/.gitignore similarity index 100% rename from spring-mvc-xml/.gitignore rename to spring-web-modules/spring-rest-query-language/.gitignore diff --git a/spring-rest-query-language/README.md b/spring-web-modules/spring-rest-query-language/README.md similarity index 100% rename from spring-rest-query-language/README.md rename to spring-web-modules/spring-rest-query-language/README.md diff --git a/spring-rest-query-language/pom.xml b/spring-web-modules/spring-rest-query-language/pom.xml similarity index 99% rename from spring-rest-query-language/pom.xml rename to spring-web-modules/spring-rest-query-language/pom.xml index 2423528743..5e7ca023dd 100644 --- a/spring-rest-query-language/pom.xml +++ b/spring-web-modules/spring-rest-query-language/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 @@ -140,7 +140,7 @@
org.hibernate - hibernate-entitymanager + hibernate-core xml-apis diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/GenericSpecificationsBuilder.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/GenericSpecificationsBuilder.java similarity index 97% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/GenericSpecificationsBuilder.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/GenericSpecificationsBuilder.java index 75fb4456c4..b6623e8885 100644 --- a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/GenericSpecificationsBuilder.java +++ b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/GenericSpecificationsBuilder.java @@ -1,100 +1,100 @@ -package com.baeldung.persistence.dao; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Deque; -import java.util.LinkedList; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.springframework.data.jpa.domain.Specification; - -import com.baeldung.web.util.SearchOperation; -import com.baeldung.web.util.SpecSearchCriteria; - -public class GenericSpecificationsBuilder { - - private final List params; - - public GenericSpecificationsBuilder() { - this.params = new ArrayList<>(); - } - - public final GenericSpecificationsBuilder with(final String key, final String operation, final Object value, final String prefix, final String suffix) { - return with(null, key, operation, value, prefix, suffix); - } - - public final GenericSpecificationsBuilder with(final String precedenceIndicator, final String key, final String operation, final Object value, final String prefix, final String suffix) { - SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0)); - if (op != null) { - if (op == SearchOperation.EQUALITY) // the operation may be complex operation - { - final boolean startWithAsterisk = prefix != null && prefix.contains(SearchOperation.ZERO_OR_MORE_REGEX); - final boolean endWithAsterisk = suffix != null && suffix.contains(SearchOperation.ZERO_OR_MORE_REGEX); - - if (startWithAsterisk && endWithAsterisk) { - op = SearchOperation.CONTAINS; - } else if (startWithAsterisk) { - op = SearchOperation.ENDS_WITH; - } else if (endWithAsterisk) { - op = SearchOperation.STARTS_WITH; - } - } - params.add(new SpecSearchCriteria(precedenceIndicator, key, op, value)); - } - return this; - } - - public Specification build(Function> converter) { - - if (params.size() == 0) { - return null; - } - - final List> specs = params.stream() - .map(converter) - .collect(Collectors.toCollection(ArrayList::new)); - - Specification result = specs.get(0); - - for (int idx = 1; idx < specs.size(); idx++) { - result = params.get(idx) - .isOrPredicate() - ? Specification.where(result) - .or(specs.get(idx)) - : Specification.where(result) - .and(specs.get(idx)); - } - - return result; - } - - public Specification build(Deque postFixedExprStack, Function> converter) { - - Deque> specStack = new LinkedList<>(); - - Collections.reverse((List) postFixedExprStack); - - while (!postFixedExprStack.isEmpty()) { - Object mayBeOperand = postFixedExprStack.pop(); - - if (!(mayBeOperand instanceof String)) { - specStack.push(converter.apply((SpecSearchCriteria) mayBeOperand)); - } else { - Specification operand1 = specStack.pop(); - Specification operand2 = specStack.pop(); - if (mayBeOperand.equals(SearchOperation.AND_OPERATOR)) - specStack.push(Specification.where(operand1) - .and(operand2)); - else if (mayBeOperand.equals(SearchOperation.OR_OPERATOR)) - specStack.push(Specification.where(operand1) - .or(operand2)); - } - - } - return specStack.pop(); - - } - -} +package com.baeldung.persistence.dao; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Deque; +import java.util.LinkedList; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.springframework.data.jpa.domain.Specification; + +import com.baeldung.web.util.SearchOperation; +import com.baeldung.web.util.SpecSearchCriteria; + +public class GenericSpecificationsBuilder { + + private final List params; + + public GenericSpecificationsBuilder() { + this.params = new ArrayList<>(); + } + + public final GenericSpecificationsBuilder with(final String key, final String operation, final Object value, final String prefix, final String suffix) { + return with(null, key, operation, value, prefix, suffix); + } + + public final GenericSpecificationsBuilder with(final String precedenceIndicator, final String key, final String operation, final Object value, final String prefix, final String suffix) { + SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0)); + if (op != null) { + if (op == SearchOperation.EQUALITY) // the operation may be complex operation + { + final boolean startWithAsterisk = prefix != null && prefix.contains(SearchOperation.ZERO_OR_MORE_REGEX); + final boolean endWithAsterisk = suffix != null && suffix.contains(SearchOperation.ZERO_OR_MORE_REGEX); + + if (startWithAsterisk && endWithAsterisk) { + op = SearchOperation.CONTAINS; + } else if (startWithAsterisk) { + op = SearchOperation.ENDS_WITH; + } else if (endWithAsterisk) { + op = SearchOperation.STARTS_WITH; + } + } + params.add(new SpecSearchCriteria(precedenceIndicator, key, op, value)); + } + return this; + } + + public Specification build(Function> converter) { + + if (params.size() == 0) { + return null; + } + + final List> specs = params.stream() + .map(converter) + .collect(Collectors.toCollection(ArrayList::new)); + + Specification result = specs.get(0); + + for (int idx = 1; idx < specs.size(); idx++) { + result = params.get(idx) + .isOrPredicate() + ? Specification.where(result) + .or(specs.get(idx)) + : Specification.where(result) + .and(specs.get(idx)); + } + + return result; + } + + public Specification build(Deque postFixedExprStack, Function> converter) { + + Deque> specStack = new LinkedList<>(); + + Collections.reverse((List) postFixedExprStack); + + while (!postFixedExprStack.isEmpty()) { + Object mayBeOperand = postFixedExprStack.pop(); + + if (!(mayBeOperand instanceof String)) { + specStack.push(converter.apply((SpecSearchCriteria) mayBeOperand)); + } else { + Specification operand1 = specStack.pop(); + Specification operand2 = specStack.pop(); + if (mayBeOperand.equals(SearchOperation.AND_OPERATOR)) + specStack.push(Specification.where(operand1) + .and(operand2)); + else if (mayBeOperand.equals(SearchOperation.OR_OPERATOR)) + specStack.push(Specification.where(operand1) + .or(operand2)); + } + + } + return specStack.pop(); + + } + +} diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/IUserDAO.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/IUserDAO.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/IUserDAO.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/IUserDAO.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/MyUserPredicate.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/MyUserPredicate.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/MyUserPredicate.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/MyUserPredicate.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/MyUserPredicatesBuilder.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/MyUserPredicatesBuilder.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/MyUserPredicatesBuilder.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/MyUserPredicatesBuilder.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/MyUserRepository.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/MyUserRepository.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/MyUserRepository.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/MyUserRepository.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserDAO.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserDAO.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserDAO.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserDAO.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserRepository.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserRepository.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserRepository.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserRepository.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserSearchQueryCriteriaConsumer.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserSearchQueryCriteriaConsumer.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserSearchQueryCriteriaConsumer.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserSearchQueryCriteriaConsumer.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserSpecification.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserSpecification.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserSpecification.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserSpecification.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserSpecificationsBuilder.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserSpecificationsBuilder.java similarity index 97% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserSpecificationsBuilder.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserSpecificationsBuilder.java index 72d7274226..eac1562294 100644 --- a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserSpecificationsBuilder.java +++ b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/UserSpecificationsBuilder.java @@ -1,70 +1,70 @@ -package com.baeldung.persistence.dao; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.data.jpa.domain.Specification; - -import com.baeldung.persistence.model.User; -import com.baeldung.web.util.SearchOperation; -import com.baeldung.web.util.SpecSearchCriteria; - -public final class UserSpecificationsBuilder { - - private final List params; - - public UserSpecificationsBuilder() { - params = new ArrayList<>(); - } - - // API - - public final UserSpecificationsBuilder with(final String key, final String operation, final Object value, final String prefix, final String suffix) { - return with(null, key, operation, value, prefix, suffix); - } - - public final UserSpecificationsBuilder with(final String orPredicate, final String key, final String operation, final Object value, final String prefix, final String suffix) { - SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0)); - if (op != null) { - if (op == SearchOperation.EQUALITY) { // the operation may be complex operation - final boolean startWithAsterisk = prefix != null && prefix.contains(SearchOperation.ZERO_OR_MORE_REGEX); - final boolean endWithAsterisk = suffix != null && suffix.contains(SearchOperation.ZERO_OR_MORE_REGEX); - - if (startWithAsterisk && endWithAsterisk) { - op = SearchOperation.CONTAINS; - } else if (startWithAsterisk) { - op = SearchOperation.ENDS_WITH; - } else if (endWithAsterisk) { - op = SearchOperation.STARTS_WITH; - } - } - params.add(new SpecSearchCriteria(orPredicate, key, op, value)); - } - return this; - } - - public Specification build() { - if (params.size() == 0) - return null; - - Specification result = new UserSpecification(params.get(0)); - - for (int i = 1; i < params.size(); i++) { - result = params.get(i).isOrPredicate() - ? Specification.where(result).or(new UserSpecification(params.get(i))) - : Specification.where(result).and(new UserSpecification(params.get(i))); - } - - return result; - } - - public final UserSpecificationsBuilder with(UserSpecification spec) { - params.add(spec.getCriteria()); - return this; - } - - public final UserSpecificationsBuilder with(SpecSearchCriteria criteria) { - params.add(criteria); - return this; - } -} +package com.baeldung.persistence.dao; + +import java.util.ArrayList; +import java.util.List; + +import org.springframework.data.jpa.domain.Specification; + +import com.baeldung.persistence.model.User; +import com.baeldung.web.util.SearchOperation; +import com.baeldung.web.util.SpecSearchCriteria; + +public final class UserSpecificationsBuilder { + + private final List params; + + public UserSpecificationsBuilder() { + params = new ArrayList<>(); + } + + // API + + public final UserSpecificationsBuilder with(final String key, final String operation, final Object value, final String prefix, final String suffix) { + return with(null, key, operation, value, prefix, suffix); + } + + public final UserSpecificationsBuilder with(final String orPredicate, final String key, final String operation, final Object value, final String prefix, final String suffix) { + SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0)); + if (op != null) { + if (op == SearchOperation.EQUALITY) { // the operation may be complex operation + final boolean startWithAsterisk = prefix != null && prefix.contains(SearchOperation.ZERO_OR_MORE_REGEX); + final boolean endWithAsterisk = suffix != null && suffix.contains(SearchOperation.ZERO_OR_MORE_REGEX); + + if (startWithAsterisk && endWithAsterisk) { + op = SearchOperation.CONTAINS; + } else if (startWithAsterisk) { + op = SearchOperation.ENDS_WITH; + } else if (endWithAsterisk) { + op = SearchOperation.STARTS_WITH; + } + } + params.add(new SpecSearchCriteria(orPredicate, key, op, value)); + } + return this; + } + + public Specification build() { + if (params.size() == 0) + return null; + + Specification result = new UserSpecification(params.get(0)); + + for (int i = 1; i < params.size(); i++) { + result = params.get(i).isOrPredicate() + ? Specification.where(result).or(new UserSpecification(params.get(i))) + : Specification.where(result).and(new UserSpecification(params.get(i))); + } + + return result; + } + + public final UserSpecificationsBuilder with(UserSpecification spec) { + params.add(spec.getCriteria()); + return this; + } + + public final UserSpecificationsBuilder with(SpecSearchCriteria criteria) { + params.add(criteria); + return this; + } +} diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/CustomRsqlVisitor.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/CustomRsqlVisitor.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/CustomRsqlVisitor.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/CustomRsqlVisitor.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/GenericRsqlSpecBuilder.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/GenericRsqlSpecBuilder.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/GenericRsqlSpecBuilder.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/GenericRsqlSpecBuilder.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/GenericRsqlSpecification.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/GenericRsqlSpecification.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/GenericRsqlSpecification.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/GenericRsqlSpecification.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/RsqlSearchOperation.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/RsqlSearchOperation.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/RsqlSearchOperation.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/dao/rsql/RsqlSearchOperation.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/model/MyUser.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/model/MyUser.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/model/MyUser.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/model/MyUser.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/model/User.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/model/User.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/model/User.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/model/User.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/persistence/model/User_.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/model/User_.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/persistence/model/User_.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/persistence/model/User_.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/spring/Application.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/spring/Application.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/spring/Application.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/spring/Application.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/spring/PersistenceConfig.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/spring/PersistenceConfig.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/spring/PersistenceConfig.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/spring/PersistenceConfig.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/spring/WebConfig.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/spring/WebConfig.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/spring/WebConfig.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/spring/WebConfig.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/web/controller/HomeController.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/controller/HomeController.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/web/controller/HomeController.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/controller/HomeController.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/web/controller/UserController.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/controller/UserController.java similarity index 97% rename from spring-rest-query-language/src/main/java/com/baeldung/web/controller/UserController.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/controller/UserController.java index 54e8618b27..73a97f84ae 100644 --- a/spring-rest-query-language/src/main/java/com/baeldung/web/controller/UserController.java +++ b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/controller/UserController.java @@ -1,171 +1,171 @@ -package com.baeldung.web.controller; - -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.querydsl.binding.QuerydslPredicate; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -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.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.ResponseStatus; - -import com.baeldung.persistence.dao.GenericSpecificationsBuilder; -import com.baeldung.persistence.dao.IUserDAO; -import com.baeldung.persistence.dao.MyUserPredicatesBuilder; -import com.baeldung.persistence.dao.MyUserRepository; -import com.baeldung.persistence.dao.UserRepository; -import com.baeldung.persistence.dao.UserSpecification; -import com.baeldung.persistence.dao.UserSpecificationsBuilder; -import com.baeldung.persistence.dao.rsql.CustomRsqlVisitor; -import com.baeldung.persistence.model.MyUser; -import com.baeldung.persistence.model.User; -import com.baeldung.web.util.CriteriaParser; -import com.baeldung.web.util.SearchCriteria; -import com.baeldung.web.util.SearchOperation; -import com.google.common.base.Joiner; -import com.google.common.base.Preconditions; -import com.querydsl.core.types.Predicate; -import com.querydsl.core.types.dsl.BooleanExpression; - -import cz.jirutka.rsql.parser.RSQLParser; -import cz.jirutka.rsql.parser.ast.Node; - -//@EnableSpringDataWebSupport -@Controller -@RequestMapping(value = "/auth/") -public class UserController { - - @Autowired - private IUserDAO service; - - @Autowired - private UserRepository dao; - - @Autowired - private MyUserRepository myUserRepository; - - public UserController() { - super(); - } - - // API - READ - - @RequestMapping(method = RequestMethod.GET, value = "/users") - @ResponseBody - public List search(@RequestParam(value = "search", required = false) String search) { - List params = new ArrayList(); - if (search != null) { - Pattern pattern = Pattern.compile("(\\w+?)(:|<|>)(\\w+?),"); - Matcher matcher = pattern.matcher(search + ","); - while (matcher.find()) { - params.add(new SearchCriteria(matcher.group(1), matcher.group(2), matcher.group(3))); - } - } - return service.searchUser(params); - } - - @RequestMapping(method = RequestMethod.GET, value = "/users/spec") - @ResponseBody - public List findAllBySpecification(@RequestParam(value = "search") String search) { - UserSpecificationsBuilder builder = new UserSpecificationsBuilder(); - String operationSetExper = Joiner.on("|") - .join(SearchOperation.SIMPLE_OPERATION_SET); - Pattern pattern = Pattern.compile("(\\w+?)(" + operationSetExper + ")(\\p{Punct}?)(\\w+?)(\\p{Punct}?),"); - Matcher matcher = pattern.matcher(search + ","); - while (matcher.find()) { - builder.with(matcher.group(1), matcher.group(2), matcher.group(4), matcher.group(3), matcher.group(5)); - } - - Specification spec = builder.build(); - return dao.findAll(spec); - } - - @GetMapping(value = "/users/espec") - @ResponseBody - public List findAllByOrPredicate(@RequestParam(value = "search") String search) { - Specification spec = resolveSpecification(search); - return dao.findAll(spec); - } - - @GetMapping(value = "/users/spec/adv") - @ResponseBody - public List findAllByAdvPredicate(@RequestParam(value = "search") String search) { - Specification spec = resolveSpecificationFromInfixExpr(search); - return dao.findAll(spec); - } - - protected Specification resolveSpecificationFromInfixExpr(String searchParameters) { - CriteriaParser parser = new CriteriaParser(); - GenericSpecificationsBuilder specBuilder = new GenericSpecificationsBuilder<>(); - return specBuilder.build(parser.parse(searchParameters), UserSpecification::new); - } - - protected Specification resolveSpecification(String searchParameters) { - - UserSpecificationsBuilder builder = new UserSpecificationsBuilder(); - String operationSetExper = Joiner.on("|") - .join(SearchOperation.SIMPLE_OPERATION_SET); - Pattern pattern = Pattern.compile("(\\p{Punct}?)(\\w+?)(" + operationSetExper + ")(\\p{Punct}?)(\\w+?)(\\p{Punct}?),"); - Matcher matcher = pattern.matcher(searchParameters + ","); - while (matcher.find()) { - builder.with(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(5), matcher.group(4), matcher.group(6)); - } - return builder.build(); - } - - @RequestMapping(method = RequestMethod.GET, value = "/myusers") - @ResponseBody - public Iterable findAllByQuerydsl(@RequestParam(value = "search") String search) { - MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder(); - if (search != null) { - Pattern pattern = Pattern.compile("(\\w+?)(:|<|>)(\\w+?),"); - Matcher matcher = pattern.matcher(search + ","); - while (matcher.find()) { - builder.with(matcher.group(1), matcher.group(2), matcher.group(3)); - } - } - BooleanExpression exp = builder.build(); - return myUserRepository.findAll(exp); - } - - @RequestMapping(method = RequestMethod.GET, value = "/users/rsql") - @ResponseBody - public List findAllByRsql(@RequestParam(value = "search") String search) { - Node rootNode = new RSQLParser().parse(search); - Specification spec = rootNode.accept(new CustomRsqlVisitor()); - return dao.findAll(spec); - } - - @RequestMapping(method = RequestMethod.GET, value = "/api/myusers") - @ResponseBody - public Iterable findAllByWebQuerydsl(@QuerydslPredicate(root = MyUser.class) Predicate predicate) { - return myUserRepository.findAll(predicate); - } - - // API - WRITE - - @RequestMapping(method = RequestMethod.POST, value = "/users") - @ResponseStatus(HttpStatus.CREATED) - public void create(@RequestBody User resource) { - Preconditions.checkNotNull(resource); - dao.save(resource); - } - - @RequestMapping(method = RequestMethod.POST, value = "/myusers") - @ResponseStatus(HttpStatus.CREATED) - public void addMyUser(@RequestBody MyUser resource) { - Preconditions.checkNotNull(resource); - myUserRepository.save(resource); - - } - -} +package com.baeldung.web.controller; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.querydsl.binding.QuerydslPredicate; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +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.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +import com.baeldung.persistence.dao.GenericSpecificationsBuilder; +import com.baeldung.persistence.dao.IUserDAO; +import com.baeldung.persistence.dao.MyUserPredicatesBuilder; +import com.baeldung.persistence.dao.MyUserRepository; +import com.baeldung.persistence.dao.UserRepository; +import com.baeldung.persistence.dao.UserSpecification; +import com.baeldung.persistence.dao.UserSpecificationsBuilder; +import com.baeldung.persistence.dao.rsql.CustomRsqlVisitor; +import com.baeldung.persistence.model.MyUser; +import com.baeldung.persistence.model.User; +import com.baeldung.web.util.CriteriaParser; +import com.baeldung.web.util.SearchCriteria; +import com.baeldung.web.util.SearchOperation; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import com.querydsl.core.types.Predicate; +import com.querydsl.core.types.dsl.BooleanExpression; + +import cz.jirutka.rsql.parser.RSQLParser; +import cz.jirutka.rsql.parser.ast.Node; + +//@EnableSpringDataWebSupport +@Controller +@RequestMapping(value = "/auth/") +public class UserController { + + @Autowired + private IUserDAO service; + + @Autowired + private UserRepository dao; + + @Autowired + private MyUserRepository myUserRepository; + + public UserController() { + super(); + } + + // API - READ + + @RequestMapping(method = RequestMethod.GET, value = "/users") + @ResponseBody + public List search(@RequestParam(value = "search", required = false) String search) { + List params = new ArrayList(); + if (search != null) { + Pattern pattern = Pattern.compile("(\\w+?)(:|<|>)(\\w+?),"); + Matcher matcher = pattern.matcher(search + ","); + while (matcher.find()) { + params.add(new SearchCriteria(matcher.group(1), matcher.group(2), matcher.group(3))); + } + } + return service.searchUser(params); + } + + @RequestMapping(method = RequestMethod.GET, value = "/users/spec") + @ResponseBody + public List findAllBySpecification(@RequestParam(value = "search") String search) { + UserSpecificationsBuilder builder = new UserSpecificationsBuilder(); + String operationSetExper = Joiner.on("|") + .join(SearchOperation.SIMPLE_OPERATION_SET); + Pattern pattern = Pattern.compile("(\\w+?)(" + operationSetExper + ")(\\p{Punct}?)(\\w+?)(\\p{Punct}?),"); + Matcher matcher = pattern.matcher(search + ","); + while (matcher.find()) { + builder.with(matcher.group(1), matcher.group(2), matcher.group(4), matcher.group(3), matcher.group(5)); + } + + Specification spec = builder.build(); + return dao.findAll(spec); + } + + @GetMapping(value = "/users/espec") + @ResponseBody + public List findAllByOrPredicate(@RequestParam(value = "search") String search) { + Specification spec = resolveSpecification(search); + return dao.findAll(spec); + } + + @GetMapping(value = "/users/spec/adv") + @ResponseBody + public List findAllByAdvPredicate(@RequestParam(value = "search") String search) { + Specification spec = resolveSpecificationFromInfixExpr(search); + return dao.findAll(spec); + } + + protected Specification resolveSpecificationFromInfixExpr(String searchParameters) { + CriteriaParser parser = new CriteriaParser(); + GenericSpecificationsBuilder specBuilder = new GenericSpecificationsBuilder<>(); + return specBuilder.build(parser.parse(searchParameters), UserSpecification::new); + } + + protected Specification resolveSpecification(String searchParameters) { + + UserSpecificationsBuilder builder = new UserSpecificationsBuilder(); + String operationSetExper = Joiner.on("|") + .join(SearchOperation.SIMPLE_OPERATION_SET); + Pattern pattern = Pattern.compile("(\\p{Punct}?)(\\w+?)(" + operationSetExper + ")(\\p{Punct}?)(\\w+?)(\\p{Punct}?),"); + Matcher matcher = pattern.matcher(searchParameters + ","); + while (matcher.find()) { + builder.with(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(5), matcher.group(4), matcher.group(6)); + } + return builder.build(); + } + + @RequestMapping(method = RequestMethod.GET, value = "/myusers") + @ResponseBody + public Iterable findAllByQuerydsl(@RequestParam(value = "search") String search) { + MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder(); + if (search != null) { + Pattern pattern = Pattern.compile("(\\w+?)(:|<|>)(\\w+?),"); + Matcher matcher = pattern.matcher(search + ","); + while (matcher.find()) { + builder.with(matcher.group(1), matcher.group(2), matcher.group(3)); + } + } + BooleanExpression exp = builder.build(); + return myUserRepository.findAll(exp); + } + + @RequestMapping(method = RequestMethod.GET, value = "/users/rsql") + @ResponseBody + public List findAllByRsql(@RequestParam(value = "search") String search) { + Node rootNode = new RSQLParser().parse(search); + Specification spec = rootNode.accept(new CustomRsqlVisitor()); + return dao.findAll(spec); + } + + @RequestMapping(method = RequestMethod.GET, value = "/api/myusers") + @ResponseBody + public Iterable findAllByWebQuerydsl(@QuerydslPredicate(root = MyUser.class) Predicate predicate) { + return myUserRepository.findAll(predicate); + } + + // API - WRITE + + @RequestMapping(method = RequestMethod.POST, value = "/users") + @ResponseStatus(HttpStatus.CREATED) + public void create(@RequestBody User resource) { + Preconditions.checkNotNull(resource); + dao.save(resource); + } + + @RequestMapping(method = RequestMethod.POST, value = "/myusers") + @ResponseStatus(HttpStatus.CREATED) + public void addMyUser(@RequestBody MyUser resource) { + Preconditions.checkNotNull(resource); + myUserRepository.save(resource); + + } + +} diff --git a/spring-rest-query-language/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/error/RestResponseEntityExceptionHandler.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/web/util/CriteriaParser.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/util/CriteriaParser.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/web/util/CriteriaParser.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/util/CriteriaParser.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/web/util/SearchCriteria.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/util/SearchCriteria.java similarity index 100% rename from spring-rest-query-language/src/main/java/com/baeldung/web/util/SearchCriteria.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/util/SearchCriteria.java diff --git a/spring-rest-query-language/src/main/java/com/baeldung/web/util/SearchOperation.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/util/SearchOperation.java similarity index 96% rename from spring-rest-query-language/src/main/java/com/baeldung/web/util/SearchOperation.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/util/SearchOperation.java index acc9e0c0a8..86ad9ad749 100644 --- a/spring-rest-query-language/src/main/java/com/baeldung/web/util/SearchOperation.java +++ b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/util/SearchOperation.java @@ -1,36 +1,36 @@ -package com.baeldung.web.util; - -public enum SearchOperation { - EQUALITY, NEGATION, GREATER_THAN, LESS_THAN, LIKE, STARTS_WITH, ENDS_WITH, CONTAINS; - - public static final String[] SIMPLE_OPERATION_SET = { ":", "!", ">", "<", "~" }; - - public static final String OR_PREDICATE_FLAG = "'"; - - public static final String ZERO_OR_MORE_REGEX = "*"; - - public static final String OR_OPERATOR = "OR"; - - public static final String AND_OPERATOR = "AND"; - - public static final String LEFT_PARANTHESIS = "("; - - public static final String RIGHT_PARANTHESIS = ")"; - - public static SearchOperation getSimpleOperation(final char input) { - switch (input) { - case ':': - return EQUALITY; - case '!': - return NEGATION; - case '>': - return GREATER_THAN; - case '<': - return LESS_THAN; - case '~': - return LIKE; - default: - return null; - } - } -} +package com.baeldung.web.util; + +public enum SearchOperation { + EQUALITY, NEGATION, GREATER_THAN, LESS_THAN, LIKE, STARTS_WITH, ENDS_WITH, CONTAINS; + + public static final String[] SIMPLE_OPERATION_SET = { ":", "!", ">", "<", "~" }; + + public static final String OR_PREDICATE_FLAG = "'"; + + public static final String ZERO_OR_MORE_REGEX = "*"; + + public static final String OR_OPERATOR = "OR"; + + public static final String AND_OPERATOR = "AND"; + + public static final String LEFT_PARANTHESIS = "("; + + public static final String RIGHT_PARANTHESIS = ")"; + + public static SearchOperation getSimpleOperation(final char input) { + switch (input) { + case ':': + return EQUALITY; + case '!': + return NEGATION; + case '>': + return GREATER_THAN; + case '<': + return LESS_THAN; + case '~': + return LIKE; + default: + return null; + } + } +} diff --git a/spring-rest-query-language/src/main/java/com/baeldung/web/util/SpecSearchCriteria.java b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/util/SpecSearchCriteria.java similarity index 96% rename from spring-rest-query-language/src/main/java/com/baeldung/web/util/SpecSearchCriteria.java rename to spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/util/SpecSearchCriteria.java index 73b690673b..22b55c78fb 100644 --- a/spring-rest-query-language/src/main/java/com/baeldung/web/util/SpecSearchCriteria.java +++ b/spring-web-modules/spring-rest-query-language/src/main/java/com/baeldung/web/util/SpecSearchCriteria.java @@ -1,82 +1,82 @@ -package com.baeldung.web.util; - -public class SpecSearchCriteria { - - private String key; - private SearchOperation operation; - private Object value; - private boolean orPredicate; - - public SpecSearchCriteria() { - - } - - public SpecSearchCriteria(final String key, final SearchOperation operation, final Object value) { - super(); - this.key = key; - this.operation = operation; - this.value = value; - } - - public SpecSearchCriteria(final String orPredicate, final String key, final SearchOperation operation, final Object value) { - super(); - this.orPredicate = orPredicate != null && orPredicate.equals(SearchOperation.OR_PREDICATE_FLAG); - this.key = key; - this.operation = operation; - this.value = value; - } - - public SpecSearchCriteria(String key, String operation, String prefix, String value, String suffix) { - SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0)); - if (op != null) { - if (op == SearchOperation.EQUALITY) { // the operation may be complex operation - final boolean startWithAsterisk = prefix != null && prefix.contains(SearchOperation.ZERO_OR_MORE_REGEX); - final boolean endWithAsterisk = suffix != null && suffix.contains(SearchOperation.ZERO_OR_MORE_REGEX); - - if (startWithAsterisk && endWithAsterisk) { - op = SearchOperation.CONTAINS; - } else if (startWithAsterisk) { - op = SearchOperation.ENDS_WITH; - } else if (endWithAsterisk) { - op = SearchOperation.STARTS_WITH; - } - } - } - this.key = key; - this.operation = op; - this.value = value; - } - - public String getKey() { - return key; - } - - public void setKey(final String key) { - this.key = key; - } - - public SearchOperation getOperation() { - return operation; - } - - public void setOperation(final SearchOperation operation) { - this.operation = operation; - } - - public Object getValue() { - return value; - } - - public void setValue(final Object value) { - this.value = value; - } - - public boolean isOrPredicate() { - return orPredicate; - } - - public void setOrPredicate(boolean orPredicate) { - this.orPredicate = orPredicate; - } - -} +package com.baeldung.web.util; + +public class SpecSearchCriteria { + + private String key; + private SearchOperation operation; + private Object value; + private boolean orPredicate; + + public SpecSearchCriteria() { + + } + + public SpecSearchCriteria(final String key, final SearchOperation operation, final Object value) { + super(); + this.key = key; + this.operation = operation; + this.value = value; + } + + public SpecSearchCriteria(final String orPredicate, final String key, final SearchOperation operation, final Object value) { + super(); + this.orPredicate = orPredicate != null && orPredicate.equals(SearchOperation.OR_PREDICATE_FLAG); + this.key = key; + this.operation = operation; + this.value = value; + } + + public SpecSearchCriteria(String key, String operation, String prefix, String value, String suffix) { + SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0)); + if (op != null) { + if (op == SearchOperation.EQUALITY) { // the operation may be complex operation + final boolean startWithAsterisk = prefix != null && prefix.contains(SearchOperation.ZERO_OR_MORE_REGEX); + final boolean endWithAsterisk = suffix != null && suffix.contains(SearchOperation.ZERO_OR_MORE_REGEX); + + if (startWithAsterisk && endWithAsterisk) { + op = SearchOperation.CONTAINS; + } else if (startWithAsterisk) { + op = SearchOperation.ENDS_WITH; + } else if (endWithAsterisk) { + op = SearchOperation.STARTS_WITH; + } + } + } + this.key = key; + this.operation = op; + this.value = value; + } + + public String getKey() { + return key; + } + + public void setKey(final String key) { + this.key = key; + } + + public SearchOperation getOperation() { + return operation; + } + + public void setOperation(final SearchOperation operation) { + this.operation = operation; + } + + public Object getValue() { + return value; + } + + public void setValue(final Object value) { + this.value = value; + } + + public boolean isOrPredicate() { + return orPredicate; + } + + public void setOrPredicate(boolean orPredicate) { + this.orPredicate = orPredicate; + } + +} diff --git a/spring-rest-query-language/src/main/resources/application.properties b/spring-web-modules/spring-rest-query-language/src/main/resources/application.properties similarity index 100% rename from spring-rest-query-language/src/main/resources/application.properties rename to spring-web-modules/spring-rest-query-language/src/main/resources/application.properties diff --git a/spring-rest-query-language/src/main/resources/data.sql b/spring-web-modules/spring-rest-query-language/src/main/resources/data.sql similarity index 100% rename from spring-rest-query-language/src/main/resources/data.sql rename to spring-web-modules/spring-rest-query-language/src/main/resources/data.sql diff --git a/spring-rest-query-language/src/main/resources/logback.xml b/spring-web-modules/spring-rest-query-language/src/main/resources/logback.xml similarity index 100% rename from spring-rest-query-language/src/main/resources/logback.xml rename to spring-web-modules/spring-rest-query-language/src/main/resources/logback.xml diff --git a/spring-rest-query-language/src/main/resources/persistence-h2.properties b/spring-web-modules/spring-rest-query-language/src/main/resources/persistence-h2.properties similarity index 100% rename from spring-rest-query-language/src/main/resources/persistence-h2.properties rename to spring-web-modules/spring-rest-query-language/src/main/resources/persistence-h2.properties diff --git a/spring-rest-query-language/src/main/resources/persistence-mysql.properties b/spring-web-modules/spring-rest-query-language/src/main/resources/persistence-mysql.properties similarity index 100% rename from spring-rest-query-language/src/main/resources/persistence-mysql.properties rename to spring-web-modules/spring-rest-query-language/src/main/resources/persistence-mysql.properties diff --git a/spring-rest-query-language/src/main/resources/springDataPersistenceConfig.xml b/spring-web-modules/spring-rest-query-language/src/main/resources/springDataPersistenceConfig.xml similarity index 100% rename from spring-rest-query-language/src/main/resources/springDataPersistenceConfig.xml rename to spring-web-modules/spring-rest-query-language/src/main/resources/springDataPersistenceConfig.xml diff --git a/spring-rest-query-language/src/main/webapp/WEB-INF/api-servlet.xml b/spring-web-modules/spring-rest-query-language/src/main/webapp/WEB-INF/api-servlet.xml similarity index 100% rename from spring-rest-query-language/src/main/webapp/WEB-INF/api-servlet.xml rename to spring-web-modules/spring-rest-query-language/src/main/webapp/WEB-INF/api-servlet.xml diff --git a/spring-rest-query-language/src/main/webapp/WEB-INF/view/homepage.jsp b/spring-web-modules/spring-rest-query-language/src/main/webapp/WEB-INF/view/homepage.jsp similarity index 100% rename from spring-rest-query-language/src/main/webapp/WEB-INF/view/homepage.jsp rename to spring-web-modules/spring-rest-query-language/src/main/webapp/WEB-INF/view/homepage.jsp diff --git a/spring-rest-query-language/src/main/webapp/WEB-INF/web.xml b/spring-web-modules/spring-rest-query-language/src/main/webapp/WEB-INF/web.xml similarity index 100% rename from spring-rest-query-language/src/main/webapp/WEB-INF/web.xml rename to spring-web-modules/spring-rest-query-language/src/main/webapp/WEB-INF/web.xml diff --git a/spring-rest-query-language/src/test/java/com/baeldung/SpringContextTest.java b/spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-rest-query-language/src/test/java/com/baeldung/SpringContextTest.java rename to spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPACriteriaQueryIntegrationTest.java b/spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPACriteriaQueryIntegrationTest.java similarity index 100% rename from spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPACriteriaQueryIntegrationTest.java rename to spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPACriteriaQueryIntegrationTest.java diff --git a/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPAQuerydslIntegrationTest.java b/spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPAQuerydslIntegrationTest.java similarity index 100% rename from spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPAQuerydslIntegrationTest.java rename to spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPAQuerydslIntegrationTest.java diff --git a/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPASpecificationIntegrationTest.java b/spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPASpecificationIntegrationTest.java similarity index 97% rename from spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPASpecificationIntegrationTest.java rename to spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPASpecificationIntegrationTest.java index 707426769e..f6fff10506 100644 --- a/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPASpecificationIntegrationTest.java +++ b/spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPASpecificationIntegrationTest.java @@ -1,180 +1,180 @@ -package com.baeldung.persistence.query; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.test.annotation.Rollback; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.transaction.annotation.Transactional; - -import com.baeldung.persistence.dao.GenericSpecificationsBuilder; -import com.baeldung.persistence.dao.UserRepository; -import com.baeldung.persistence.dao.UserSpecification; -import com.baeldung.persistence.dao.UserSpecificationsBuilder; -import com.baeldung.persistence.model.User; -import com.baeldung.spring.PersistenceConfig; -import com.baeldung.web.util.CriteriaParser; -import com.baeldung.web.util.SearchOperation; -import com.baeldung.web.util.SpecSearchCriteria; - -import java.util.List; -import java.util.function.Function; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.collection.IsCollectionWithSize.hasSize; -import static org.hamcrest.collection.IsIn.isIn; -import static org.hamcrest.core.IsNot.not; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { PersistenceConfig.class }) -@Transactional -@Rollback -public class JPASpecificationIntegrationTest { - - @Autowired - private UserRepository repository; - - private User userJohn; - - private User userTom; - - private User userPercy; - - @Before - public void init() { - userJohn = new User(); - userJohn.setFirstName("john"); - userJohn.setLastName("doe"); - userJohn.setEmail("john@doe.com"); - userJohn.setAge(22); - repository.save(userJohn); - - userTom = new User(); - userTom.setFirstName("tom"); - userTom.setLastName("doe"); - userTom.setEmail("tom@doe.com"); - userTom.setAge(26); - repository.save(userTom); - - userPercy = new User(); - userPercy.setFirstName("percy"); - userPercy.setLastName("blackney"); - userPercy.setEmail("percy@blackney.com"); - userPercy.setAge(30); - repository.save(userPercy); - } - - @Test - public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.EQUALITY, "john")); - final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("lastName", SearchOperation.EQUALITY, "doe")); - final List results = repository.findAll(Specification - .where(spec) - .and(spec1)); - - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } - - @Test - public void givenFirstOrLastName_whenGettingListOfUsers_thenCorrect() { - UserSpecificationsBuilder builder = new UserSpecificationsBuilder(); - - SpecSearchCriteria spec = new SpecSearchCriteria("firstName", SearchOperation.EQUALITY, "john"); - SpecSearchCriteria spec1 = new SpecSearchCriteria("'","lastName", SearchOperation.EQUALITY, "doe"); - - List results = repository.findAll(builder - .with(spec) - .with(spec1) - .build()); - - assertThat(results, hasSize(2)); - assertThat(userJohn, isIn(results)); - assertThat(userTom, isIn(results)); - } - - @Test - public void givenFirstOrLastNameAndAgeGenericBuilder_whenGettingListOfUsers_thenCorrect() { - GenericSpecificationsBuilder builder = new GenericSpecificationsBuilder<>(); - Function> converter = UserSpecification::new; - - CriteriaParser parser=new CriteriaParser(); - List results = repository.findAll(builder.build(parser.parse("( lastName:doe OR firstName:john ) AND age:22"), converter)); - - assertThat(results, hasSize(1)); - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } - - @Test - public void givenFirstOrLastNameGenericBuilder_whenGettingListOfUsers_thenCorrect() { - GenericSpecificationsBuilder builder = new GenericSpecificationsBuilder<>(); - Function> converter = UserSpecification::new; - - builder.with("firstName", ":", "john", null, null); - builder.with("'", "lastName", ":", "doe", null, null); - - List results = repository.findAll(builder.build(converter)); - - assertThat(results, hasSize(2)); - assertThat(userJohn, isIn(results)); - assertThat(userTom, isIn(results)); - } - - @Test - public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.NEGATION, "john")); - final List results = repository.findAll(Specification.where(spec)); - - assertThat(userTom, isIn(results)); - assertThat(userJohn, not(isIn(results))); - } - - @Test - public void givenMinAge_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "25")); - final List results = repository.findAll(Specification.where(spec)); - assertThat(userTom, isIn(results)); - assertThat(userJohn, not(isIn(results))); - } - - @Test - public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.STARTS_WITH, "jo")); - final List results = repository.findAll(spec); - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } - - @Test - public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.ENDS_WITH, "n")); - final List results = repository.findAll(spec); - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } - - @Test - public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.CONTAINS, "oh")); - final List results = repository.findAll(spec); - - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } - - @Test - public void givenAgeRange_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "20")); - final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.LESS_THAN, "25")); - final List results = repository.findAll(Specification - .where(spec) - .and(spec1)); - - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } -} +package com.baeldung.persistence.query; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.test.annotation.Rollback; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +import com.baeldung.persistence.dao.GenericSpecificationsBuilder; +import com.baeldung.persistence.dao.UserRepository; +import com.baeldung.persistence.dao.UserSpecification; +import com.baeldung.persistence.dao.UserSpecificationsBuilder; +import com.baeldung.persistence.model.User; +import com.baeldung.spring.PersistenceConfig; +import com.baeldung.web.util.CriteriaParser; +import com.baeldung.web.util.SearchOperation; +import com.baeldung.web.util.SpecSearchCriteria; + +import java.util.List; +import java.util.function.Function; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.hamcrest.collection.IsIn.isIn; +import static org.hamcrest.core.IsNot.not; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }) +@Transactional +@Rollback +public class JPASpecificationIntegrationTest { + + @Autowired + private UserRepository repository; + + private User userJohn; + + private User userTom; + + private User userPercy; + + @Before + public void init() { + userJohn = new User(); + userJohn.setFirstName("john"); + userJohn.setLastName("doe"); + userJohn.setEmail("john@doe.com"); + userJohn.setAge(22); + repository.save(userJohn); + + userTom = new User(); + userTom.setFirstName("tom"); + userTom.setLastName("doe"); + userTom.setEmail("tom@doe.com"); + userTom.setAge(26); + repository.save(userTom); + + userPercy = new User(); + userPercy.setFirstName("percy"); + userPercy.setLastName("blackney"); + userPercy.setEmail("percy@blackney.com"); + userPercy.setAge(30); + repository.save(userPercy); + } + + @Test + public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.EQUALITY, "john")); + final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("lastName", SearchOperation.EQUALITY, "doe")); + final List results = repository.findAll(Specification + .where(spec) + .and(spec1)); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenFirstOrLastName_whenGettingListOfUsers_thenCorrect() { + UserSpecificationsBuilder builder = new UserSpecificationsBuilder(); + + SpecSearchCriteria spec = new SpecSearchCriteria("firstName", SearchOperation.EQUALITY, "john"); + SpecSearchCriteria spec1 = new SpecSearchCriteria("'","lastName", SearchOperation.EQUALITY, "doe"); + + List results = repository.findAll(builder + .with(spec) + .with(spec1) + .build()); + + assertThat(results, hasSize(2)); + assertThat(userJohn, isIn(results)); + assertThat(userTom, isIn(results)); + } + + @Test + public void givenFirstOrLastNameAndAgeGenericBuilder_whenGettingListOfUsers_thenCorrect() { + GenericSpecificationsBuilder builder = new GenericSpecificationsBuilder<>(); + Function> converter = UserSpecification::new; + + CriteriaParser parser=new CriteriaParser(); + List results = repository.findAll(builder.build(parser.parse("( lastName:doe OR firstName:john ) AND age:22"), converter)); + + assertThat(results, hasSize(1)); + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenFirstOrLastNameGenericBuilder_whenGettingListOfUsers_thenCorrect() { + GenericSpecificationsBuilder builder = new GenericSpecificationsBuilder<>(); + Function> converter = UserSpecification::new; + + builder.with("firstName", ":", "john", null, null); + builder.with("'", "lastName", ":", "doe", null, null); + + List results = repository.findAll(builder.build(converter)); + + assertThat(results, hasSize(2)); + assertThat(userJohn, isIn(results)); + assertThat(userTom, isIn(results)); + } + + @Test + public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.NEGATION, "john")); + final List results = repository.findAll(Specification.where(spec)); + + assertThat(userTom, isIn(results)); + assertThat(userJohn, not(isIn(results))); + } + + @Test + public void givenMinAge_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "25")); + final List results = repository.findAll(Specification.where(spec)); + assertThat(userTom, isIn(results)); + assertThat(userJohn, not(isIn(results))); + } + + @Test + public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.STARTS_WITH, "jo")); + final List results = repository.findAll(spec); + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.ENDS_WITH, "n")); + final List results = repository.findAll(spec); + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.CONTAINS, "oh")); + final List results = repository.findAll(spec); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenAgeRange_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "20")); + final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.LESS_THAN, "25")); + final List results = repository.findAll(Specification + .where(spec) + .and(spec1)); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } +} diff --git a/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPASpecificationLiveTest.java b/spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPASpecificationLiveTest.java similarity index 97% rename from spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPASpecificationLiveTest.java rename to spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPASpecificationLiveTest.java index ad6a4259e7..d1fded3f10 100644 --- a/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPASpecificationLiveTest.java +++ b/spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/JPASpecificationLiveTest.java @@ -1,147 +1,147 @@ -package com.baeldung.persistence.query; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import io.restassured.RestAssured; -import io.restassured.response.Response; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.test.context.ActiveProfiles; - -import com.baeldung.persistence.model.User; - -//@RunWith(SpringJUnit4ClassRunner.class) -//@ContextConfiguration(classes = { ConfigTest.class, -// PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) -@ActiveProfiles("test") -public class JPASpecificationLiveTest { - - // @Autowired - // private UserRepository repository; - - private User userJohn; - - private User userTom; - - private final String URL_PREFIX = "http://localhost:8082/spring-rest-query-language/auth/users/spec?search="; - - @Before - public void init() { - userJohn = new User(); - userJohn.setFirstName("john"); - userJohn.setLastName("doe"); - userJohn.setEmail("john@doe.com"); - userJohn.setAge(22); - // repository.save(userJohn); - - userTom = new User(); - userTom.setFirstName("tom"); - userTom.setLastName("doe"); - userTom.setEmail("tom@doe.com"); - userTom.setAge(26); - // repository.save(userTom); - } - - private final String EURL_PREFIX = "http://localhost:8082/spring-rest-query-language/auth/users/espec?search="; - - @Test - public void givenFirstOrLastName_whenGettingListOfUsers_thenCorrect() { - final Response response = RestAssured.get(EURL_PREFIX + "firstName:john,'lastName:doe"); - final String result = response.body() - .asString(); - assertTrue(result.contains(userJohn.getEmail())); - assertTrue(result.contains(userTom.getEmail())); - } - - @Test - public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { - final Response response = RestAssured.get(URL_PREFIX + "firstName:john,lastName:doe"); - final String result = response.body() - .asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - @Test - public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() { - final Response response = RestAssured.get(URL_PREFIX + "firstName!john"); - final String result = response.body() - .asString(); - - assertTrue(result.contains(userTom.getEmail())); - assertFalse(result.contains(userJohn.getEmail())); - } - - @Test - public void givenMinAge_whenGettingListOfUsers_thenCorrect() { - final Response response = RestAssured.get(URL_PREFIX + "age>25"); - final String result = response.body() - .asString(); - - assertTrue(result.contains(userTom.getEmail())); - assertFalse(result.contains(userJohn.getEmail())); - } - - @Test - public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() { - final Response response = RestAssured.get(URL_PREFIX + "firstName:jo*"); - final String result = response.body() - .asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - @Test - public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() { - final Response response = RestAssured.get(URL_PREFIX + "firstName:*n"); - final String result = response.body() - .asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - @Test - public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() { - final Response response = RestAssured.get(URL_PREFIX + "firstName:*oh*"); - final String result = response.body() - .asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - @Test - public void givenAgeRange_whenGettingListOfUsers_thenCorrect() { - final Response response = RestAssured.get(URL_PREFIX + "age>20,age<25"); - final String result = response.body() - .asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - private final String ADV_URL_PREFIX = "http://localhost:8082/spring-rest-query-language/auth/users/spec/adv?search="; - - @Test - public void givenFirstOrLastName_whenGettingAdvListOfUsers_thenCorrect() { - final Response response = RestAssured.get(ADV_URL_PREFIX + "firstName:john OR lastName:doe"); - final String result = response.body() - .asString(); - assertTrue(result.contains(userJohn.getEmail())); - assertTrue(result.contains(userTom.getEmail())); - } - - @Test - public void givenFirstOrFirstNameAndAge_whenGettingAdvListOfUsers_thenCorrect() { - final Response response = RestAssured.get(ADV_URL_PREFIX + "( firstName:john OR firstName:tom ) AND age>22"); - final String result = response.body() - .asString(); - assertFalse(result.contains(userJohn.getEmail())); - assertTrue(result.contains(userTom.getEmail())); - } - -} +package com.baeldung.persistence.query; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import io.restassured.RestAssured; +import io.restassured.response.Response; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.test.context.ActiveProfiles; + +import com.baeldung.persistence.model.User; + +//@RunWith(SpringJUnit4ClassRunner.class) +//@ContextConfiguration(classes = { ConfigTest.class, +// PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +@ActiveProfiles("test") +public class JPASpecificationLiveTest { + + // @Autowired + // private UserRepository repository; + + private User userJohn; + + private User userTom; + + private final String URL_PREFIX = "http://localhost:8082/spring-rest-query-language/auth/users/spec?search="; + + @Before + public void init() { + userJohn = new User(); + userJohn.setFirstName("john"); + userJohn.setLastName("doe"); + userJohn.setEmail("john@doe.com"); + userJohn.setAge(22); + // repository.save(userJohn); + + userTom = new User(); + userTom.setFirstName("tom"); + userTom.setLastName("doe"); + userTom.setEmail("tom@doe.com"); + userTom.setAge(26); + // repository.save(userTom); + } + + private final String EURL_PREFIX = "http://localhost:8082/spring-rest-query-language/auth/users/espec?search="; + + @Test + public void givenFirstOrLastName_whenGettingListOfUsers_thenCorrect() { + final Response response = RestAssured.get(EURL_PREFIX + "firstName:john,'lastName:doe"); + final String result = response.body() + .asString(); + assertTrue(result.contains(userJohn.getEmail())); + assertTrue(result.contains(userTom.getEmail())); + } + + @Test + public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { + final Response response = RestAssured.get(URL_PREFIX + "firstName:john,lastName:doe"); + final String result = response.body() + .asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + @Test + public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() { + final Response response = RestAssured.get(URL_PREFIX + "firstName!john"); + final String result = response.body() + .asString(); + + assertTrue(result.contains(userTom.getEmail())); + assertFalse(result.contains(userJohn.getEmail())); + } + + @Test + public void givenMinAge_whenGettingListOfUsers_thenCorrect() { + final Response response = RestAssured.get(URL_PREFIX + "age>25"); + final String result = response.body() + .asString(); + + assertTrue(result.contains(userTom.getEmail())); + assertFalse(result.contains(userJohn.getEmail())); + } + + @Test + public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() { + final Response response = RestAssured.get(URL_PREFIX + "firstName:jo*"); + final String result = response.body() + .asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + @Test + public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() { + final Response response = RestAssured.get(URL_PREFIX + "firstName:*n"); + final String result = response.body() + .asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + @Test + public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() { + final Response response = RestAssured.get(URL_PREFIX + "firstName:*oh*"); + final String result = response.body() + .asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + @Test + public void givenAgeRange_whenGettingListOfUsers_thenCorrect() { + final Response response = RestAssured.get(URL_PREFIX + "age>20,age<25"); + final String result = response.body() + .asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + private final String ADV_URL_PREFIX = "http://localhost:8082/spring-rest-query-language/auth/users/spec/adv?search="; + + @Test + public void givenFirstOrLastName_whenGettingAdvListOfUsers_thenCorrect() { + final Response response = RestAssured.get(ADV_URL_PREFIX + "firstName:john OR lastName:doe"); + final String result = response.body() + .asString(); + assertTrue(result.contains(userJohn.getEmail())); + assertTrue(result.contains(userTom.getEmail())); + } + + @Test + public void givenFirstOrFirstNameAndAge_whenGettingAdvListOfUsers_thenCorrect() { + final Response response = RestAssured.get(ADV_URL_PREFIX + "( firstName:john OR firstName:tom ) AND age>22"); + final String result = response.body() + .asString(); + assertFalse(result.contains(userJohn.getEmail())); + assertTrue(result.contains(userTom.getEmail())); + } + +} diff --git a/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/RsqlIntegrationTest.java b/spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/RsqlIntegrationTest.java similarity index 100% rename from spring-rest-query-language/src/test/java/com/baeldung/persistence/query/RsqlIntegrationTest.java rename to spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/persistence/query/RsqlIntegrationTest.java diff --git a/spring-rest-query-language/src/test/java/com/baeldung/web/MyUserLiveTest.java b/spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/web/MyUserLiveTest.java similarity index 100% rename from spring-rest-query-language/src/test/java/com/baeldung/web/MyUserLiveTest.java rename to spring-web-modules/spring-rest-query-language/src/test/java/com/baeldung/web/MyUserLiveTest.java diff --git a/spring-rest-query-language/.gitignore b/spring-web-modules/spring-rest-query-language/src/test/resources/.gitignore similarity index 100% rename from spring-rest-query-language/.gitignore rename to spring-web-modules/spring-rest-query-language/src/test/resources/.gitignore diff --git a/spring-rest-shell/README.md b/spring-web-modules/spring-rest-shell/README.md similarity index 100% rename from spring-rest-shell/README.md rename to spring-web-modules/spring-rest-shell/README.md diff --git a/spring-rest-shell/pom.xml b/spring-web-modules/spring-rest-shell/pom.xml similarity index 96% rename from spring-rest-shell/pom.xml rename to spring-web-modules/spring-rest-shell/pom.xml index 1148a5c093..f5792fd6ca 100644 --- a/spring-rest-shell/pom.xml +++ b/spring-web-modules/spring-rest-shell/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 diff --git a/spring-rest-shell/src/main/java/com/baeldung/Application.java b/spring-web-modules/spring-rest-shell/src/main/java/com/baeldung/Application.java similarity index 100% rename from spring-rest-shell/src/main/java/com/baeldung/Application.java rename to spring-web-modules/spring-rest-shell/src/main/java/com/baeldung/Application.java diff --git a/spring-rest-shell/src/main/java/com/baeldung/acticle/Article.java b/spring-web-modules/spring-rest-shell/src/main/java/com/baeldung/acticle/Article.java similarity index 100% rename from spring-rest-shell/src/main/java/com/baeldung/acticle/Article.java rename to spring-web-modules/spring-rest-shell/src/main/java/com/baeldung/acticle/Article.java diff --git a/spring-rest-shell/src/main/java/com/baeldung/acticle/ArticleRepository.java b/spring-web-modules/spring-rest-shell/src/main/java/com/baeldung/acticle/ArticleRepository.java similarity index 100% rename from spring-rest-shell/src/main/java/com/baeldung/acticle/ArticleRepository.java rename to spring-web-modules/spring-rest-shell/src/main/java/com/baeldung/acticle/ArticleRepository.java diff --git a/spring-session/spring-session-mongodb/src/main/resources/logback.xml b/spring-web-modules/spring-rest-shell/src/main/resources/logback.xml similarity index 100% rename from spring-session/spring-session-mongodb/src/main/resources/logback.xml rename to spring-web-modules/spring-rest-shell/src/main/resources/logback.xml diff --git a/spring-rest-simple/README.md b/spring-web-modules/spring-rest-simple/README.md similarity index 100% rename from spring-rest-simple/README.md rename to spring-web-modules/spring-rest-simple/README.md diff --git a/spring-rest-simple/pom.xml b/spring-web-modules/spring-rest-simple/pom.xml similarity index 99% rename from spring-rest-simple/pom.xml rename to spring-web-modules/spring-rest-simple/pom.xml index 291053c87f..b9d5100fbf 100644 --- a/spring-rest-simple/pom.xml +++ b/spring-web-modules/spring-rest-simple/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 @@ -314,7 +314,6 @@ - 1.3.3 4.0.0 1.4 3.1.0 diff --git a/spring-rest-simple/src/main/java/com/baeldung/Application.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/Application.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/Application.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/Application.java diff --git a/spring-rest-simple/src/main/java/com/baeldung/apachefileupload/UploadController.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/apachefileupload/UploadController.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/apachefileupload/UploadController.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/apachefileupload/UploadController.java diff --git a/spring-rest-simple/src/main/java/com/baeldung/config/MvcConfig.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/config/MvcConfig.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/config/MvcConfig.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/config/MvcConfig.java diff --git a/spring-rest-simple/src/main/java/com/baeldung/config/converter/KryoHttpMessageConverter.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/config/converter/KryoHttpMessageConverter.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/config/converter/KryoHttpMessageConverter.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/config/converter/KryoHttpMessageConverter.java diff --git a/spring-rest-simple/src/main/java/com/baeldung/repository/BookRepository.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/repository/BookRepository.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/repository/BookRepository.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/repository/BookRepository.java diff --git a/spring-rest-simple/src/main/java/com/baeldung/web/controller/ApiExceptionHandler.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/controller/ApiExceptionHandler.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/web/controller/ApiExceptionHandler.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/controller/ApiExceptionHandler.java diff --git a/spring-rest-simple/src/main/java/com/baeldung/web/controller/BookController.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/controller/BookController.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/web/controller/BookController.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/controller/BookController.java diff --git a/spring-rest-simple/src/main/java/com/baeldung/web/controller/FooController.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/controller/FooController.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/web/controller/FooController.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/controller/FooController.java diff --git a/spring-rest-simple/src/main/java/com/baeldung/web/dto/Bazz.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/dto/Bazz.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/web/dto/Bazz.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/dto/Bazz.java diff --git a/spring-rest-simple/src/main/java/com/baeldung/web/dto/Book.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/dto/Book.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/web/dto/Book.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/dto/Book.java diff --git a/spring-rest-simple/src/main/java/com/baeldung/web/dto/Foo.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/dto/Foo.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/web/dto/Foo.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/dto/Foo.java diff --git a/spring-rest-simple/src/main/java/com/baeldung/web/dto/FooProtos.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/dto/FooProtos.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/web/dto/FooProtos.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/dto/FooProtos.java diff --git a/spring-rest-simple/src/main/java/com/baeldung/web/error/ApiErrorResponse.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/error/ApiErrorResponse.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/web/error/ApiErrorResponse.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/error/ApiErrorResponse.java diff --git a/spring-rest-simple/src/main/java/com/baeldung/web/error/BookNotFoundException.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/error/BookNotFoundException.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/web/error/BookNotFoundException.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/error/BookNotFoundException.java diff --git a/spring-rest-simple/src/main/java/com/baeldung/web/util/LinkUtil.java b/spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/util/LinkUtil.java similarity index 100% rename from spring-rest-simple/src/main/java/com/baeldung/web/util/LinkUtil.java rename to spring-web-modules/spring-rest-simple/src/main/java/com/baeldung/web/util/LinkUtil.java diff --git a/spring-rest-simple/src/main/resources/application.properties b/spring-web-modules/spring-rest-simple/src/main/resources/application.properties similarity index 100% rename from spring-rest-simple/src/main/resources/application.properties rename to spring-web-modules/spring-rest-simple/src/main/resources/application.properties diff --git a/spring-rest-simple/src/main/resources/logback.xml b/spring-web-modules/spring-rest-simple/src/main/resources/logback.xml similarity index 100% rename from spring-rest-simple/src/main/resources/logback.xml rename to spring-web-modules/spring-rest-simple/src/main/resources/logback.xml diff --git a/spring-rest-simple/src/main/webapp/WEB-INF/company.html b/spring-web-modules/spring-rest-simple/src/main/webapp/WEB-INF/company.html similarity index 100% rename from spring-rest-simple/src/main/webapp/WEB-INF/company.html rename to spring-web-modules/spring-rest-simple/src/main/webapp/WEB-INF/company.html diff --git a/spring-rest-simple/src/main/webapp/WEB-INF/spring-views.xml b/spring-web-modules/spring-rest-simple/src/main/webapp/WEB-INF/spring-views.xml similarity index 100% rename from spring-rest-simple/src/main/webapp/WEB-INF/spring-views.xml rename to spring-web-modules/spring-rest-simple/src/main/webapp/WEB-INF/spring-views.xml diff --git a/spring-rest-simple/src/main/webapp/WEB-INF/spring-web-config.xml b/spring-web-modules/spring-rest-simple/src/main/webapp/WEB-INF/spring-web-config.xml similarity index 100% rename from spring-rest-simple/src/main/webapp/WEB-INF/spring-web-config.xml rename to spring-web-modules/spring-rest-simple/src/main/webapp/WEB-INF/spring-web-config.xml diff --git a/spring-rest-simple/src/test/java/com/baeldung/SpringContextTest.java b/spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-rest-simple/src/test/java/com/baeldung/SpringContextTest.java rename to spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-rest-simple/src/test/java/com/baeldung/repository/BookRepositoryUnitTest.java b/spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/repository/BookRepositoryUnitTest.java similarity index 100% rename from spring-rest-simple/src/test/java/com/baeldung/repository/BookRepositoryUnitTest.java rename to spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/repository/BookRepositoryUnitTest.java diff --git a/spring-rest-simple/src/test/java/com/baeldung/web/controller/BookControllerIntegrationTest.java b/spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/controller/BookControllerIntegrationTest.java similarity index 100% rename from spring-rest-simple/src/test/java/com/baeldung/web/controller/BookControllerIntegrationTest.java rename to spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/controller/BookControllerIntegrationTest.java diff --git a/spring-rest-simple/src/test/java/com/baeldung/web/controller/mediatypes/TestConfig.java b/spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/controller/mediatypes/TestConfig.java similarity index 100% rename from spring-rest-simple/src/test/java/com/baeldung/web/controller/mediatypes/TestConfig.java rename to spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/controller/mediatypes/TestConfig.java diff --git a/spring-rest-simple/src/test/java/com/baeldung/web/test/RequestMappingLiveTest.java b/spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/test/RequestMappingLiveTest.java similarity index 100% rename from spring-rest-simple/src/test/java/com/baeldung/web/test/RequestMappingLiveTest.java rename to spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/test/RequestMappingLiveTest.java diff --git a/spring-rest-simple/src/test/java/com/baeldung/web/test/RestTemplateBasicLiveTest.java b/spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/test/RestTemplateBasicLiveTest.java similarity index 100% rename from spring-rest-simple/src/test/java/com/baeldung/web/test/RestTemplateBasicLiveTest.java rename to spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/test/RestTemplateBasicLiveTest.java diff --git a/spring-rest-simple/src/test/java/com/baeldung/web/test/SpringHttpMessageConvertersLiveTest.java b/spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/test/SpringHttpMessageConvertersLiveTest.java similarity index 100% rename from spring-rest-simple/src/test/java/com/baeldung/web/test/SpringHttpMessageConvertersLiveTest.java rename to spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/test/SpringHttpMessageConvertersLiveTest.java diff --git a/spring-rest-simple/src/test/java/com/baeldung/web/test/TestRestTemplateBasicLiveTest.java b/spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/test/TestRestTemplateBasicLiveTest.java similarity index 100% rename from spring-rest-simple/src/test/java/com/baeldung/web/test/TestRestTemplateBasicLiveTest.java rename to spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/test/TestRestTemplateBasicLiveTest.java diff --git a/spring-rest-simple/src/test/java/com/baeldung/web/util/HTTPLinkHeaderUtil.java b/spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/util/HTTPLinkHeaderUtil.java similarity index 100% rename from spring-rest-simple/src/test/java/com/baeldung/web/util/HTTPLinkHeaderUtil.java rename to spring-web-modules/spring-rest-simple/src/test/java/com/baeldung/web/util/HTTPLinkHeaderUtil.java diff --git a/spring-rest-query-language/src/test/resources/.gitignore b/spring-web-modules/spring-rest-simple/src/test/resources/.gitignore similarity index 100% rename from spring-rest-query-language/src/test/resources/.gitignore rename to spring-web-modules/spring-rest-simple/src/test/resources/.gitignore diff --git a/spring-rest-simple/src/test/resources/.gitignore b/spring-web-modules/spring-rest-testing/.gitignore similarity index 100% rename from spring-rest-simple/src/test/resources/.gitignore rename to spring-web-modules/spring-rest-testing/.gitignore diff --git a/spring-rest-testing/README.md b/spring-web-modules/spring-rest-testing/README.md similarity index 100% rename from spring-rest-testing/README.md rename to spring-web-modules/spring-rest-testing/README.md diff --git a/spring-rest-testing/pom.xml b/spring-web-modules/spring-rest-testing/pom.xml similarity index 98% rename from spring-rest-testing/pom.xml rename to spring-web-modules/spring-rest-testing/pom.xml index 9bfe9d83a4..fea8d25e4d 100644 --- a/spring-rest-testing/pom.xml +++ b/spring-web-modules/spring-rest-testing/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 @@ -120,7 +120,7 @@ org.hibernate - hibernate-entitymanager + hibernate-core xml-apis diff --git a/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/ExceptionTestingApplication.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/ExceptionTestingApplication.java similarity index 97% rename from spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/ExceptionTestingApplication.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/ExceptionTestingApplication.java index facc300dfa..b6e62b7295 100644 --- a/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/ExceptionTestingApplication.java +++ b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/ExceptionTestingApplication.java @@ -1,25 +1,25 @@ -package com.baeldung.exceptiontesting; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.scheduling.annotation.EnableScheduling; - -/** - * Main Application Class - uses Spring Boot. Just run this as a normal Java - * class to run up a Jetty Server (on http://localhost:8082/spring-rest-full) - * - */ -@EnableScheduling -@EnableAutoConfiguration -@ComponentScan("com.baeldung.exceptiontesting") -@SpringBootApplication -public class ExceptionTestingApplication extends SpringBootServletInitializer { - - public static void main(final String[] args) { - SpringApplication.run(ExceptionTestingApplication.class, args); - } - +package com.baeldung.exceptiontesting; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * Main Application Class - uses Spring Boot. Just run this as a normal Java + * class to run up a Jetty Server (on http://localhost:8082/spring-rest-full) + * + */ +@EnableScheduling +@EnableAutoConfiguration +@ComponentScan("com.baeldung.exceptiontesting") +@SpringBootApplication +public class ExceptionTestingApplication extends SpringBootServletInitializer { + + public static void main(final String[] args) { + SpringApplication.run(ExceptionTestingApplication.class, args); + } + } \ No newline at end of file diff --git a/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/controller/ExceptionController.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/controller/ExceptionController.java similarity index 97% rename from spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/controller/ExceptionController.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/controller/ExceptionController.java index 0f458b5f10..6d98337e40 100644 --- a/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/controller/ExceptionController.java +++ b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/controller/ExceptionController.java @@ -1,31 +1,31 @@ -package com.baeldung.exceptiontesting.controller; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RestController; - -import com.baeldung.exceptiontesting.exception.BadArgumentsException; -import com.baeldung.exceptiontesting.exception.InternalException; -import com.baeldung.exceptiontesting.exception.ResourceNotFoundException; - -@RestController -public class ExceptionController { - - @GetMapping("/exception/{exception_id}") - public void getSpecificException(@PathVariable("exception_id") String pException) { - if("not_found".equals(pException)) { - throw new ResourceNotFoundException("resource not found"); - } - else if("bad_arguments".equals(pException)) { - throw new BadArgumentsException("bad arguments"); - } - else { - throw new InternalException("internal error"); - } - } - - @GetMapping("/exception/throw") - public void getException() throws Exception { - throw new Exception("error"); - } -} +package com.baeldung.exceptiontesting.controller; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.exceptiontesting.exception.BadArgumentsException; +import com.baeldung.exceptiontesting.exception.InternalException; +import com.baeldung.exceptiontesting.exception.ResourceNotFoundException; + +@RestController +public class ExceptionController { + + @GetMapping("/exception/{exception_id}") + public void getSpecificException(@PathVariable("exception_id") String pException) { + if("not_found".equals(pException)) { + throw new ResourceNotFoundException("resource not found"); + } + else if("bad_arguments".equals(pException)) { + throw new BadArgumentsException("bad arguments"); + } + else { + throw new InternalException("internal error"); + } + } + + @GetMapping("/exception/throw") + public void getException() throws Exception { + throw new Exception("error"); + } +} diff --git a/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/BadArgumentsException.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/BadArgumentsException.java similarity index 96% rename from spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/BadArgumentsException.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/BadArgumentsException.java index 1eb1e6a3c9..1f0e1c1ddb 100644 --- a/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/BadArgumentsException.java +++ b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/BadArgumentsException.java @@ -1,13 +1,13 @@ -package com.baeldung.exceptiontesting.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@SuppressWarnings("serial") -@ResponseStatus(HttpStatus.BAD_REQUEST) -public class BadArgumentsException extends RuntimeException { - - public BadArgumentsException(String message) { - super(message); - } -} +package com.baeldung.exceptiontesting.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@SuppressWarnings("serial") +@ResponseStatus(HttpStatus.BAD_REQUEST) +public class BadArgumentsException extends RuntimeException { + + public BadArgumentsException(String message) { + super(message); + } +} diff --git a/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/InternalException.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/InternalException.java similarity index 96% rename from spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/InternalException.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/InternalException.java index 8e9f0f60f3..854d6a57f0 100644 --- a/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/InternalException.java +++ b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/InternalException.java @@ -1,13 +1,13 @@ -package com.baeldung.exceptiontesting.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@SuppressWarnings("serial") -@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) -public class InternalException extends RuntimeException { - - public InternalException(String message) { - super(message); - } -} +package com.baeldung.exceptiontesting.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@SuppressWarnings("serial") +@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) +public class InternalException extends RuntimeException { + + public InternalException(String message) { + super(message); + } +} diff --git a/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/ResourceNotFoundException.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/ResourceNotFoundException.java similarity index 96% rename from spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/ResourceNotFoundException.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/ResourceNotFoundException.java index 469d5af96f..6d6e6ef712 100644 --- a/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/ResourceNotFoundException.java +++ b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/exceptiontesting/exception/ResourceNotFoundException.java @@ -1,13 +1,13 @@ -package com.baeldung.exceptiontesting.exception; - -import org.springframework.http.HttpStatus; -import org.springframework.web.bind.annotation.ResponseStatus; - -@SuppressWarnings("serial") -@ResponseStatus(HttpStatus.NOT_FOUND) -public class ResourceNotFoundException extends RuntimeException { - - public ResourceNotFoundException(String message) { - super(message); - } -} +package com.baeldung.exceptiontesting.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.ResponseStatus; + +@SuppressWarnings("serial") +@ResponseStatus(HttpStatus.NOT_FOUND) +public class ResourceNotFoundException extends RuntimeException { + + public ResourceNotFoundException(String message) { + super(message); + } +} diff --git a/spring-rest-testing/src/main/java/com/baeldung/persistence/IOperations.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/persistence/IOperations.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/persistence/IOperations.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/persistence/IOperations.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/persistence/dao/IFooDao.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/persistence/dao/IFooDao.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/persistence/dao/IFooDao.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/persistence/dao/IFooDao.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/persistence/model/Foo.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/persistence/model/Foo.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/persistence/model/Foo.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/persistence/model/Foo.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/persistence/model/User.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/persistence/model/User.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/persistence/model/User.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/persistence/model/User.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/persistence/service/IFooService.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/persistence/service/IFooService.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/persistence/service/IFooService.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/persistence/service/IFooService.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/persistence/service/common/AbstractService.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/persistence/service/common/AbstractService.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/persistence/service/common/AbstractService.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/persistence/service/common/AbstractService.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/persistence/service/impl/FooService.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/persistence/service/impl/FooService.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/persistence/service/impl/FooService.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/persistence/service/impl/FooService.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/spring/Application.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/spring/Application.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/spring/Application.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/spring/Application.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/spring/PersistenceConfig.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/spring/PersistenceConfig.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/spring/PersistenceConfig.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/spring/PersistenceConfig.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/spring/WebConfig.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/spring/WebConfig.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/spring/WebConfig.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/spring/WebConfig.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/web/controller/FooController.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/controller/FooController.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/web/controller/FooController.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/controller/FooController.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/web/controller/HomeController.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/controller/HomeController.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/web/controller/HomeController.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/controller/HomeController.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/web/controller/RootController.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/controller/RootController.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/web/controller/RootController.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/controller/RootController.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/exception/MyResourceNotFoundException.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/web/metric/ActuatorMetricService.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/ActuatorMetricService.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/web/metric/ActuatorMetricService.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/ActuatorMetricService.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/web/metric/CustomActuatorMetricService.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/CustomActuatorMetricService.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/web/metric/CustomActuatorMetricService.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/CustomActuatorMetricService.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/web/metric/IActuatorMetricService.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/IActuatorMetricService.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/web/metric/IActuatorMetricService.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/IActuatorMetricService.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/web/metric/ICustomActuatorMetricService.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/ICustomActuatorMetricService.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/web/metric/ICustomActuatorMetricService.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/ICustomActuatorMetricService.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/web/metric/IMetricService.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/IMetricService.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/web/metric/IMetricService.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/IMetricService.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/web/metric/MetricFilter.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/MetricFilter.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/web/metric/MetricFilter.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/MetricFilter.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/web/metric/MetricService.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/MetricService.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/web/metric/MetricService.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/metric/MetricService.java diff --git a/spring-rest-testing/src/main/java/com/baeldung/web/util/RestPreconditions.java b/spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/util/RestPreconditions.java similarity index 100% rename from spring-rest-testing/src/main/java/com/baeldung/web/util/RestPreconditions.java rename to spring-web-modules/spring-rest-testing/src/main/java/com/baeldung/web/util/RestPreconditions.java diff --git a/spring-rest-testing/src/main/resources/application.properties b/spring-web-modules/spring-rest-testing/src/main/resources/application.properties similarity index 100% rename from spring-rest-testing/src/main/resources/application.properties rename to spring-web-modules/spring-rest-testing/src/main/resources/application.properties diff --git a/spring-rest-testing/src/main/resources/logback.xml b/spring-web-modules/spring-rest-testing/src/main/resources/logback.xml similarity index 100% rename from spring-rest-testing/src/main/resources/logback.xml rename to spring-web-modules/spring-rest-testing/src/main/resources/logback.xml diff --git a/spring-rest-testing/src/main/resources/persistence-h2.properties b/spring-web-modules/spring-rest-testing/src/main/resources/persistence-h2.properties similarity index 100% rename from spring-rest-testing/src/main/resources/persistence-h2.properties rename to spring-web-modules/spring-rest-testing/src/main/resources/persistence-h2.properties diff --git a/spring-rest-testing/src/main/resources/persistence-mysql.properties b/spring-web-modules/spring-rest-testing/src/main/resources/persistence-mysql.properties similarity index 100% rename from spring-rest-testing/src/main/resources/persistence-mysql.properties rename to spring-web-modules/spring-rest-testing/src/main/resources/persistence-mysql.properties diff --git a/spring-rest-testing/src/main/resources/springDataPersistenceConfig.xml b/spring-web-modules/spring-rest-testing/src/main/resources/springDataPersistenceConfig.xml similarity index 100% rename from spring-rest-testing/src/main/resources/springDataPersistenceConfig.xml rename to spring-web-modules/spring-rest-testing/src/main/resources/springDataPersistenceConfig.xml diff --git a/spring-rest-testing/src/main/webapp/WEB-INF/api-servlet.xml b/spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/api-servlet.xml similarity index 100% rename from spring-rest-testing/src/main/webapp/WEB-INF/api-servlet.xml rename to spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/api-servlet.xml diff --git a/spring-rest-testing/src/main/webapp/WEB-INF/view/graph.jsp b/spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/view/graph.jsp similarity index 100% rename from spring-rest-testing/src/main/webapp/WEB-INF/view/graph.jsp rename to spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/view/graph.jsp diff --git a/spring-rest-testing/src/main/webapp/WEB-INF/view/homepage.jsp b/spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/view/homepage.jsp similarity index 100% rename from spring-rest-testing/src/main/webapp/WEB-INF/view/homepage.jsp rename to spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/view/homepage.jsp diff --git a/spring-rest-testing/src/main/webapp/WEB-INF/web.xml b/spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/web.xml similarity index 100% rename from spring-rest-testing/src/main/webapp/WEB-INF/web.xml rename to spring-web-modules/spring-rest-testing/src/main/webapp/WEB-INF/web.xml diff --git a/spring-rest-testing/src/test/java/com/baeldung/Consts.java b/spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/Consts.java similarity index 100% rename from spring-rest-testing/src/test/java/com/baeldung/Consts.java rename to spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/Consts.java diff --git a/spring-rest-testing/src/test/java/com/baeldung/SpringContextIntegrationTest.java b/spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/SpringContextIntegrationTest.java similarity index 100% rename from spring-rest-testing/src/test/java/com/baeldung/SpringContextIntegrationTest.java rename to spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/SpringContextIntegrationTest.java diff --git a/spring-rest-testing/src/test/java/com/baeldung/SpringContextTest.java b/spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/SpringContextTest.java similarity index 100% rename from spring-rest-testing/src/test/java/com/baeldung/SpringContextTest.java rename to spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/SpringContextTest.java diff --git a/spring-rest-testing/src/test/java/com/baeldung/exceptiontesting/controller/ExceptionControllerUnitTest.java b/spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/exceptiontesting/controller/ExceptionControllerUnitTest.java similarity index 97% rename from spring-rest-testing/src/test/java/com/baeldung/exceptiontesting/controller/ExceptionControllerUnitTest.java rename to spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/exceptiontesting/controller/ExceptionControllerUnitTest.java index d624efcdd0..8e1eaad977 100644 --- a/spring-rest-testing/src/test/java/com/baeldung/exceptiontesting/controller/ExceptionControllerUnitTest.java +++ b/spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/exceptiontesting/controller/ExceptionControllerUnitTest.java @@ -1,65 +1,65 @@ -package com.baeldung.exceptiontesting.controller; -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.http.MediaType; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; - -import com.baeldung.exceptiontesting.controller.ExceptionController; -import com.baeldung.exceptiontesting.exception.BadArgumentsException; -import com.baeldung.exceptiontesting.exception.InternalException; -import com.baeldung.exceptiontesting.exception.ResourceNotFoundException; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; - -@RunWith(SpringRunner.class) -@WebMvcTest(ExceptionController.class) -public class ExceptionControllerUnitTest{ - - @Autowired - private MockMvc mvc; - - @Test - public void givenNotFound_whenGetSpecificException_thenNotFoundCode() throws Exception { - String exceptionParam = "not_found"; - - mvc.perform(get("/exception/{exception_id}", exceptionParam) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isNotFound()) - .andExpect(result -> assertTrue(result.getResolvedException() instanceof ResourceNotFoundException)) - .andExpect(result -> assertEquals("resource not found", result.getResolvedException().getMessage())); - } - - @Test - public void givenBadArguments_whenGetSpecificException_thenBadRequest() throws Exception { - String exceptionParam = "bad_arguments"; - - mvc.perform(get("/exception/{exception_id}", exceptionParam) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isBadRequest()) - .andExpect(result -> assertTrue(result.getResolvedException() instanceof BadArgumentsException)) - .andExpect(result -> assertEquals("bad arguments", result.getResolvedException().getMessage())); - } - - @Test - public void givenOther_whenGetSpecificException_thenInternalServerError() throws Exception { - String exceptionParam = "dummy"; - - mvc.perform(get("/exception/{exception_id}", exceptionParam) - .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().isInternalServerError()) - .andExpect(result -> assertTrue(result.getResolvedException() instanceof InternalException)) - .andExpect(result -> assertEquals("internal error", result.getResolvedException().getMessage())); - } - - @Test(expected = Exception.class) - public void whenGetException_thenInternalServerError() throws Exception { - mvc.perform(get("/exception/throw") - .contentType(MediaType.APPLICATION_JSON)); - } -} +package com.baeldung.exceptiontesting.controller; +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.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +import com.baeldung.exceptiontesting.controller.ExceptionController; +import com.baeldung.exceptiontesting.exception.BadArgumentsException; +import com.baeldung.exceptiontesting.exception.InternalException; +import com.baeldung.exceptiontesting.exception.ResourceNotFoundException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@RunWith(SpringRunner.class) +@WebMvcTest(ExceptionController.class) +public class ExceptionControllerUnitTest{ + + @Autowired + private MockMvc mvc; + + @Test + public void givenNotFound_whenGetSpecificException_thenNotFoundCode() throws Exception { + String exceptionParam = "not_found"; + + mvc.perform(get("/exception/{exception_id}", exceptionParam) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNotFound()) + .andExpect(result -> assertTrue(result.getResolvedException() instanceof ResourceNotFoundException)) + .andExpect(result -> assertEquals("resource not found", result.getResolvedException().getMessage())); + } + + @Test + public void givenBadArguments_whenGetSpecificException_thenBadRequest() throws Exception { + String exceptionParam = "bad_arguments"; + + mvc.perform(get("/exception/{exception_id}", exceptionParam) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()) + .andExpect(result -> assertTrue(result.getResolvedException() instanceof BadArgumentsException)) + .andExpect(result -> assertEquals("bad arguments", result.getResolvedException().getMessage())); + } + + @Test + public void givenOther_whenGetSpecificException_thenInternalServerError() throws Exception { + String exceptionParam = "dummy"; + + mvc.perform(get("/exception/{exception_id}", exceptionParam) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isInternalServerError()) + .andExpect(result -> assertTrue(result.getResolvedException() instanceof InternalException)) + .andExpect(result -> assertEquals("internal error", result.getResolvedException().getMessage())); + } + + @Test(expected = Exception.class) + public void whenGetException_thenInternalServerError() throws Exception { + mvc.perform(get("/exception/throw") + .contentType(MediaType.APPLICATION_JSON)); + } +} diff --git a/spring-rest-testing/src/test/java/com/baeldung/persistence/PersistenceTestSuite.java b/spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/persistence/PersistenceTestSuite.java similarity index 100% rename from spring-rest-testing/src/test/java/com/baeldung/persistence/PersistenceTestSuite.java rename to spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/persistence/PersistenceTestSuite.java diff --git a/spring-rest-testing/src/test/java/com/baeldung/persistence/service/AbstractServicePersistenceIntegrationTest.java b/spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/persistence/service/AbstractServicePersistenceIntegrationTest.java similarity index 100% rename from spring-rest-testing/src/test/java/com/baeldung/persistence/service/AbstractServicePersistenceIntegrationTest.java rename to spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/persistence/service/AbstractServicePersistenceIntegrationTest.java diff --git a/spring-rest-testing/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java b/spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java similarity index 100% rename from spring-rest-testing/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java rename to spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/persistence/service/FooServicePersistenceIntegrationTest.java diff --git a/spring-rest-testing/src/test/java/com/baeldung/util/IDUtil.java b/spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/util/IDUtil.java similarity index 100% rename from spring-rest-testing/src/test/java/com/baeldung/util/IDUtil.java rename to spring-web-modules/spring-rest-testing/src/test/java/com/baeldung/util/IDUtil.java diff --git a/spring-rest-testing/.gitignore b/spring-web-modules/spring-rest-testing/src/test/resources/.gitignore similarity index 100% rename from spring-rest-testing/.gitignore rename to spring-web-modules/spring-rest-testing/src/test/resources/.gitignore diff --git a/spring-web-modules/spring-rest-testing/src/testFile b/spring-web-modules/spring-rest-testing/src/testFile new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/spring-web-modules/spring-rest-testing/src/testFile @@ -0,0 +1 @@ + diff --git a/spring-resttemplate-2/README.md b/spring-web-modules/spring-resttemplate-2/README.md similarity index 55% rename from spring-resttemplate-2/README.md rename to spring-web-modules/spring-resttemplate-2/README.md index e1e0ba40b0..ace7ae817b 100644 --- a/spring-resttemplate-2/README.md +++ b/spring-web-modules/spring-resttemplate-2/README.md @@ -8,3 +8,6 @@ This module contains articles about Spring RestTemplate - [Proxies With RestTemplate](https://www.baeldung.com/java-resttemplate-proxy) - [A Custom Media Type for a Spring REST API](https://www.baeldung.com/spring-rest-custom-media-type) - [RestTemplate Post Request with JSON](https://www.baeldung.com/spring-resttemplate-post-json) +- [How to Compress Requests Using the Spring RestTemplate](https://www.baeldung.com/spring-resttemplate-compressing-requests) +- [Get list of JSON objects with Spring RestTemplate](https://www.baeldung.com/spring-resttemplate-json-list) +- [Spring RestTemplate Exception: “Not enough variables available to expand”](https://www.baeldung.com/spring-not-enough-variables-available) diff --git a/spring-resttemplate-2/pom.xml b/spring-web-modules/spring-resttemplate-2/pom.xml similarity index 66% rename from spring-resttemplate-2/pom.xml rename to spring-web-modules/spring-resttemplate-2/pom.xml index b1d6f60c53..158380b403 100644 --- a/spring-resttemplate-2/pom.xml +++ b/spring-web-modules/spring-resttemplate-2/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2/pom.xml @@ -20,7 +20,30 @@ org.springframework.boot spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + + + + org.springframework.boot + spring-boot-starter-jetty + + + + org.apache.httpcomponents + httpclient + + + + commons-io + commons-io + ${commons-io.version} + + org.springframework.boot spring-boot-starter-test @@ -48,16 +71,16 @@ ch.qos.logback logback-classic - + - + - - org.springframework.boot - spring-boot-maven-plugin - + + org.springframework.boot + spring-boot-maven-plugin + - + \ No newline at end of file diff --git a/spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/CompressingClientHttpRequestInterceptor.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/CompressingClientHttpRequestInterceptor.java similarity index 96% rename from spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/CompressingClientHttpRequestInterceptor.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/CompressingClientHttpRequestInterceptor.java index 78b77256af..e880e8f915 100644 --- a/spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/CompressingClientHttpRequestInterceptor.java +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/CompressingClientHttpRequestInterceptor.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.rest.compress; +package com.baeldung.compress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/GzipUtils.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/GzipUtils.java similarity index 83% rename from spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/GzipUtils.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/GzipUtils.java index b9731535b2..50c565d92c 100644 --- a/spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/GzipUtils.java +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/GzipUtils.java @@ -1,14 +1,14 @@ -package com.baeldung.spring.rest.compress; - -import org.apache.commons.codec.Charsets; -import org.apache.commons.io.IOUtils; +package com.baeldung.compress; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; +import org.apache.commons.io.IOUtils; + public class GzipUtils { /** @@ -19,7 +19,7 @@ public class GzipUtils { * @throws Exception */ public static byte[] compress(String text) throws Exception { - return GzipUtils.compress(text.getBytes(Charsets.UTF_8)); + return GzipUtils.compress(text.getBytes(StandardCharsets.UTF_8)); } /** @@ -46,7 +46,7 @@ public class GzipUtils { */ public static String decompress(byte[] body) throws IOException { try (GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(body))) { - return IOUtils.toString(gzipInputStream, Charsets.UTF_8); + return IOUtils.toString(gzipInputStream, StandardCharsets.UTF_8); } } } diff --git a/spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/JettyWebServerConfiguration.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/JettyWebServerConfiguration.java similarity index 96% rename from spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/JettyWebServerConfiguration.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/JettyWebServerConfiguration.java index 8de8e5b523..3ac8c31ab3 100644 --- a/spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/JettyWebServerConfiguration.java +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/JettyWebServerConfiguration.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.rest.compress; +package com.baeldung.compress; import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.gzip.GzipHandler; diff --git a/spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/Message.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/Message.java similarity index 92% rename from spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/Message.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/Message.java index 24272a4fca..f43d06c2fc 100644 --- a/spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/Message.java +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/Message.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.rest.compress; +package com.baeldung.compress; public class Message { diff --git a/spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/MessageController.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/MessageController.java similarity index 96% rename from spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/MessageController.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/MessageController.java index 2fc2ca8272..ec574d9dec 100644 --- a/spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/MessageController.java +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/MessageController.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.rest.compress; +package com.baeldung.compress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/RestTemplateConfiguration.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/RestTemplateConfiguration.java similarity index 92% rename from spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/RestTemplateConfiguration.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/RestTemplateConfiguration.java index c1e3c89ae9..12b1e4249e 100644 --- a/spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/RestTemplateConfiguration.java +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/RestTemplateConfiguration.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.rest.compress; +package com.baeldung.compress; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/SpringCompressRequestApplication.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/SpringCompressRequestApplication.java similarity index 90% rename from spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/SpringCompressRequestApplication.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/SpringCompressRequestApplication.java index 9b1b71979d..9ff88ab257 100644 --- a/spring-rest-compress/src/main/java/com/baeldung/spring/rest/compress/SpringCompressRequestApplication.java +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/compress/SpringCompressRequestApplication.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.rest.compress; +package com.baeldung.compress; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; diff --git a/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/RestTemplateConfigurationApplication.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/RestTemplateConfigurationApplication.java similarity index 83% rename from spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/RestTemplateConfigurationApplication.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/RestTemplateConfigurationApplication.java index 8df3c13d7b..a7e65fc96c 100644 --- a/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/RestTemplateConfigurationApplication.java +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/RestTemplateConfigurationApplication.java @@ -1,7 +1,6 @@ package com.baeldung.resttemplate; import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication diff --git a/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/json/consumer/service/UserConsumerService.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/json/consumer/service/UserConsumerService.java new file mode 100644 index 0000000000..751e234e8b --- /dev/null +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/json/consumer/service/UserConsumerService.java @@ -0,0 +1,16 @@ +package com.baeldung.resttemplate.json.consumer.service; + +import java.util.List; + +public interface UserConsumerService { + + List processUserDataFromObjectArray(); + + List processUserDataFromUserArray(); + + List processUserDataFromUserList(); + + List processNestedUserDataFromUserArray(); + + List processNestedUserDataFromUserList(); +} diff --git a/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/json/consumer/service/UserConsumerServiceImpl.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/json/consumer/service/UserConsumerServiceImpl.java new file mode 100644 index 0000000000..dc1566d971 --- /dev/null +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/json/consumer/service/UserConsumerServiceImpl.java @@ -0,0 +1,90 @@ +package com.baeldung.resttemplate.json.consumer.service; + +import com.baeldung.resttemplate.json.model.Address; +import com.baeldung.resttemplate.json.model.User; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class UserConsumerServiceImpl implements UserConsumerService { + + private static final String BASE_URL = "http://localhost:8080/users"; + private final RestTemplate restTemplate; + private static final ObjectMapper mapper = new ObjectMapper(); + + public UserConsumerServiceImpl(RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + @Override + public List processUserDataFromObjectArray() { + ResponseEntity responseEntity = restTemplate.getForEntity(BASE_URL, Object[].class); + Object[] objects = responseEntity.getBody(); + return Arrays.stream(objects) + .map(object -> mapper.convertValue(object, User.class)) + .map(User::getName) + .collect(Collectors.toList()); + } + + @Override + public List processUserDataFromUserArray() { + ResponseEntity responseEntity = restTemplate.getForEntity(BASE_URL, User[].class); + User[] userArray = responseEntity.getBody(); + return Arrays.stream(userArray) + .map(User::getName) + .collect(Collectors.toList()); + } + + @Override + public List processUserDataFromUserList() { + ResponseEntity> responseEntity = + restTemplate.exchange( + BASE_URL, + HttpMethod.GET, + null, + new ParameterizedTypeReference>() {} + ); + List users = responseEntity.getBody(); + return users.stream() + .map(User::getName) + .collect(Collectors.toList()); + } + + @Override + public List processNestedUserDataFromUserArray() { + ResponseEntity responseEntity = restTemplate.getForEntity(BASE_URL, User[].class); + User[] userArray = responseEntity.getBody(); + //we can get more info if we need : + MediaType contentType = responseEntity.getHeaders().getContentType(); + HttpStatus statusCode = responseEntity.getStatusCode(); + + return Arrays.stream(userArray) + .flatMap(user -> user.getAddressList().stream()) + .map(Address::getPostCode) + .collect(Collectors.toList()); + } + + @Override + public List processNestedUserDataFromUserList() { + ResponseEntity> responseEntity = + restTemplate.exchange( + BASE_URL, + HttpMethod.GET, + null, + new ParameterizedTypeReference>() {} + ); + List userList = responseEntity.getBody(); + return userList.stream() + .flatMap(user -> user.getAddressList().stream()) + .map(Address::getPostCode) + .collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/json/model/Address.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/json/model/Address.java new file mode 100644 index 0000000000..f41ff4d8ea --- /dev/null +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/json/model/Address.java @@ -0,0 +1,29 @@ +package com.baeldung.resttemplate.json.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class Address { + private final String addressLine1; + private final String addressLine2; + private final String town; + private final String postCode; + + @JsonCreator + public Address( + @JsonProperty("addressLine1") String addressLine1, + @JsonProperty("addressLine2") String addressLine2, + @JsonProperty("town") String town, + @JsonProperty("postCode") String postCode) { + this.addressLine1 = addressLine1; + this.addressLine2 = addressLine2; + this.town = town; + this.postCode = postCode; + } + public String getPostCode() { + return postCode; + } +} diff --git a/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/json/model/User.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/json/model/User.java new file mode 100644 index 0000000000..8e02ef7787 --- /dev/null +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/json/model/User.java @@ -0,0 +1,30 @@ +package com.baeldung.resttemplate.json.model; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class User { + private final int id; + private final String name; + private final List
addressList; + + @JsonCreator + public User( + @JsonProperty("id") int id, + @JsonProperty("name") String name, + @JsonProperty("addressList") List
addressList) { + this.id = id; + this.name = name; + this.addressList = addressList; + } + + public String getName() { + return name; + } + + public List
getAddressList() { return addressList; } +} diff --git a/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/logging/web/controller/PersonController.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/logging/web/controller/PersonController.java similarity index 100% rename from spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/logging/web/controller/PersonController.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/logging/web/controller/PersonController.java diff --git a/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/controller/PersonAPI.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/controller/PersonAPI.java similarity index 100% rename from spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/controller/PersonAPI.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/controller/PersonAPI.java diff --git a/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/dto/Person.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/dto/Person.java similarity index 100% rename from spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/dto/Person.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/dto/Person.java diff --git a/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/service/PersonService.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/service/PersonService.java similarity index 100% rename from spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/service/PersonService.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/service/PersonService.java diff --git a/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/service/PersonServiceImpl.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/service/PersonServiceImpl.java similarity index 100% rename from spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/service/PersonServiceImpl.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplate/web/service/PersonServiceImpl.java diff --git a/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplateexception/RestTemplateExceptionApplication.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplateexception/RestTemplateExceptionApplication.java new file mode 100644 index 0000000000..84a337f5ee --- /dev/null +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplateexception/RestTemplateExceptionApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.resttemplateexception; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class RestTemplateExceptionApplication { + + public static void main(String[] args) { + SpringApplication.run(RestTemplateExceptionApplication.class, args); + } + +} diff --git a/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplateexception/controller/ProductApi.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplateexception/controller/ProductApi.java new file mode 100644 index 0000000000..2c530cae2b --- /dev/null +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplateexception/controller/ProductApi.java @@ -0,0 +1,46 @@ +package com.baeldung.resttemplateexception.controller; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.baeldung.resttemplateexception.model.Criterion; +import com.baeldung.resttemplateexception.model.Product; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +@RestController +@RequestMapping("/api") +public class ProductApi { + + private List productList = new ArrayList<>(Arrays.asList(new Product(1, "Acer Aspire 5", 437), new Product(2, "ASUS VivoBook", 650), new Product(3, "Lenovo Legion", 990))); + + @GetMapping("/get") + public Product get(@RequestParam String criterion) throws JsonMappingException, JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + Criterion crt = objectMapper.readValue(criterion, Criterion.class); + if (crt.getProp().equals("name")) + return findByName(crt.getValue()); + + // Search by other properties (id,price) + + return null; + } + + private Product findByName(String name) { + for (Product product : this.productList) { + if (product.getName().equals(name)) { + return product; + } + } + return null; + } + + // Other methods +} diff --git a/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplateexception/model/Criterion.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplateexception/model/Criterion.java new file mode 100644 index 0000000000..9a96ad4dc3 --- /dev/null +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplateexception/model/Criterion.java @@ -0,0 +1,28 @@ +package com.baeldung.resttemplateexception.model; + +public class Criterion { + + private String prop; + private String value; + + public Criterion() { + + } + + public String getProp() { + return prop; + } + + public void setProp(String prop) { + this.prop = prop; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + +} diff --git a/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplateexception/model/Product.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplateexception/model/Product.java new file mode 100644 index 0000000000..e4cc29279c --- /dev/null +++ b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/resttemplateexception/model/Product.java @@ -0,0 +1,43 @@ +package com.baeldung.resttemplateexception.model; + +public class Product { + + private int id; + private String name; + private double price; + + public Product() { + + } + + public Product(int id, String name, double price) { + this.id = id; + this.name = name; + this.price = price; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + +} diff --git a/spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/config/WebConfig.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/config/WebConfig.java similarity index 100% rename from spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/config/WebConfig.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/config/WebConfig.java diff --git a/spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/web/controller/mediatypes/CustomMediaTypeController.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/web/controller/mediatypes/CustomMediaTypeController.java similarity index 100% rename from spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/web/controller/mediatypes/CustomMediaTypeController.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/web/controller/mediatypes/CustomMediaTypeController.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/redirect/RedirectController.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/web/controller/redirect/RedirectController.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/redirect/RedirectController.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/web/controller/redirect/RedirectController.java diff --git a/spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItem.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItem.java similarity index 100% rename from spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItem.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItem.java diff --git a/spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItemV2.java b/spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItemV2.java similarity index 100% rename from spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItemV2.java rename to spring-web-modules/spring-resttemplate-2/src/main/java/com/baeldung/sampleapp/web/dto/BaeldungItemV2.java diff --git a/spring-resttemplate-2/src/main/resources/application.properties b/spring-web-modules/spring-resttemplate-2/src/main/resources/application.properties similarity index 100% rename from spring-resttemplate-2/src/main/resources/application.properties rename to spring-web-modules/spring-resttemplate-2/src/main/resources/application.properties diff --git a/spring-web-modules/spring-resttemplate-2/src/main/webapp/WEB-INF/api-servlet.xml b/spring-web-modules/spring-resttemplate-2/src/main/webapp/WEB-INF/api-servlet.xml new file mode 100644 index 0000000000..ed37a962e9 --- /dev/null +++ b/spring-web-modules/spring-resttemplate-2/src/main/webapp/WEB-INF/api-servlet.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + /WEB-INF/spring-views.xml + + + + + + + + + + + + + diff --git a/spring-web-modules/spring-resttemplate-2/src/main/webapp/WEB-INF/spring-views.xml b/spring-web-modules/spring-resttemplate-2/src/main/webapp/WEB-INF/spring-views.xml new file mode 100644 index 0000000000..2944828d6d --- /dev/null +++ b/spring-web-modules/spring-resttemplate-2/src/main/webapp/WEB-INF/spring-views.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/spring-rest-compress/src/test/java/com/baeldung/spring/rest/compress/GzipUtilsUnitTest.java b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/compress/GzipUtilsUnitTest.java similarity index 92% rename from spring-rest-compress/src/test/java/com/baeldung/spring/rest/compress/GzipUtilsUnitTest.java rename to spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/compress/GzipUtilsUnitTest.java index 431758d358..10c2eeb748 100644 --- a/spring-rest-compress/src/test/java/com/baeldung/spring/rest/compress/GzipUtilsUnitTest.java +++ b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/compress/GzipUtilsUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.rest.compress; +package com.baeldung.compress; import org.junit.Test; diff --git a/spring-rest-compress/src/test/java/com/baeldung/spring/rest/compress/MessageControllerUnitTest.java b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/compress/MessageControllerUnitTest.java similarity index 97% rename from spring-rest-compress/src/test/java/com/baeldung/spring/rest/compress/MessageControllerUnitTest.java rename to spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/compress/MessageControllerUnitTest.java index 50b2b7ccd7..643e3f6881 100644 --- a/spring-rest-compress/src/test/java/com/baeldung/spring/rest/compress/MessageControllerUnitTest.java +++ b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/compress/MessageControllerUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.spring.rest.compress; +package com.baeldung.compress; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/json/consumer/service/UserConsumerServiceImplUnitTest.java b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/json/consumer/service/UserConsumerServiceImplUnitTest.java new file mode 100644 index 0000000000..4cc58e30f5 --- /dev/null +++ b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/json/consumer/service/UserConsumerServiceImplUnitTest.java @@ -0,0 +1,127 @@ +package com.baeldung.resttemplate.json.consumer.service; + +import org.junit.Before; +import org.junit.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.test.web.client.ExpectedCount; +import org.springframework.test.web.client.MockRestServiceServer; +import org.springframework.web.client.RestTemplate; + +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; + +@SpringBootTest +public class UserConsumerServiceImplUnitTest { + + private static String USER_JSON = "[{\"id\":1,\"name\":\"user1\",\"addressList\":[{\"addressLine1\":\"address1_addressLine1\",\"addressLine2\":\"address1_addressLine2\",\"town\":\"address1_town\",\"postCode\":\"user1_address1_postCode\"}," + + "{\"addressLine1\":\"address2_addressLine1\",\"addressLine2\":\"address2_addressLine2\",\"town\":\"address2_town\",\"postCode\":\"user1_address2_postCode\"}]}," + + "{\"id\":2,\"name\":\"user2\",\"addressList\":[{\"addressLine1\":\"address1_addressLine1\",\"addressLine2\":\"address1_addressLine2\",\"town\":\"address1_town\",\"postCode\":\"user2_address1_postCode\"}]}]"; + + private MockRestServiceServer mockServer; + private final RestTemplate restTemplate = new RestTemplate(); + private final UserConsumerService tested = new UserConsumerServiceImpl(restTemplate); + + @Before + public void init() { + mockServer = MockRestServiceServer.createServer(restTemplate); + } + + @Test + public void whenProcessUserDataAsObjects_thenOK() { + String url = "http://localhost:8080/users"; + List expected = Arrays.asList("user1", "user2"); + + mockServer.expect(ExpectedCount.once(), + requestTo(url)) + .andExpect(method(HttpMethod.GET)) + .andRespond(withStatus(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(USER_JSON)); + + List actual = tested.processUserDataFromObjectArray(); + + mockServer.verify(); + assertThat(actual).containsExactly(expected.get(0), expected.get(1)); + } + + @Test + public void whenProcessUserDataAsArray_thenOK() { + String url = "http://localhost:8080/users"; + List expected = Arrays.asList("user1", "user2"); + + mockServer.expect(ExpectedCount.once(), + requestTo(url)) + .andExpect(method(HttpMethod.GET)) + .andRespond(withStatus(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(USER_JSON)); + + List actual = tested.processUserDataFromUserArray(); + + mockServer.verify(); + assertThat(actual).containsExactly(expected.get(0), expected.get(1)); + } + + @Test + public void whenProcessUserDataAsList_thenOK() { + String url = "http://localhost:8080/users"; + List expected = Arrays.asList("user1", "user2"); + + mockServer.expect(ExpectedCount.once(), + requestTo(url)) + .andExpect(method(HttpMethod.GET)) + .andRespond(withStatus(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(USER_JSON)); + + List actual = tested.processUserDataFromUserList(); + + mockServer.verify(); + assertThat(actual).containsExactly(expected.get(0), expected.get(1)); + } + + + @Test + public void whenProcessNestedUserDataFromArray_thenOK() { + String url = "http://localhost:8080/users"; + List expected = Arrays.asList("user1_address1_postCode", "user1_address2_postCode", "user2_address1_postCode"); + + mockServer.expect(ExpectedCount.once(), + requestTo(url)) + .andExpect(method(HttpMethod.GET)) + .andRespond(withStatus(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(USER_JSON)); + + List actual = tested.processNestedUserDataFromUserArray(); + + mockServer.verify(); + assertThat(actual).containsExactly(expected.get(0), expected.get(1), expected.get(2)); + } + + @Test + public void whenProcessNestedUserDataFromList_thenOK() { + String url = "http://localhost:8080/users"; + List expected = Arrays.asList("user1_address1_postCode", "user1_address2_postCode", "user2_address1_postCode"); + + mockServer.expect(ExpectedCount.once(), + requestTo(url)) + .andExpect(method(HttpMethod.GET)) + .andRespond(withStatus(HttpStatus.OK) + .contentType(MediaType.APPLICATION_JSON) + .body(USER_JSON)); + + List actual = tested.processNestedUserDataFromUserList(); + + mockServer.verify(); + assertThat(actual).containsExactly(expected.get(0), expected.get(1), expected.get(2)); + } +} \ No newline at end of file diff --git a/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/LoggingInterceptor.java b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/LoggingInterceptor.java similarity index 62% rename from spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/LoggingInterceptor.java rename to spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/LoggingInterceptor.java index 17ce390d8a..c699d9d9dc 100644 --- a/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/LoggingInterceptor.java +++ b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/LoggingInterceptor.java @@ -14,16 +14,18 @@ import org.springframework.http.client.ClientHttpResponse; public class LoggingInterceptor implements ClientHttpRequestInterceptor { - final static Logger log = LoggerFactory.getLogger(LoggingInterceptor.class); + final static Logger LOGGER = LoggerFactory.getLogger(LoggingInterceptor.class); @Override public ClientHttpResponse intercept(HttpRequest req, byte[] reqBody, ClientHttpRequestExecution ex) throws IOException { - log.debug("Request body: {}", new String(reqBody, StandardCharsets.UTF_8)); + LOGGER.debug("Request body: {}", new String(reqBody, StandardCharsets.UTF_8)); ClientHttpResponse response = ex.execute(req, reqBody); - InputStreamReader isr = new InputStreamReader(response.getBody(), StandardCharsets.UTF_8); - String body = new BufferedReader(isr).lines() - .collect(Collectors.joining("\n")); - log.debug("Response body: {}", body); + if (LOGGER.isDebugEnabled()) { + InputStreamReader isr = new InputStreamReader(response.getBody(), StandardCharsets.UTF_8); + String body = new BufferedReader(isr).lines() + .collect(Collectors.joining("\n")); + LOGGER.debug("Response body: {}", body); + } return response; } } diff --git a/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/RestTemplateLoggingLiveTest.java b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/RestTemplateLoggingLiveTest.java similarity index 62% rename from spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/RestTemplateLoggingLiveTest.java rename to spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/RestTemplateLoggingLiveTest.java index 99d0201eff..86ffa574a0 100644 --- a/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/RestTemplateLoggingLiveTest.java +++ b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/logging/RestTemplateLoggingLiveTest.java @@ -1,18 +1,21 @@ package com.baeldung.resttemplate.logging; -import static org.hamcrest.CoreMatchers.equalTo; - -import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertEquals; import java.util.ArrayList; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.http.client.BufferingClientHttpRequestFactory; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.CollectionUtils; import org.springframework.web.client.RestTemplate; @@ -22,6 +25,7 @@ import org.springframework.web.client.RestTemplate; public class RestTemplateLoggingLiveTest { private static final String baseUrl = "http://localhost:8080/spring-rest"; + private static final Logger LOGGER = LoggerFactory.getLogger(RestTemplateLoggingLiveTest.class); @Test public void givenHttpClientConfiguration_whenSendGetForRequestEntity_thenRequestResponseFullLog() { @@ -30,13 +34,22 @@ public class RestTemplateLoggingLiveTest { restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); final ResponseEntity response = restTemplate.postForEntity(baseUrl + "/persons", "my request body", String.class); - assertThat(response.getStatusCode(), equalTo(HttpStatus.OK)); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertEquals("[\"Lucie\",\"Jackie\",\"Danesh\",\"Tao\"]", response.getBody()); } @Test public void givenLoggingInterceptorConfiguration_whenSendGetForRequestEntity_thenRequestResponseCustomLog() { - RestTemplate restTemplate = new RestTemplate(); + RestTemplate restTemplate = null; + if (LOGGER.isDebugEnabled()) { + ClientHttpRequestFactory factory = new BufferingClientHttpRequestFactory( + new SimpleClientHttpRequestFactory()); + restTemplate = new RestTemplate(factory); + } else { + restTemplate = new RestTemplate(); + } + List interceptors = restTemplate.getInterceptors(); if (CollectionUtils.isEmpty(interceptors)) { interceptors = new ArrayList<>(); @@ -45,6 +58,7 @@ public class RestTemplateLoggingLiveTest { restTemplate.setInterceptors(interceptors); final ResponseEntity response = restTemplate.postForEntity(baseUrl + "/persons", "my request body", String.class); - assertThat(response.getStatusCode(), equalTo(HttpStatus.OK)); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertEquals("[\"Lucie\",\"Jackie\",\"Danesh\",\"Tao\"]", response.getBody()); } } diff --git a/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/postjson/PersonAPILiveTest.java b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/postjson/PersonAPILiveTest.java similarity index 100% rename from spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/postjson/PersonAPILiveTest.java rename to spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/postjson/PersonAPILiveTest.java diff --git a/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/proxy/RequestFactoryLiveTest.java b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/proxy/RequestFactoryLiveTest.java similarity index 100% rename from spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/proxy/RequestFactoryLiveTest.java rename to spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/proxy/RequestFactoryLiveTest.java diff --git a/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/proxy/RestTemplateCustomizerLiveTest.java b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/proxy/RestTemplateCustomizerLiveTest.java similarity index 100% rename from spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/proxy/RestTemplateCustomizerLiveTest.java rename to spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplate/proxy/RestTemplateCustomizerLiveTest.java diff --git a/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplateexception/RestTemplateExceptionLiveTest.java b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplateexception/RestTemplateExceptionLiveTest.java new file mode 100644 index 0000000000..adfb8ffa4e --- /dev/null +++ b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/resttemplateexception/RestTemplateExceptionLiveTest.java @@ -0,0 +1,47 @@ +package com.baeldung.resttemplateexception; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import com.baeldung.resttemplateexception.model.Product; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = { RestTemplate.class, RestTemplateExceptionApplication.class }) +public class RestTemplateExceptionLiveTest { + + @Autowired + RestTemplate restTemplate; + + @Test(expected = IllegalArgumentException.class) + public void givenGetUrl_whenJsonIsPassed_thenThrowException() { + String url = "http://localhost:8080/spring-rest/api/get?criterion={\"prop\":\"name\",\"value\":\"ASUS VivoBook\"}"; + Product product = restTemplate.getForObject(url, Product.class); + } + + @Test + public void givenGetUrl_whenJsonIsPassed_thenGetProduct() { + String criterion = "{\"prop\":\"name\",\"value\":\"ASUS VivoBook\"}"; + String url = "http://localhost:8080/spring-rest/api/get?criterion={criterion}"; + Product product = restTemplate.getForObject(url, Product.class, criterion); + + assertEquals(product.getPrice(), 650, 0); + } + + @Test + public void givenGetUrl_whenJsonIsPassed_thenReturnProduct() { + String criterion = "{\"prop\":\"name\",\"value\":\"Acer Aspire 5\"}"; + String url = "http://localhost:8080/spring-rest/api/get"; + + UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url).queryParam("criterion", criterion); + Product product = restTemplate.getForObject(builder.build().toUri(), Product.class); + + assertEquals(product.getId(), 1, 0); + } +} diff --git a/spring-resttemplate-2/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerIntegrationTest.java b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerIntegrationTest.java similarity index 100% rename from spring-resttemplate-2/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerIntegrationTest.java rename to spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerIntegrationTest.java diff --git a/spring-resttemplate-2/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerLiveTest.java b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerLiveTest.java similarity index 100% rename from spring-resttemplate-2/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerLiveTest.java rename to spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/web/controller/mediatypes/CustomMediaTypeControllerLiveTest.java diff --git a/spring-resttemplate-2/src/test/java/com/baeldung/web/controller/mediatypes/TestConfig.java b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/web/controller/mediatypes/TestConfig.java similarity index 100% rename from spring-resttemplate-2/src/test/java/com/baeldung/web/controller/mediatypes/TestConfig.java rename to spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/web/controller/mediatypes/TestConfig.java diff --git a/spring-resttemplate/src/test/java/com/baeldung/web/controller/redirect/RedirectControllerIntegrationTest.java b/spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/web/controller/redirect/RedirectControllerIntegrationTest.java similarity index 100% rename from spring-resttemplate/src/test/java/com/baeldung/web/controller/redirect/RedirectControllerIntegrationTest.java rename to spring-web-modules/spring-resttemplate-2/src/test/java/com/baeldung/web/controller/redirect/RedirectControllerIntegrationTest.java diff --git a/spring-resttemplate-2/src/test/resources/application.properties b/spring-web-modules/spring-resttemplate-2/src/test/resources/application.properties similarity index 71% rename from spring-resttemplate-2/src/test/resources/application.properties rename to spring-web-modules/spring-resttemplate-2/src/test/resources/application.properties index 7bc9e56041..286ea95a4f 100644 --- a/spring-resttemplate-2/src/test/resources/application.properties +++ b/spring-web-modules/spring-resttemplate-2/src/test/resources/application.properties @@ -1,5 +1,5 @@ logging.level.org.springframework.web.client.RestTemplate=DEBUG -logging.level.com.baeldung.resttemplate.logging.LoggingInterceptor=DEBUG +logging.level.com.baeldung.resttemplate.logging=DEBUG logging.level.org.apache.http=DEBUG logging.level.httpclient.wire=DEBUG logging.pattern.console=%20logger{20} - %msg%n diff --git a/persistence-modules/spring-hibernate4/.gitignore b/spring-web-modules/spring-resttemplate-3/.gitignore similarity index 77% rename from persistence-modules/spring-hibernate4/.gitignore rename to spring-web-modules/spring-resttemplate-3/.gitignore index d31cc4c619..8f98975dc9 100644 --- a/persistence-modules/spring-hibernate4/.gitignore +++ b/spring-web-modules/spring-resttemplate-3/.gitignore @@ -2,7 +2,6 @@ #folders# /target -/neoDb* /data /src/main/webapp/WEB-INF/classes */META-INF/* @@ -10,6 +9,4 @@ # Packaged files # *.jar *.war -*.ear -/target/ -/target/ +*.ear \ No newline at end of file diff --git a/spring-web-modules/spring-resttemplate-3/README.md b/spring-web-modules/spring-resttemplate-3/README.md new file mode 100644 index 0000000000..6a00d226db --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/README.md @@ -0,0 +1,11 @@ +## Spring RestTemplate + +This module contains articles about Spring RestTemplate + +### The Course +The "REST With Spring" Classes: http://bit.ly/restwithspring + +### Relevant Articles: +- [Uploading MultipartFile with Spring RestTemplate](https://www.baeldung.com/spring-rest-template-multipart-upload) +- [Get and Post Lists of Objects with RestTemplate](https://www.baeldung.com/spring-rest-template-list) +- [Download a Large File Through a Spring RestTemplate](https://www.baeldung.com/spring-resttemplate-download-large-file) \ No newline at end of file diff --git a/spring-web-modules/spring-resttemplate-3/pom.xml b/spring-web-modules/spring-resttemplate-3/pom.xml new file mode 100644 index 0000000000..b1c26e002f --- /dev/null +++ b/spring-web-modules/spring-resttemplate-3/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + spring-resttemplate-3 + 0.1-SNAPSHOT + spring-resttemplate-3 + war + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + + + + diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/EmployeeApplication.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/EmployeeApplication.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/EmployeeApplication.java rename to spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/EmployeeApplication.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/client/EmployeeClient.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/client/EmployeeClient.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/client/EmployeeClient.java rename to spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/client/EmployeeClient.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/controller/EmployeeResource.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/controller/EmployeeResource.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/controller/EmployeeResource.java rename to spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/controller/EmployeeResource.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/dto/Employee.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/dto/Employee.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/dto/Employee.java rename to spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/dto/Employee.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/dto/EmployeeList.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/dto/EmployeeList.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/dto/EmployeeList.java rename to spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/dto/EmployeeList.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/service/EmployeeService.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/service/EmployeeService.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/lists/service/EmployeeService.java rename to spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/resttemplate/lists/service/EmployeeService.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/web/upload/app/UploadApplication.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/app/UploadApplication.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/web/upload/app/UploadApplication.java rename to spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/app/UploadApplication.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/web/upload/client/MultipartFileUploadClient.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/client/MultipartFileUploadClient.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/web/upload/client/MultipartFileUploadClient.java rename to spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/client/MultipartFileUploadClient.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/web/upload/controller/FileServerResource.java b/spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/controller/FileServerResource.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/web/upload/controller/FileServerResource.java rename to spring-web-modules/spring-resttemplate-3/src/main/java/com/baeldung/web/upload/controller/FileServerResource.java diff --git a/spring-resttemplate/src/main/resources/application.properties b/spring-web-modules/spring-resttemplate-3/src/main/resources/application.properties similarity index 100% rename from spring-resttemplate/src/main/resources/application.properties rename to spring-web-modules/spring-resttemplate-3/src/main/resources/application.properties diff --git a/spring-resttemplate/src/main/resources/logback.xml b/spring-web-modules/spring-resttemplate-3/src/main/resources/logback.xml similarity index 100% rename from spring-resttemplate/src/main/resources/logback.xml rename to spring-web-modules/spring-resttemplate-3/src/main/resources/logback.xml diff --git a/spring-kafka/src/test/java/com/baeldung/SpringContextLiveTest.java b/spring-web-modules/spring-resttemplate-3/src/test/java/com/baeldung/SpringContextTest.java similarity index 69% rename from spring-kafka/src/test/java/com/baeldung/SpringContextLiveTest.java rename to spring-web-modules/spring-resttemplate-3/src/test/java/com/baeldung/SpringContextTest.java index 60262df9d4..26972a0aca 100644 --- a/spring-kafka/src/test/java/com/baeldung/SpringContextLiveTest.java +++ b/spring-web-modules/spring-resttemplate-3/src/test/java/com/baeldung/SpringContextTest.java @@ -5,11 +5,9 @@ import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.spring.kafka.KafkaApplication; - @RunWith(SpringRunner.class) -@SpringBootTest(classes = KafkaApplication.class) -public class SpringContextLiveTest { +@SpringBootTest(classes = { com.baeldung.web.upload.app.UploadApplication.class, }) +public class SpringContextTest { @Test public void whenSpringContextIsBootstrapped_thenNoExceptions() { diff --git a/spring-resttemplate/src/test/java/com/baeldung/resttemplate/LargeFileDownloadIntegrationTest.java b/spring-web-modules/spring-resttemplate-3/src/test/java/com/baeldung/largefile/LargeFileDownloadIntegrationTest.java similarity index 94% rename from spring-resttemplate/src/test/java/com/baeldung/resttemplate/LargeFileDownloadIntegrationTest.java rename to spring-web-modules/spring-resttemplate-3/src/test/java/com/baeldung/largefile/LargeFileDownloadIntegrationTest.java index eb5d01d06f..d8fc58319f 100644 --- a/spring-resttemplate/src/test/java/com/baeldung/resttemplate/LargeFileDownloadIntegrationTest.java +++ b/spring-web-modules/spring-resttemplate-3/src/test/java/com/baeldung/largefile/LargeFileDownloadIntegrationTest.java @@ -1,21 +1,17 @@ -package com.baeldung.resttemplate; +package com.baeldung.largefile; + +import java.io.File; +import java.io.FileOutputStream; import org.assertj.core.api.Assertions; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import org.springframework.core.io.FileSystemResource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.converter.HttpMessageConverter; import org.springframework.util.StreamUtils; import org.springframework.web.client.RestTemplate; -import java.io.File; -import java.io.FileOutputStream; -import java.util.ArrayList; -import java.util.List; - public class LargeFileDownloadIntegrationTest { static String FILE_URL = "http://ovh.net/files/1Mio.dat"; diff --git a/spring-rest-testing/src/test/resources/.gitignore b/spring-web-modules/spring-resttemplate-3/src/test/resources/.gitignore similarity index 100% rename from spring-rest-testing/src/test/resources/.gitignore rename to spring-web-modules/spring-resttemplate-3/src/test/resources/.gitignore diff --git a/spring-resttemplate/src/test/resources/logback-test.xml b/spring-web-modules/spring-resttemplate-3/src/test/resources/logback-test.xml similarity index 100% rename from spring-resttemplate/src/test/resources/logback-test.xml rename to spring-web-modules/spring-resttemplate-3/src/test/resources/logback-test.xml diff --git a/spring-resttemplate/.gitignore b/spring-web-modules/spring-resttemplate/.gitignore similarity index 100% rename from spring-resttemplate/.gitignore rename to spring-web-modules/spring-resttemplate/.gitignore diff --git a/spring-resttemplate/README.md b/spring-web-modules/spring-resttemplate/README.md similarity index 73% rename from spring-resttemplate/README.md rename to spring-web-modules/spring-resttemplate/README.md index 952f35e90b..e8c240d86b 100644 --- a/spring-resttemplate/README.md +++ b/spring-web-modules/spring-resttemplate/README.md @@ -11,10 +11,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring RestTemplate Error Handling](https://www.baeldung.com/spring-rest-template-error-handling) - [Configure a RestTemplate with RestTemplateBuilder](https://www.baeldung.com/spring-rest-template-builder) - [Mocking a RestTemplate in Spring](https://www.baeldung.com/spring-mock-rest-template) -- [Download a Large File Through a Spring RestTemplate](https://www.baeldung.com/spring-resttemplate-download-large-file) - [Using the Spring RestTemplate Interceptor](https://www.baeldung.com/spring-rest-template-interceptor) -- [Uploading MultipartFile with Spring RestTemplate](https://www.baeldung.com/spring-rest-template-multipart-upload) -- [Get and Post Lists of Objects with RestTemplate](https://www.baeldung.com/spring-rest-template-list) - [HTTP PUT vs HTTP PATCH in a REST API](https://www.baeldung.com/http-put-patch-difference-spring) ### NOTE: diff --git a/spring-resttemplate/pom.xml b/spring-web-modules/spring-resttemplate/pom.xml similarity index 98% rename from spring-resttemplate/pom.xml rename to spring-web-modules/spring-resttemplate/pom.xml index 05660f5210..1db6b5db57 100644 --- a/spring-resttemplate/pom.xml +++ b/spring-web-modules/spring-resttemplate/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 @@ -188,7 +188,7 @@ cargo-maven2-plugin ${cargo-maven2-plugin.version} - + true tomcat8x embedded @@ -297,7 +297,7 @@ 20.0 - 1.6.0 + 1.6.1 3.0.4 diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/service/EmployeeService.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/mock/EmployeeService.java similarity index 95% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/service/EmployeeService.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/mock/EmployeeService.java index 18dff3db1b..16180a3640 100644 --- a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/service/EmployeeService.java +++ b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/mock/EmployeeService.java @@ -1,4 +1,4 @@ -package com.baeldung.resttemplate.web.service; +package com.baeldung.mock; import com.baeldung.resttemplate.web.model.Employee; import org.slf4j.Logger; diff --git a/spring-resttemplate/src/main/java/com/baeldung/responseheaders/ResponseHeadersApplication.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/responseheaders/ResponseHeadersApplication.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/responseheaders/ResponseHeadersApplication.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/responseheaders/ResponseHeadersApplication.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/responseheaders/controllers/FilterResponseHeaderController.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/responseheaders/controllers/FilterResponseHeaderController.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/responseheaders/controllers/FilterResponseHeaderController.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/responseheaders/controllers/FilterResponseHeaderController.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/responseheaders/controllers/ResponseHeaderController.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/responseheaders/controllers/ResponseHeaderController.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/responseheaders/controllers/ResponseHeaderController.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/responseheaders/controllers/ResponseHeaderController.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/responseheaders/filter/AddResponseHeaderFilter.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/responseheaders/filter/AddResponseHeaderFilter.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/responseheaders/filter/AddResponseHeaderFilter.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/responseheaders/filter/AddResponseHeaderFilter.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/RestTemplateConfigurationApplication.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/RestTemplateConfigurationApplication.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/RestTemplateConfigurationApplication.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/RestTemplateConfigurationApplication.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/CustomClientHttpRequestInterceptor.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/CustomClientHttpRequestInterceptor.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/CustomClientHttpRequestInterceptor.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/CustomClientHttpRequestInterceptor.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/CustomRestTemplateCustomizer.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/CustomRestTemplateCustomizer.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/CustomRestTemplateCustomizer.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/CustomRestTemplateCustomizer.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/FooController.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/FooController.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/FooController.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/FooController.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/HelloController.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/HelloController.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/HelloController.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/HelloController.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/SpringConfig.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/SpringConfig.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/SpringConfig.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/configuration/SpringConfig.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/dto/Foo.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/dto/Foo.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/dto/Foo.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/dto/Foo.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/exception/NotFoundException.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/exception/NotFoundException.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/exception/NotFoundException.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/exception/NotFoundException.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/handler/RestTemplateResponseErrorHandler.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/handler/RestTemplateResponseErrorHandler.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/handler/RestTemplateResponseErrorHandler.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/handler/RestTemplateResponseErrorHandler.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/model/Bar.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/model/Bar.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/model/Bar.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/model/Bar.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/model/Employee.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/model/Employee.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/model/Employee.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/model/Employee.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/service/BarConsumerService.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/service/BarConsumerService.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/service/BarConsumerService.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/resttemplate/web/service/BarConsumerService.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/MainApplication.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/MainApplication.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/MainApplication.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/MainApplication.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/RestClientConfig.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/RestClientConfig.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/RestClientConfig.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/RestClientConfig.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/WebConfig.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/WebConfig.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/WebConfig.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/config/WebConfig.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/interceptors/RestTemplateHeaderModifierInterceptor.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/interceptors/RestTemplateHeaderModifierInterceptor.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/interceptors/RestTemplateHeaderModifierInterceptor.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/interceptors/RestTemplateHeaderModifierInterceptor.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/repository/HeavyResourceRepository.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/repository/HeavyResourceRepository.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/repository/HeavyResourceRepository.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/repository/HeavyResourceRepository.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/BarMappingExamplesController.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/BarMappingExamplesController.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/BarMappingExamplesController.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/BarMappingExamplesController.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/CompanyController.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/CompanyController.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/CompanyController.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/CompanyController.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/DeferredResultController.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/DeferredResultController.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/DeferredResultController.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/DeferredResultController.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/HeavyResourceController.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/HeavyResourceController.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/HeavyResourceController.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/HeavyResourceController.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/ItemController.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/ItemController.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/ItemController.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/ItemController.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/MyFooController.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/MyFooController.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/MyFooController.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/MyFooController.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/PactController.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/PactController.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/PactController.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/PactController.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/SimplePostController.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/SimplePostController.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/SimplePostController.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/controller/SimplePostController.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Company.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Company.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Company.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Company.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Foo.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResource.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResource.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResource.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResource.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressOnly.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressOnly.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressOnly.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressOnly.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressPartialUpdate.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressPartialUpdate.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressPartialUpdate.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/HeavyResourceAddressPartialUpdate.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Item.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Item.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Item.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Item.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/ItemManager.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/ItemManager.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/ItemManager.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/ItemManager.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/PactDto.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/PactDto.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/PactDto.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/PactDto.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Views.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Views.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Views.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/dto/Views.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/exception/ResourceNotFoundException.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/exception/ResourceNotFoundException.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/exception/ResourceNotFoundException.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/sampleapp/web/exception/ResourceNotFoundException.java diff --git a/spring-resttemplate/src/main/java/com/baeldung/transfer/LoginForm.java b/spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/transfer/LoginForm.java similarity index 100% rename from spring-resttemplate/src/main/java/com/baeldung/transfer/LoginForm.java rename to spring-web-modules/spring-resttemplate/src/main/java/com/baeldung/transfer/LoginForm.java diff --git a/spring-web-modules/spring-resttemplate/src/main/resources/application.properties b/spring-web-modules/spring-resttemplate/src/main/resources/application.properties new file mode 100644 index 0000000000..1a26e3ad99 --- /dev/null +++ b/spring-web-modules/spring-resttemplate/src/main/resources/application.properties @@ -0,0 +1,2 @@ +server.port=8082 +server.servlet.context-path=/spring-rest \ No newline at end of file diff --git a/spring-web-modules/spring-resttemplate/src/main/resources/logback.xml b/spring-web-modules/spring-resttemplate/src/main/resources/logback.xml new file mode 100644 index 0000000000..9f48d36486 --- /dev/null +++ b/spring-web-modules/spring-resttemplate/src/main/resources/logback.xml @@ -0,0 +1,23 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-resttemplate/src/test/java/com/baeldung/SpringContextTest.java b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/SpringContextTest.java similarity index 75% rename from spring-resttemplate/src/test/java/com/baeldung/SpringContextTest.java rename to spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/SpringContextTest.java index 43901cf37f..dc176f5322 100644 --- a/spring-resttemplate/src/test/java/com/baeldung/SpringContextTest.java +++ b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/SpringContextTest.java @@ -8,12 +8,10 @@ import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.responseheaders.ResponseHeadersApplication; @RunWith(SpringRunner.class) -@SpringBootTest(classes = { ResponseHeadersApplication.class, - com.baeldung.web.upload.app.UploadApplication.class, - }) +@SpringBootTest(classes = { ResponseHeadersApplication.class }) public class SpringContextTest { @Test - public void whenSpringContextIsBootstrapped_thenNoExceptions() { + public void whenSpringContextIsBootstrapped_thenNoExceptions() { } } diff --git a/spring-resttemplate/src/test/java/com/baeldung/SpringTestConfig.java b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/SpringTestConfig.java similarity index 100% rename from spring-resttemplate/src/test/java/com/baeldung/SpringTestConfig.java rename to spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/SpringTestConfig.java diff --git a/spring-resttemplate/src/test/java/com/baeldung/client/Consts.java b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/client/Consts.java similarity index 100% rename from spring-resttemplate/src/test/java/com/baeldung/client/Consts.java rename to spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/client/Consts.java diff --git a/spring-resttemplate/src/test/java/com/baeldung/client/TestRestTemplateBasicLiveTest.java b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/client/TestRestTemplateBasicLiveTest.java similarity index 98% rename from spring-resttemplate/src/test/java/com/baeldung/client/TestRestTemplateBasicLiveTest.java rename to spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/client/TestRestTemplateBasicLiveTest.java index 9f4b3c9b35..406dd5979b 100644 --- a/spring-resttemplate/src/test/java/com/baeldung/client/TestRestTemplateBasicLiveTest.java +++ b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/client/TestRestTemplateBasicLiveTest.java @@ -18,6 +18,7 @@ import org.springframework.web.client.RestTemplate; import okhttp3.Request; import okhttp3.RequestBody; +// This test needs RestTemplateConfigurationApplication to be up and running public class TestRestTemplateBasicLiveTest { private RestTemplate restTemplate; diff --git a/spring-resttemplate/src/test/java/com/baeldung/web/service/EmployeeServiceMockRestServiceServerUnitTest.java b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/mock/EmployeeServiceMockRestServiceServerUnitTest.java similarity index 96% rename from spring-resttemplate/src/test/java/com/baeldung/web/service/EmployeeServiceMockRestServiceServerUnitTest.java rename to spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/mock/EmployeeServiceMockRestServiceServerUnitTest.java index ee01cb6a50..309e0635a4 100644 --- a/spring-resttemplate/src/test/java/com/baeldung/web/service/EmployeeServiceMockRestServiceServerUnitTest.java +++ b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/mock/EmployeeServiceMockRestServiceServerUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.web.service; +package com.baeldung.mock; import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; @@ -7,8 +7,9 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat import java.net.URI; import com.baeldung.SpringTestConfig; +import com.baeldung.mock.EmployeeService; import com.baeldung.resttemplate.web.model.Employee; -import com.baeldung.resttemplate.web.service.EmployeeService; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; diff --git a/spring-resttemplate/src/test/java/com/baeldung/web/service/EmployeeServiceUnitTest.java b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/mock/EmployeeServiceUnitTest.java similarity index 92% rename from spring-resttemplate/src/test/java/com/baeldung/web/service/EmployeeServiceUnitTest.java rename to spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/mock/EmployeeServiceUnitTest.java index 6eb040414b..9a992f390a 100644 --- a/spring-resttemplate/src/test/java/com/baeldung/web/service/EmployeeServiceUnitTest.java +++ b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/mock/EmployeeServiceUnitTest.java @@ -1,7 +1,8 @@ -package com.baeldung.web.service; +package com.baeldung.mock; +import com.baeldung.mock.EmployeeService; import com.baeldung.resttemplate.web.model.Employee; -import com.baeldung.resttemplate.web.service.EmployeeService; + import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-resttemplate/src/test/java/com/baeldung/pact/PactProviderLiveTest.java b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/pact/PactProviderLiveTest.java similarity index 100% rename from spring-resttemplate/src/test/java/com/baeldung/pact/PactProviderLiveTest.java rename to spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/pact/PactProviderLiveTest.java diff --git a/spring-resttemplate/src/test/java/com/baeldung/resttemplate/RestTemplateBasicLiveTest.java b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/resttemplate/RestTemplateBasicLiveTest.java similarity index 99% rename from spring-resttemplate/src/test/java/com/baeldung/resttemplate/RestTemplateBasicLiveTest.java rename to spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/resttemplate/RestTemplateBasicLiveTest.java index 0dab124316..8d52394dd1 100644 --- a/spring-resttemplate/src/test/java/com/baeldung/resttemplate/RestTemplateBasicLiveTest.java +++ b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/resttemplate/RestTemplateBasicLiveTest.java @@ -38,6 +38,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.google.common.base.Charsets; +// This test needs RestTemplateConfigurationApplication to be up and running public class RestTemplateBasicLiveTest { private RestTemplate restTemplate; diff --git a/spring-resttemplate/src/test/java/com/baeldung/resttemplate/RestTemplateLiveTest.java b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/resttemplate/RestTemplateLiveTest.java similarity index 100% rename from spring-resttemplate/src/test/java/com/baeldung/resttemplate/RestTemplateLiveTest.java rename to spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/resttemplate/RestTemplateLiveTest.java diff --git a/spring-resttemplate/src/test/java/com/baeldung/web/handler/RestTemplateResponseErrorHandlerIntegrationTest.java b/spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/web/handler/RestTemplateResponseErrorHandlerIntegrationTest.java similarity index 100% rename from spring-resttemplate/src/test/java/com/baeldung/web/handler/RestTemplateResponseErrorHandlerIntegrationTest.java rename to spring-web-modules/spring-resttemplate/src/test/java/com/baeldung/web/handler/RestTemplateResponseErrorHandlerIntegrationTest.java diff --git a/spring-resttemplate/src/test/resources/.gitignore b/spring-web-modules/spring-resttemplate/src/test/resources/.gitignore similarity index 100% rename from spring-resttemplate/src/test/resources/.gitignore rename to spring-web-modules/spring-resttemplate/src/test/resources/.gitignore diff --git a/spring-web-modules/spring-resttemplate/src/test/resources/logback-test.xml b/spring-web-modules/spring-resttemplate/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..9f48d36486 --- /dev/null +++ b/spring-web-modules/spring-resttemplate/src/test/resources/logback-test.xml @@ -0,0 +1,23 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-thymeleaf-2/README.md b/spring-web-modules/spring-thymeleaf-2/README.md similarity index 100% rename from spring-thymeleaf-2/README.md rename to spring-web-modules/spring-thymeleaf-2/README.md diff --git a/spring-thymeleaf-2/pom.xml b/spring-web-modules/spring-thymeleaf-2/pom.xml similarity index 97% rename from spring-thymeleaf-2/pom.xml rename to spring-web-modules/spring-thymeleaf-2/pom.xml index 43f36d9887..ddcd1e1005 100644 --- a/spring-thymeleaf-2/pom.xml +++ b/spring-web-modules/spring-thymeleaf-2/pom.xml @@ -10,7 +10,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/Application.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/Application.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/Application.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/Application.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/ThymeleafConfig.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/ThymeleafConfig.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/ThymeleafConfig.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/ThymeleafConfig.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/arrays/ThymeleafArrayController.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/arrays/ThymeleafArrayController.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/arrays/ThymeleafArrayController.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/arrays/ThymeleafArrayController.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/booleanexpressions/BooleanExpressionsController.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/booleanexpressions/BooleanExpressionsController.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/booleanexpressions/BooleanExpressionsController.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/booleanexpressions/BooleanExpressionsController.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/customhtml/Course.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/customhtml/Course.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/customhtml/Course.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/customhtml/Course.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/customhtml/CourseRegistrationController.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/customhtml/CourseRegistrationController.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/customhtml/CourseRegistrationController.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/customhtml/CourseRegistrationController.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/Color.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/Color.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/Color.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/Color.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/Widget.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/Widget.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/Widget.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/Widget.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/WidgetController.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/WidgetController.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/WidgetController.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/enums/WidgetController.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/lists/ListsController.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/lists/ListsController.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/lists/ListsController.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/lists/ListsController.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/BeanConfig.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/BeanConfig.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/BeanConfig.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/BeanConfig.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/EmailController.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/repository/EmailData.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/repository/EmailData.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/repository/EmailData.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/mvcdata/repository/EmailData.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/pathvariables/Detail.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/pathvariables/Detail.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/pathvariables/Detail.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/pathvariables/Detail.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/pathvariables/Item.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/pathvariables/Item.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/pathvariables/Item.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/pathvariables/Item.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/pathvariables/PathVariablesController.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/pathvariables/PathVariablesController.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/pathvariables/PathVariablesController.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/pathvariables/PathVariablesController.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/requestparameters/ParticipantController.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/requestparameters/ParticipantController.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/requestparameters/ParticipantController.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/requestparameters/ParticipantController.java diff --git a/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/templatedir/HelloController.java b/spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/templatedir/HelloController.java similarity index 100% rename from spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/templatedir/HelloController.java rename to spring-web-modules/spring-thymeleaf-2/src/main/java/com/baeldung/thymeleaf/templatedir/HelloController.java diff --git a/spring-thymeleaf-2/src/main/resources/application.properties b/spring-web-modules/spring-thymeleaf-2/src/main/resources/application.properties similarity index 100% rename from spring-thymeleaf-2/src/main/resources/application.properties rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/application.properties diff --git a/spring-thymeleaf-2/src/main/resources/templates-2/hello.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates-2/hello.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates-2/hello.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates-2/hello.html diff --git a/spring-thymeleaf-2/src/main/resources/templates-2/participants.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates-2/participants.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates-2/participants.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates-2/participants.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/booleans.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/booleans.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/booleans.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/booleans.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/continents.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/continents.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/continents.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/continents.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/courseRegistration.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/courseRegistration.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/courseRegistration.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/courseRegistration.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/enums/new.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/enums/new.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/enums/new.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/enums/new.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/enums/view.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/enums/view.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/enums/view.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/enums/view.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/lists/contains.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/lists/contains.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/lists/contains.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/lists/contains.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/lists/isEmpty.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/lists/isEmpty.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/lists/isEmpty.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/lists/isEmpty.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/lists/size.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/lists/size.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/lists/size.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/lists/size.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/lists/sort.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/lists/sort.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/lists/sort.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/lists/sort.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/lists/toList.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/lists/toList.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/lists/toList.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/lists/toList.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-bean-data.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-bean-data.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-bean-data.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-bean-data.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-model-attributes.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-model-attributes.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-model-attributes.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-model-attributes.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-request-parameters.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-request-parameters.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-request-parameters.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-request-parameters.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-servlet-context.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-servlet-context.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-servlet-context.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-servlet-context.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-session-attributes.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-session-attributes.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-session-attributes.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/mvcdata/email-session-attributes.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/pathvariables/index.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/pathvariables/index.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/pathvariables/index.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/pathvariables/index.html diff --git a/spring-thymeleaf-2/src/main/resources/templates/pathvariables/view.html b/spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/pathvariables/view.html similarity index 100% rename from spring-thymeleaf-2/src/main/resources/templates/pathvariables/view.html rename to spring-web-modules/spring-thymeleaf-2/src/main/resources/templates/pathvariables/view.html diff --git a/spring-thymeleaf-2/src/test/java/com/baeldung/thymeleaf/lists/ListsControllerIntegrationTest.java b/spring-web-modules/spring-thymeleaf-2/src/test/java/com/baeldung/thymeleaf/lists/ListsControllerIntegrationTest.java similarity index 100% rename from spring-thymeleaf-2/src/test/java/com/baeldung/thymeleaf/lists/ListsControllerIntegrationTest.java rename to spring-web-modules/spring-thymeleaf-2/src/test/java/com/baeldung/thymeleaf/lists/ListsControllerIntegrationTest.java diff --git a/spring-thymeleaf-2/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java b/spring-web-modules/spring-thymeleaf-2/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java similarity index 100% rename from spring-thymeleaf-2/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java rename to spring-web-modules/spring-thymeleaf-2/src/test/java/com/baeldung/thymeleaf/mvcdata/EmailControllerUnitTest.java diff --git a/spring-thymeleaf-3/README.md b/spring-web-modules/spring-thymeleaf-3/README.md similarity index 89% rename from spring-thymeleaf-3/README.md rename to spring-web-modules/spring-thymeleaf-3/README.md index 8bb8861daf..048b48d39f 100644 --- a/spring-thymeleaf-3/README.md +++ b/spring-web-modules/spring-thymeleaf-3/README.md @@ -9,3 +9,4 @@ This module contains articles about Spring with Thymeleaf - [Working with Select and Option in Thymeleaf](https://www.baeldung.com/thymeleaf-select-option) - [Conditional CSS Classes in Thymeleaf](https://www.baeldung.com/spring-mvc-thymeleaf-conditional-css-classes) - [Using Hidden Inputs with Spring and Thymeleaf](https://www.baeldung.com/spring-thymeleaf-hidden-inputs) +- [Thymeleaf Variables](https://www.baeldung.com/thymeleaf-variables) diff --git a/spring-thymeleaf-3/pom.xml b/spring-web-modules/spring-thymeleaf-3/pom.xml similarity index 98% rename from spring-thymeleaf-3/pom.xml rename to spring-web-modules/spring-thymeleaf-3/pom.xml index 7c58115d11..6dd1267e8a 100644 --- a/spring-thymeleaf-3/pom.xml +++ b/spring-web-modules/spring-thymeleaf-3/pom.xml @@ -10,7 +10,7 @@ com.baeldung parent-boot-2 0.0.1-SNAPSHOT - ../parent-boot-2 + ../../parent-boot-2 diff --git a/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/Application.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/Application.java similarity index 100% rename from spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/Application.java rename to spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/Application.java diff --git a/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/articles/Article.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/articles/Article.java new file mode 100644 index 0000000000..9b01328e45 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/articles/Article.java @@ -0,0 +1,28 @@ +package main.java.com.baeldung.thymeleaf.articles; + +public class Article { + + private String name; + private String url; + + public Article(String name, String url) { + this.name = name; + this.url = url; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } +} diff --git a/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/articles/ArticlesController.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/articles/ArticlesController.java new file mode 100644 index 0000000000..cfbf0fcaa6 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/articles/ArticlesController.java @@ -0,0 +1,37 @@ +package main.java.com.baeldung.thymeleaf.articles; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; + +import java.util.Arrays; +import java.util.List; + +@Controller +@RequestMapping("/api/articles") +public class ArticlesController { + + @GetMapping + public String allArticles(Model model) { + model.addAttribute("articles", fetchArticles()); + return "articles/articles-list"; + } + + private List
fetchArticles() { + return Arrays.asList( + new Article( + "Introduction to Using Thymeleaf in Spring", + "https://www.baeldung.com/thymeleaf-in-spring-mvc" + ), + new Article( + "Spring Boot CRUD Application with Thymeleaf", + "https://www.baeldung.com/spring-boot-crud-thymeleaf" + ), + new Article( + "Spring MVC Data and Thymeleaf", + "https://www.baeldung.com/spring-mvc-thymeleaf-data" + ) + ); + } +} diff --git a/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/blog/BlogController.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/blog/BlogController.java similarity index 100% rename from spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/blog/BlogController.java rename to spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/blog/BlogController.java diff --git a/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/blog/BlogDTO.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/blog/BlogDTO.java similarity index 100% rename from spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/blog/BlogDTO.java rename to spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/blog/BlogDTO.java diff --git a/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/conditionalclasses/ConditionalClassesController.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/conditionalclasses/ConditionalClassesController.java similarity index 100% rename from spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/conditionalclasses/ConditionalClassesController.java rename to spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/conditionalclasses/ConditionalClassesController.java diff --git a/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/cssandjs/CssAndJsApplication.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/cssandjs/CssAndJsApplication.java similarity index 100% rename from spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/cssandjs/CssAndJsApplication.java rename to spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/cssandjs/CssAndJsApplication.java diff --git a/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/cssandjs/CssAndJsController.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/cssandjs/CssAndJsController.java similarity index 100% rename from spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/cssandjs/CssAndJsController.java rename to spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/cssandjs/CssAndJsController.java diff --git a/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/currencies/CurrenciesController.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/currencies/CurrenciesController.java similarity index 100% rename from spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/currencies/CurrenciesController.java rename to spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/currencies/CurrenciesController.java diff --git a/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/option/Student.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/option/Student.java similarity index 100% rename from spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/option/Student.java rename to spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/option/Student.java diff --git a/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/option/StudentController.java b/spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/option/StudentController.java similarity index 100% rename from spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/option/StudentController.java rename to spring-web-modules/spring-thymeleaf-3/src/main/java/com/baeldung/thymeleaf/option/StudentController.java diff --git a/spring-thymeleaf-3/src/main/resources/static/js/cssandjs/actions.js b/spring-web-modules/spring-thymeleaf-3/src/main/resources/static/js/cssandjs/actions.js similarity index 100% rename from spring-thymeleaf-3/src/main/resources/static/js/cssandjs/actions.js rename to spring-web-modules/spring-thymeleaf-3/src/main/resources/static/js/cssandjs/actions.js diff --git a/spring-thymeleaf-3/src/main/resources/static/styles/cssandjs/main.css b/spring-web-modules/spring-thymeleaf-3/src/main/resources/static/styles/cssandjs/main.css similarity index 100% rename from spring-thymeleaf-3/src/main/resources/static/styles/cssandjs/main.css rename to spring-web-modules/spring-thymeleaf-3/src/main/resources/static/styles/cssandjs/main.css diff --git a/spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/articles/articles-list.html b/spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/articles/articles-list.html new file mode 100644 index 0000000000..de03a86731 --- /dev/null +++ b/spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/articles/articles-list.html @@ -0,0 +1,39 @@ + + + + Thymeleaf Variables + + + +
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+

+
+ +
+
+ +
+
+
+ + \ No newline at end of file diff --git a/spring-thymeleaf-3/src/main/resources/templates/blog/blog-new.html b/spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/blog/blog-new.html similarity index 100% rename from spring-thymeleaf-3/src/main/resources/templates/blog/blog-new.html rename to spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/blog/blog-new.html diff --git a/spring-thymeleaf-3/src/main/resources/templates/conditionalclasses/conditionalclasses.html b/spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/conditionalclasses/conditionalclasses.html similarity index 100% rename from spring-thymeleaf-3/src/main/resources/templates/conditionalclasses/conditionalclasses.html rename to spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/conditionalclasses/conditionalclasses.html diff --git a/spring-thymeleaf-3/src/main/resources/templates/cssandjs/styledPage.html b/spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/cssandjs/styledPage.html similarity index 100% rename from spring-thymeleaf-3/src/main/resources/templates/cssandjs/styledPage.html rename to spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/cssandjs/styledPage.html diff --git a/spring-thymeleaf-3/src/main/resources/templates/currencies/currencies.html b/spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/currencies/currencies.html similarity index 100% rename from spring-thymeleaf-3/src/main/resources/templates/currencies/currencies.html rename to spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/currencies/currencies.html diff --git a/spring-thymeleaf-3/src/main/resources/templates/option/studentForm.html b/spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/option/studentForm.html similarity index 100% rename from spring-thymeleaf-3/src/main/resources/templates/option/studentForm.html rename to spring-web-modules/spring-thymeleaf-3/src/main/resources/templates/option/studentForm.html diff --git a/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/ApplicationIntegrationTest.java b/spring-web-modules/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/ApplicationIntegrationTest.java similarity index 100% rename from spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/ApplicationIntegrationTest.java rename to spring-web-modules/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/ApplicationIntegrationTest.java diff --git a/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/cssandjs/CssAndJsControllerIntegrationTest.java b/spring-web-modules/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/cssandjs/CssAndJsControllerIntegrationTest.java similarity index 100% rename from spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/cssandjs/CssAndJsControllerIntegrationTest.java rename to spring-web-modules/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/cssandjs/CssAndJsControllerIntegrationTest.java diff --git a/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/currencies/CurrenciesControllerIntegrationTest.java b/spring-web-modules/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/currencies/CurrenciesControllerIntegrationTest.java similarity index 100% rename from spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/currencies/CurrenciesControllerIntegrationTest.java rename to spring-web-modules/spring-thymeleaf-3/src/test/java/com/baeldung/thymeleaf/currencies/CurrenciesControllerIntegrationTest.java diff --git a/spring-thymeleaf/README.md b/spring-web-modules/spring-thymeleaf/README.md similarity index 100% rename from spring-thymeleaf/README.md rename to spring-web-modules/spring-thymeleaf/README.md diff --git a/spring-thymeleaf/pom.xml b/spring-web-modules/spring-thymeleaf/pom.xml similarity index 99% rename from spring-thymeleaf/pom.xml rename to spring-web-modules/spring-thymeleaf/pom.xml index 30f77dd73e..7b0cd2c510 100644 --- a/spring-thymeleaf/pom.xml +++ b/spring-web-modules/spring-thymeleaf/pom.xml @@ -11,7 +11,7 @@ com.baeldung parent-spring-5 0.0.1-SNAPSHOT - ../parent-spring-5 + ../../parent-spring-5 diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/InitSecurity.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/InitSecurity.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/InitSecurity.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/InitSecurity.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebApp.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebApp.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebApp.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebApp.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCConfig.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCSecurity.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCSecurity.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCSecurity.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/config/WebMVCSecurity.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/BookController.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/BookController.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/BookController.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/BookController.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/DatesController.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/DatesController.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/DatesController.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/DatesController.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsController.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsController.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsController.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsController.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/FragmentsController.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/FragmentsController.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/FragmentsController.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/FragmentsController.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/HomeController.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/InliningController.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/InliningController.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/InliningController.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/InliningController.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/LayoutDialectController.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/LayoutDialectController.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/LayoutDialectController.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/LayoutDialectController.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/StudentController.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/StudentController.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/StudentController.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/StudentController.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/TeacherController.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/TeacherController.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/TeacherController.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/controller/TeacherController.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/formatter/NameFormatter.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/formatter/NameFormatter.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/formatter/NameFormatter.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/formatter/NameFormatter.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Book.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Book.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Book.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Book.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Student.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Student.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Student.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Student.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Teacher.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Teacher.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Teacher.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/model/Teacher.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/service/BookService.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/service/BookService.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/service/BookService.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/service/BookService.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/ArrayUtil.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/ArrayUtil.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/ArrayUtil.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/ArrayUtil.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/BookUtils.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/BookUtils.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/BookUtils.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/BookUtils.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/StudentUtils.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/StudentUtils.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/StudentUtils.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/StudentUtils.java diff --git a/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/TeacherUtils.java b/spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/TeacherUtils.java similarity index 100% rename from spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/TeacherUtils.java rename to spring-web-modules/spring-thymeleaf/src/main/java/com/baeldung/thymeleaf/utils/TeacherUtils.java diff --git a/spring-thymeleaf/src/main/resources/logback.xml b/spring-web-modules/spring-thymeleaf/src/main/resources/logback.xml similarity index 100% rename from spring-thymeleaf/src/main/resources/logback.xml rename to spring-web-modules/spring-thymeleaf/src/main/resources/logback.xml diff --git a/spring-thymeleaf/src/main/resources/messages_en.properties b/spring-web-modules/spring-thymeleaf/src/main/resources/messages_en.properties similarity index 100% rename from spring-thymeleaf/src/main/resources/messages_en.properties rename to spring-web-modules/spring-thymeleaf/src/main/resources/messages_en.properties diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/css/styles.css b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/css/styles.css similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/css/styles.css rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/css/styles.css diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/js/studentCheck.js b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/js/studentCheck.js similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/js/studentCheck.js rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/js/studentCheck.js diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/txt/studentsList.txt b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/txt/studentsList.txt similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/txt/studentsList.txt rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/txt/studentsList.txt diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/addStudent.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/addStudent.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/addStudent.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/addStudent.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/content.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/content.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/content.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/content.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/csrfAttack.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/csrfAttack.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/csrfAttack.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/csrfAttack.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/dates.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/dates.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/dates.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/dates.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/forms.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/forms.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/forms.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/forms.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/general.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/general.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/general.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/general.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/menus.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/menus.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/menus.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/menus.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/subtitle.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/subtitle.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/subtitle.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/subtitle.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/tables.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/tables.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/tables.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/fragments/tables.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/home.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/home.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/home.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/home.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/inliningExample.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/inliningExample.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/inliningExample.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/inliningExample.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/listBooks.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/listBooks.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/listBooks.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/listBooks.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/listStudents.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/listStudents.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/listStudents.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/listStudents.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/listTeachers.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/listTeachers.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/listTeachers.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/listTeachers.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/markup.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/markup.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/markup.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/markup.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/objects.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/objects.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/objects.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/objects.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/other.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/other.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/other.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/other.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/params.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/params.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/params.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/params.html diff --git a/spring-thymeleaf/src/main/webapp/WEB-INF/views/template.html b/spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/template.html similarity index 100% rename from spring-thymeleaf/src/main/webapp/WEB-INF/views/template.html rename to spring-web-modules/spring-thymeleaf/src/main/webapp/WEB-INF/views/template.html diff --git a/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/SpringContextTest.java b/spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/SpringContextTest.java similarity index 100% rename from spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/SpringContextTest.java rename to spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/SpringContextTest.java diff --git a/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerIntegrationTest.java b/spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerIntegrationTest.java similarity index 100% rename from spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerIntegrationTest.java rename to spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/ExpressionUtilityObjectsControllerIntegrationTest.java diff --git a/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/FragmentsIntegrationTest.java b/spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/FragmentsIntegrationTest.java similarity index 100% rename from spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/FragmentsIntegrationTest.java rename to spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/FragmentsIntegrationTest.java diff --git a/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/LayoutDialectControllerIntegrationTest.java b/spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/LayoutDialectControllerIntegrationTest.java similarity index 100% rename from spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/LayoutDialectControllerIntegrationTest.java rename to spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/controller/LayoutDialectControllerIntegrationTest.java diff --git a/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/security/csrf/CsrfEnabledIntegrationTest.java b/spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/security/csrf/CsrfEnabledIntegrationTest.java similarity index 100% rename from spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/security/csrf/CsrfEnabledIntegrationTest.java rename to spring-web-modules/spring-thymeleaf/src/test/java/com/baeldung/thymeleaf/security/csrf/CsrfEnabledIntegrationTest.java diff --git a/spring-websockets/README.md b/spring-websockets/README.md index 26e1c6db7c..9cc84f0fda 100644 --- a/spring-websockets/README.md +++ b/spring-websockets/README.md @@ -5,3 +5,4 @@ This module contains articles about Spring WebSockets. ### Relevant articles - [Intro to WebSockets with Spring](https://www.baeldung.com/websockets-spring) - [A Quick Example of Spring Websockets’ @SendToUser Annotation](https://www.baeldung.com/spring-websockets-sendtouser) +- [Scheduled WebSocket Push with Spring Boot](https://www.baeldung.com/spring-boot-scheduled-websocket) diff --git a/spring-websockets/pom.xml b/spring-websockets/pom.xml index ddfd512476..d2a32a8eb6 100644 --- a/spring-websockets/pom.xml +++ b/spring-websockets/pom.xml @@ -18,6 +18,15 @@ org.springframework.boot spring-boot-starter-websocket + + io.projectreactor + reactor-core + + + com.github.javafaker + javafaker + 1.0.2 + com.google.code.gson gson diff --git a/spring-websockets/src/main/java/com/baeldung/SpringBootApp.java b/spring-websockets/src/main/java/com/baeldung/SpringBootApp.java index ea2a461dfc..3a98746748 100644 --- a/spring-websockets/src/main/java/com/baeldung/SpringBootApp.java +++ b/spring-websockets/src/main/java/com/baeldung/SpringBootApp.java @@ -3,8 +3,10 @@ package com.baeldung; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication +@EnableScheduling public class SpringBootApp extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(SpringBootApp.class, args); diff --git a/spring-websockets/src/main/java/com/baeldung/websockets/BotsController.java b/spring-websockets/src/main/java/com/baeldung/websockets/BotsController.java new file mode 100644 index 0000000000..3f268f3794 --- /dev/null +++ b/spring-websockets/src/main/java/com/baeldung/websockets/BotsController.java @@ -0,0 +1,21 @@ +package com.baeldung.websockets; + +import org.springframework.messaging.handler.annotation.MessageMapping; +import org.springframework.messaging.handler.annotation.SendTo; +import org.springframework.stereotype.Controller; + +import java.text.SimpleDateFormat; +import java.util.Date; + +@Controller +public class BotsController { + + @MessageMapping("/chatwithbots") + @SendTo("/topic/pushmessages") + public OutputMessage send(final Message message) throws Exception { + + final String time = new SimpleDateFormat("HH:mm").format(new Date()); + return new OutputMessage(message.getFrom(), message.getText(), time); + } + +} diff --git a/spring-websockets/src/main/java/com/baeldung/websockets/ReactiveScheduledPushMessages.java b/spring-websockets/src/main/java/com/baeldung/websockets/ReactiveScheduledPushMessages.java new file mode 100644 index 0000000000..36b1b886fc --- /dev/null +++ b/spring-websockets/src/main/java/com/baeldung/websockets/ReactiveScheduledPushMessages.java @@ -0,0 +1,32 @@ +package com.baeldung.websockets; + +import com.github.javafaker.Faker; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; + +import java.text.SimpleDateFormat; +import java.time.Duration; +import java.util.Date; + +@Service +public class ReactiveScheduledPushMessages implements InitializingBean { + + private final SimpMessagingTemplate simpMessagingTemplate; + + private final Faker faker; + + public ReactiveScheduledPushMessages(SimpMessagingTemplate simpMessagingTemplate) { + this.simpMessagingTemplate = simpMessagingTemplate; + this.faker = new Faker(); + } + + @Override + public void afterPropertiesSet() throws Exception { + Flux.interval(Duration.ofSeconds(4L)) + .map((n) -> new OutputMessage(faker.backToTheFuture().character(), faker.backToTheFuture().quote(), + new SimpleDateFormat("HH:mm").format(new Date()))) + .subscribe(message -> simpMessagingTemplate.convertAndSend("/topic/pushmessages", message)); + } +} diff --git a/spring-websockets/src/main/java/com/baeldung/websockets/ScheduledPushMessages.java b/spring-websockets/src/main/java/com/baeldung/websockets/ScheduledPushMessages.java new file mode 100644 index 0000000000..2468b69713 --- /dev/null +++ b/spring-websockets/src/main/java/com/baeldung/websockets/ScheduledPushMessages.java @@ -0,0 +1,32 @@ +package com.baeldung.websockets; + + +import com.github.javafaker.Faker; +import org.springframework.messaging.simp.SimpMessagingTemplate; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Controller; +import org.springframework.stereotype.Service; + +import java.text.SimpleDateFormat; +import java.util.Date; + +@Service +public class ScheduledPushMessages { + + private final SimpMessagingTemplate simpMessagingTemplate; + + private final Faker faker; + + public ScheduledPushMessages(SimpMessagingTemplate simpMessagingTemplate) { + this.simpMessagingTemplate = simpMessagingTemplate; + faker = new Faker(); + } + + @Scheduled(fixedRate = 5000) + public void sendMessage() { + final String time = new SimpleDateFormat("HH:mm").format(new Date()); + simpMessagingTemplate.convertAndSend("/topic/pushmessages", + new OutputMessage("Chuck Norris", faker.chuckNorris().fact(), time)); + } + +} diff --git a/spring-websockets/src/main/java/com/baeldung/websockets/WebSocketConfig.java b/spring-websockets/src/main/java/com/baeldung/websockets/WebSocketConfig.java index 7b53dbc3f3..6179ec9c0d 100644 --- a/spring-websockets/src/main/java/com/baeldung/websockets/WebSocketConfig.java +++ b/spring-websockets/src/main/java/com/baeldung/websockets/WebSocketConfig.java @@ -20,6 +20,8 @@ public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { public void registerStompEndpoints(final StompEndpointRegistry registry) { registry.addEndpoint("/chat"); registry.addEndpoint("/chat").withSockJS(); + registry.addEndpoint("/chatwithbots"); + registry.addEndpoint("/chatwithbots").withSockJS(); } } \ No newline at end of file diff --git a/spring-websockets/src/main/webapp/bots.html b/spring-websockets/src/main/webapp/bots.html new file mode 100644 index 0000000000..38570d420c --- /dev/null +++ b/spring-websockets/src/main/webapp/bots.html @@ -0,0 +1,88 @@ + + + Chat WebSocket + + + + + + + + + + +
+ + +
+ +
+
+
+ + +
+
+
+ + +

+
+
+ + + \ No newline at end of file diff --git a/stripe/README.md b/stripe/README.md index 9e41dcf945..36f0d6e3f3 100644 --- a/stripe/README.md +++ b/stripe/README.md @@ -5,4 +5,4 @@ This module contains articles about Stripe ### Relevant articles - [Introduction to the Stripe API for Java](https://www.baeldung.com/java-stripe-api) - +- [Viewing Contents of a JAR File](https://www.baeldung.com/java-view-jar-contents) diff --git a/testing-modules/junit-4/README.md b/testing-modules/junit-4/README.md index 6cc3981ed4..cf20c8da91 100644 --- a/testing-modules/junit-4/README.md +++ b/testing-modules/junit-4/README.md @@ -5,3 +5,4 @@ - [Introduction to JUnitParams](http://www.baeldung.com/junit-params) - [Running JUnit Tests Programmatically, from a Java Application](https://www.baeldung.com/junit-tests-run-programmatically-from-java) - [Introduction to Lambda Behave](https://www.baeldung.com/lambda-behave) +- [Conditionally Run or Ignore Tests in JUnit 4](https://www.baeldung.com/junit-conditional-assume) diff --git a/testing-modules/junit-5-advanced/src/test/java/com/baeldung/extensions/testwatcher/TestResultLoggerExtension.java b/testing-modules/junit-5-advanced/src/test/java/com/baeldung/extensions/testwatcher/TestResultLoggerExtension.java index a92c44a85b..1cbebd8d48 100644 --- a/testing-modules/junit-5-advanced/src/test/java/com/baeldung/extensions/testwatcher/TestResultLoggerExtension.java +++ b/testing-modules/junit-5-advanced/src/test/java/com/baeldung/extensions/testwatcher/TestResultLoggerExtension.java @@ -46,7 +46,7 @@ public class TestResultLoggerExtension implements TestWatcher, AfterAllCallback @Override public void testFailed(ExtensionContext context, Throwable cause) { - LOG.info("Test Aborted for test {}: ", context.getDisplayName()); + LOG.info("Test Failed for test {}: ", context.getDisplayName()); testResultsStatus.add(TestResultStatus.FAILED); } diff --git a/testing-modules/junit-5-basics/src/test/java/com/baeldung/migration/junit4/BeforeAndAfterAnnotationsUnitTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/migration/junit4/BeforeAndAfterAnnotationsUnitTest.java index fac07a20ef..6022de123f 100644 --- a/testing-modules/junit-5-basics/src/test/java/com/baeldung/migration/junit4/BeforeAndAfterAnnotationsUnitTest.java +++ b/testing-modules/junit-5-basics/src/test/java/com/baeldung/migration/junit4/BeforeAndAfterAnnotationsUnitTest.java @@ -28,8 +28,8 @@ public class BeforeAndAfterAnnotationsUnitTest { } @After - public void finalize() { - LOG.info("finalize"); + public void teardown() { + LOG.info("teardown"); list.clear(); } diff --git a/testing-modules/junit-5-basics/src/test/java/com/baeldung/migration/junit5/BeforeEachAndAfterEachAnnotationsUnitTest.java b/testing-modules/junit-5-basics/src/test/java/com/baeldung/migration/junit5/BeforeEachAndAfterEachAnnotationsUnitTest.java index be916d66ea..f0093b3bf6 100644 --- a/testing-modules/junit-5-basics/src/test/java/com/baeldung/migration/junit5/BeforeEachAndAfterEachAnnotationsUnitTest.java +++ b/testing-modules/junit-5-basics/src/test/java/com/baeldung/migration/junit5/BeforeEachAndAfterEachAnnotationsUnitTest.java @@ -28,8 +28,8 @@ public class BeforeEachAndAfterEachAnnotationsUnitTest { } @AfterEach - public void finalize() { - LOG.info("finalize"); + public void teardown() { + LOG.info("teardown"); list.clear(); } diff --git a/testing-modules/junit-5/README.md b/testing-modules/junit-5/README.md index e62f2dd345..984b79c29d 100644 --- a/testing-modules/junit-5/README.md +++ b/testing-modules/junit-5/README.md @@ -7,3 +7,4 @@ - [Testing an Abstract Class With JUnit](https://www.baeldung.com/junit-test-abstract-class) - [Guide to Dynamic Tests in JUnit 5](https://www.baeldung.com/junit5-dynamic-tests) - [Determine the Execution Time of JUnit Tests](https://www.baeldung.com/junit-test-execution-time) +- [@BeforeAll and @AfterAll in Non-Static Methods](https://www.baeldung.com/java-beforeall-afterall-non-static) diff --git a/testing-modules/junit5-annotations/pom.xml b/testing-modules/junit5-annotations/pom.xml index 9e51d0ab55..7ffc17c69b 100644 --- a/testing-modules/junit5-annotations/pom.xml +++ b/testing-modules/junit5-annotations/pom.xml @@ -55,8 +55,8 @@
- 5.6.2 - 1.6.0 + 5.7.0 + 1.7.0 2.8.2 3.11.1 diff --git a/testing-modules/load-testing-comparison/pom.xml b/testing-modules/load-testing-comparison/pom.xml index 1143ecb9ac..4c237aeb75 100644 --- a/testing-modules/load-testing-comparison/pom.xml +++ b/testing-modules/load-testing-comparison/pom.xml @@ -37,7 +37,6 @@ com.fasterxml.jackson.core jackson-databind - ${jackson.version} org.springframework.boot @@ -55,11 +54,6 @@ com.h2database h2 - - org.projectlombok - lombok - compile - @@ -77,7 +71,6 @@ org.springframework.boot spring-boot-maven-plugin - 2.0.5.RELEASE @@ -122,10 +115,10 @@ 1.8 1.8 UTF-8 - 2.11.12 - 2.2.5 - 3.2.2 - 2.2.1 + 2.12.12 + 3.4.0 + 4.4.0 + 3.1.0 5.0 diff --git a/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/TransactionController.java b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/TransactionController.java deleted file mode 100644 index 2ea2c06a41..0000000000 --- a/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/TransactionController.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.baeldung.loadtesting; - -import com.baeldung.loadtesting.model.Transaction; -import com.baeldung.loadtesting.repository.TransactionRepository; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - -@RestController -@Deprecated -public class TransactionController { - - @Autowired - private TransactionRepository transactionRepository; - - @PostMapping(path="/addTransaction") - public @ResponseBody - String saveTransactions(@RequestBody Transaction trnsctn){ - transactionRepository.save(trnsctn); - return "Saved Transaction."; - } - - @GetMapping(path="/findAll/{rewardId}") - public @ResponseBody Iterable getTransactions(@RequestParam Integer id){ - return transactionRepository.findByCustomerRewardsId(id); - } -} diff --git a/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/model/CustomerRewardsAccount.java b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/model/CustomerRewardsAccount.java index 2c6742fbaf..4d92c93fcb 100644 --- a/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/model/CustomerRewardsAccount.java +++ b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/model/CustomerRewardsAccount.java @@ -4,11 +4,11 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; - -import lombok.Data; +import javax.persistence.Index; +import javax.persistence.Table; @Entity -@Data +@Table(indexes = {@Index(columnList="customerId")}) public class CustomerRewardsAccount { @Id @@ -19,4 +19,18 @@ public class CustomerRewardsAccount { public Integer getCustomerId(){ return this.customerId; } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public void setCustomerId(Integer customerId) { + this.customerId = customerId; + } + + } diff --git a/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/model/Transaction.java b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/model/Transaction.java index 312f52f4ab..6e2fb39cc6 100644 --- a/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/model/Transaction.java +++ b/testing-modules/load-testing-comparison/src/main/java/com/baeldung/loadtesting/model/Transaction.java @@ -1,16 +1,17 @@ package com.baeldung.loadtesting.model; -import lombok.Data; - import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.Index; +import javax.persistence.Table; + import java.util.Date; import java.util.Calendar; @Entity -@Data +@Table(indexes = {@Index(columnList="customerRewardsId")}) public class Transaction { @Id @@ -27,4 +28,34 @@ public class Transaction { public void setTransactionDate(Date transactionDate){ this.transactionDate = transactionDate; } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getCustomerRewardsId() { + return customerRewardsId; + } + + public void setCustomerRewardsId(Integer customerRewardsId) { + this.customerRewardsId = customerRewardsId; + } + + public Integer getCustomerId() { + return customerId; + } + + public void setCustomerId(Integer customerId) { + this.customerId = customerId; + } + + public Date getTransactionDate() { + return transactionDate; + } + + } diff --git a/testing-modules/load-testing-comparison/src/main/resources/application.properties b/testing-modules/load-testing-comparison/src/main/resources/application.properties new file mode 100644 index 0000000000..e2c8cb1879 --- /dev/null +++ b/testing-modules/load-testing-comparison/src/main/resources/application.properties @@ -0,0 +1,7 @@ +spring.h2.console.enabled=true +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password= +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect + diff --git a/testing-modules/load-testing-comparison/src/main/resources/scripts/Gatling/GatlingScenario.scala b/testing-modules/load-testing-comparison/src/main/resources/scripts/Gatling/GatlingScenario.scala index f9b3837759..e8cc608e42 100644 --- a/testing-modules/load-testing-comparison/src/main/resources/scripts/Gatling/GatlingScenario.scala +++ b/testing-modules/load-testing-comparison/src/main/resources/scripts/Gatling/GatlingScenario.scala @@ -7,46 +7,41 @@ import scala.concurrent.duration._ class RewardsScenario extends Simulation { - def randCustId() = Random.nextInt(99) + def randCustId() = java.util.concurrent.ThreadLocalRandom.current().nextInt() val httpProtocol = http.baseUrl("http://localhost:8080") - .acceptHeader("text/html,application/json;q=0.9,*/*;q=0.8") - .doNotTrackHeader("1") - .acceptLanguageHeader("en-US,en;q=0.5") - .acceptEncodingHeader("gzip, deflate") - .userAgentHeader("Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0") val scn = scenario("RewardsScenario") - .repeat(10){ + .repeat(1000){ + exec(http("transactions_add") .post("/transactions/add/") - .body(StringBody("""{ "customerRewardsId":null,"customerId":""""+ randCustId() + """","transactionDate":null }""")).asJson + .body(StringBody(_ => s"""{"customerRewardsId":null,"customerId":${randCustId()},"transactionDate":null}""")).asJson .check(jsonPath("$.id").saveAs("txnId")) .check(jsonPath("$.transactionDate").saveAs("txtDate")) .check(jsonPath("$.customerId").saveAs("custId"))) - .pause(1) .exec(http("get_reward") .get("/rewards/find/${custId}") - .check(jsonPath("$.id").saveAs("rwdId"))) - .pause(1) + .check(jsonPath("$.id").optional.saveAs("rwdId"))) .doIf("${rwdId.isUndefined()}"){ exec(http("rewards_add") .post("/rewards/add") - .body(StringBody("""{ "customerId": "${custId}" }""")).asJson + .body(StringBody("""{"customerId":${custId}}""")).asJson .check(jsonPath("$.id").saveAs("rwdId"))) } - .exec(http("transactions_add") + .exec(http("transactions_update") .post("/transactions/add/") - .body(StringBody("""{ "customerRewardsId":"${rwdId}","customerId":"${custId}","transactionDate":"${txtDate}" }""")).asJson) - .pause(1) + .body(StringBody("""{"customerRewardsId":${rwdId},"customerId":${custId},"transactionDate":"${txtDate}" }""")).asJson) - .exec(http("get_reward") + .exec(http("get_transactions") .get("/transactions/findAll/${rwdId}")) + + .exec(_.removeAll("txnId", "txtDate", "custId", "rwdId")) } setUp( scn.inject(atOnceUsers(100)) ).protocols(httpProtocol) -} \ No newline at end of file +} diff --git a/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx b/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx index 97640dfac7..cbb036b77b 100644 --- a/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx +++ b/testing-modules/load-testing-comparison/src/main/resources/scripts/JMeter/Test Plan.jmx @@ -16,7 +16,7 @@ continue false - 10 + 1000 100 0 @@ -200,7 +200,7 @@ - 10000 + 9223372036854775806 1 false diff --git a/testing-modules/load-testing-comparison/src/main/resources/scripts/The Grinder/grinder.properties b/testing-modules/load-testing-comparison/src/main/resources/scripts/The Grinder/grinder.properties index 68adf90856..ca5969cb7a 100644 --- a/testing-modules/load-testing-comparison/src/main/resources/scripts/The Grinder/grinder.properties +++ b/testing-modules/load-testing-comparison/src/main/resources/scripts/The Grinder/grinder.properties @@ -1,5 +1,5 @@ grinder.script = grinder.py grinder.threads = 100 grinder.processes = 1 -grinder.runs = 10 +grinder.runs = 1000 grinder.logDirectory = /logs diff --git a/testing-modules/load-testing-comparison/src/main/resources/scripts/The Grinder/grinder.py b/testing-modules/load-testing-comparison/src/main/resources/scripts/The Grinder/grinder.py index 025f90d38b..a71f101b41 100644 --- a/testing-modules/load-testing-comparison/src/main/resources/scripts/The Grinder/grinder.py +++ b/testing-modules/load-testing-comparison/src/main/resources/scripts/The Grinder/grinder.py @@ -24,6 +24,7 @@ random=java.util.Random() class TestRunner: def __call__(self): + customerId = str(random.nextInt()); result = request1.POST("http://localhost:8080/transactions/add", "{"'"customerRewardsId"'":null,"'"customerId"'":"+ customerId + ","'"transactionDate"'":null}") @@ -37,4 +38,5 @@ class TestRunner: rwdId = parseJsonString(result.getText(), "id") result = request1.POST("http://localhost:8080/transactions/add", "{"'"id"'":" + txnId + ","'"customerRewardsId"'":" + rwdId + ","'"customerId"'":"+ customerId + ","'"transactionDate"'":null}") - result = request1.GET("http://localhost:8080/transactions/findAll/" + rwdId) \ No newline at end of file + result = request1.GET("http://localhost:8080/transactions/findAll/" + rwdId) + diff --git a/testing-modules/mockito-2/README.md b/testing-modules/mockito-2/README.md index c7b62182b5..4bd2ff9759 100644 --- a/testing-modules/mockito-2/README.md +++ b/testing-modules/mockito-2/README.md @@ -9,3 +9,4 @@ - [Mockito – Using Spies](https://www.baeldung.com/mockito-spy) - [Using Mockito ArgumentCaptor](https://www.baeldung.com/mockito-argumentcaptor) - [Difference Between when() and doXxx() Methods in Mockito](https://www.baeldung.com/java-mockito-when-vs-do) +- [Overview of Mockito MockSettings](https://www.baeldung.com/mockito-mocksettings) diff --git a/testing-modules/mockito-2/pom.xml b/testing-modules/mockito-2/pom.xml index 340af89c82..055debe615 100644 --- a/testing-modules/mockito-2/pom.xml +++ b/testing-modules/mockito-2/pom.xml @@ -30,7 +30,6 @@ 2.21.0 - 2.10.3 diff --git a/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/mocksettings/AbstractCoffee.java b/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/mocksettings/AbstractCoffee.java new file mode 100644 index 0000000000..99fd686951 --- /dev/null +++ b/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/mocksettings/AbstractCoffee.java @@ -0,0 +1,15 @@ +package com.baeldung.mockito.mocksettings; + +public abstract class AbstractCoffee { + + protected String name; + + protected AbstractCoffee(String name) { + this.name = name; + } + + protected String getName() { + return name; + } + +} diff --git a/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/mocksettings/SimpleService.java b/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/mocksettings/SimpleService.java new file mode 100644 index 0000000000..034517acbf --- /dev/null +++ b/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/mocksettings/SimpleService.java @@ -0,0 +1,10 @@ +package com.baeldung.mockito.mocksettings; + +public class SimpleService { + + public SimpleService(SpecialInterface special) { + Runnable runnable = (Runnable) special; + runnable.run(); + } + +} diff --git a/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/mocksettings/SpecialInterface.java b/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/mocksettings/SpecialInterface.java new file mode 100644 index 0000000000..e5f88247d6 --- /dev/null +++ b/testing-modules/mockito-2/src/main/java/com/baeldung/mockito/mocksettings/SpecialInterface.java @@ -0,0 +1,5 @@ +package com.baeldung.mockito.mocksettings; + +public interface SpecialInterface { + +} diff --git a/testing-modules/mockito-2/src/test/java/com/baeldung/mockito/mocksettings/MockSettingsUnitTest.java b/testing-modules/mockito-2/src/test/java/com/baeldung/mockito/mocksettings/MockSettingsUnitTest.java new file mode 100644 index 0000000000..907abc3d76 --- /dev/null +++ b/testing-modules/mockito-2/src/test/java/com/baeldung/mockito/mocksettings/MockSettingsUnitTest.java @@ -0,0 +1,56 @@ +package com.baeldung.mockito.mocksettings; + +import static org.mockito.Answers.RETURNS_SMART_NULLS; +import static org.junit.Assert.assertEquals; +import static org.mockito.Answers.CALLS_REAL_METHODS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.exceptions.verification.SmartNullPointerException; +import org.mockito.junit.MockitoJUnitRunner; + +import com.baeldung.mockito.fluentapi.Pizza; +import com.baeldung.mockito.fluentapi.PizzaService; + +@RunWith(MockitoJUnitRunner.class) +public class MockSettingsUnitTest { + + @Test(expected = SmartNullPointerException.class) + public void whenServiceMockedWithSmartNulls_thenExceptionHasExtraInfo() { + PizzaService service = mock(PizzaService.class, withSettings().defaultAnswer(RETURNS_SMART_NULLS)); + Pizza pizza = service.orderHouseSpecial(); + pizza.getSize(); + } + + @Test + public void whenServiceMockedWithNameAndVerboseLogging_thenLogsMethodInvocations() { + PizzaService service = mock(PizzaService.class, withSettings().name("pizzaServiceMock") + .verboseLogging()); + + Pizza pizza = mock(Pizza.class); + when(service.orderHouseSpecial()).thenReturn(pizza); + + service.orderHouseSpecial(); + + verify(service).orderHouseSpecial(); + } + + @Test + public void whenServiceMockedWithExtraInterfaces_thenConstructorSuccess() { + SpecialInterface specialMock = mock(SpecialInterface.class, withSettings().extraInterfaces(Runnable.class)); + new SimpleService(specialMock); + } + + @Test + public void whenMockSetupWithConstructor_thenConstructorIsInvoked() { + AbstractCoffee coffeeSpy = mock(AbstractCoffee.class, withSettings().useConstructor("espresso") + .defaultAnswer(CALLS_REAL_METHODS)); + + assertEquals("Coffee name: ", "espresso", coffeeSpy.getName()); + } + +} diff --git a/testing-modules/rest-testing/pom.xml b/testing-modules/rest-testing/pom.xml index 1e8a27afa5..b3966c1b6a 100644 --- a/testing-modules/rest-testing/pom.xml +++ b/testing-modules/rest-testing/pom.xml @@ -65,13 +65,13 @@ - info.cukes + io.cucumber cucumber-java ${cucumber.version} test - info.cukes + io.cucumber cucumber-junit ${cucumber.version} @@ -105,56 +105,44 @@ true - - - - maven-failsafe-plugin - ${maven-failsafe-plugin.version} - - classes - 4 - - - - - integration-test - verify - - - - - - com.github.temyers - cucumber-jvm-parallel-plugin - 5.0.0 - - - generateRunners - generate-test-sources - - generateRunners - - - - com.baeldung.rest.cucumber - - src/test/resources/Feature/ - SCENARIO - - - - - - + + + parallel + + + + maven-failsafe-plugin + ${maven-failsafe-plugin.version} + + + CucumberIntegrationTest.java + + methods + 2 + + + + + integration-test + verify + + + + + + + + + 19.0 2.9.0 - 1.2.5 + 6.8.0 2.21.0 0.6.1 diff --git a/testing-modules/rest-testing/src/main/resources/karate/cucumber.feature b/testing-modules/rest-testing/src/main/resources/karate/cucumber.feature deleted file mode 100644 index 99dd8249fe..0000000000 --- a/testing-modules/rest-testing/src/main/resources/karate/cucumber.feature +++ /dev/null @@ -1,10 +0,0 @@ -Feature: Testing a REST API - Users should be able to submit GET and POST requests to a web service, represented by WireMock - - Scenario: Data Upload to a web service - When users upload data on a project - Then the server should handle it and return a success status - - Scenario: Data retrieval from a web service - When users want to get information on the Cucumber project - Then the requested data is returned \ No newline at end of file diff --git a/testing-modules/rest-testing/src/test/java/com/baeldung/rest/cucumber/CucumberIntegrationTest.java b/testing-modules/rest-testing/src/test/java/com/baeldung/rest/cucumber/CucumberIntegrationTest.java index f80178a43d..33e2c62301 100644 --- a/testing-modules/rest-testing/src/test/java/com/baeldung/rest/cucumber/CucumberIntegrationTest.java +++ b/testing-modules/rest-testing/src/test/java/com/baeldung/rest/cucumber/CucumberIntegrationTest.java @@ -1,8 +1,8 @@ package com.baeldung.rest.cucumber; +import io.cucumber.junit.Cucumber; +import io.cucumber.junit.CucumberOptions; import org.junit.runner.RunWith; -import cucumber.api.CucumberOptions; -import cucumber.api.junit.Cucumber; @RunWith(Cucumber.class) @CucumberOptions(features = "classpath:Feature") diff --git a/testing-modules/rest-testing/src/test/java/com/baeldung/rest/cucumber/StepDefinition.java b/testing-modules/rest-testing/src/test/java/com/baeldung/rest/cucumber/StepDefinition.java index 35a913ae25..f1fcb48f01 100644 --- a/testing-modules/rest-testing/src/test/java/com/baeldung/rest/cucumber/StepDefinition.java +++ b/testing-modules/rest-testing/src/test/java/com/baeldung/rest/cucumber/StepDefinition.java @@ -20,6 +20,8 @@ import java.io.IOException; import java.io.InputStream; import java.util.Scanner; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; @@ -29,8 +31,6 @@ import org.apache.http.impl.client.HttpClients; import com.github.tomakehurst.wiremock.WireMockServer; -import cucumber.api.java.en.Then; -import cucumber.api.java.en.When; public class StepDefinition { @@ -66,7 +66,8 @@ public class StepDefinition { wireMockServer.stop(); } - @When("^users want to get information on the (.+) project$") +// @When("^users want to get information on the '(.+)' project$") + @When("users want to get information on the {string} project") public void usersGetInformationOnAProject(String projectName) throws IOException { wireMockServer.start(); @@ -86,11 +87,11 @@ public class StepDefinition { wireMockServer.stop(); } - @Then("^the server should handle it and return a success status$") + @Then("the server should handle it and return a success status") public void theServerShouldReturnASuccessStatus() { } - @Then("^the requested data is returned$") + @Then("the requested data is returned") public void theRequestedDataIsReturned() { } diff --git a/testing-modules/rest-testing/src/test/resources/Feature/cucumber.feature b/testing-modules/rest-testing/src/test/resources/Feature/cucumber.feature index 99dd8249fe..f8bbd809de 100644 --- a/testing-modules/rest-testing/src/test/resources/Feature/cucumber.feature +++ b/testing-modules/rest-testing/src/test/resources/Feature/cucumber.feature @@ -6,5 +6,5 @@ Feature: Testing a REST API Then the server should handle it and return a success status Scenario: Data retrieval from a web service - When users want to get information on the Cucumber project + When users want to get information on the 'Cucumber' project Then the requested data is returned \ No newline at end of file diff --git a/testing-modules/spring-testing-2/README.md b/testing-modules/spring-testing-2/README.md index 702a02ff27..16b47adeac 100644 --- a/testing-modules/spring-testing-2/README.md +++ b/testing-modules/spring-testing-2/README.md @@ -1,3 +1,5 @@ ## Relevant Articles: - [Guide to @DynamicPropertySource in Spring](https://www.baeldung.com/spring-dynamicpropertysource) +- [Concurrent Test Execution in Spring 5](https://www.baeldung.com/spring-5-concurrent-tests) +- [Spring 5 Testing with @EnabledIf Annotation](https://www.baeldung.com/spring-5-enabledIf) diff --git a/testing-modules/spring-testing-2/pom.xml b/testing-modules/spring-testing-2/pom.xml index 807b84c676..4686a20202 100644 --- a/testing-modules/spring-testing-2/pom.xml +++ b/testing-modules/spring-testing-2/pom.xml @@ -54,8 +54,25 @@ + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + methods + true + + + + 1.12.2 + 2.21.0 \ No newline at end of file diff --git a/spring-5/src/test/java/com/baeldung/Spring5JUnit4ConcurrentIntegrationTest.java b/testing-modules/spring-testing-2/src/test/java/com/baeldung/concurrent/Spring5JUnit4ConcurrentIntegrationTest.java similarity index 98% rename from spring-5/src/test/java/com/baeldung/Spring5JUnit4ConcurrentIntegrationTest.java rename to testing-modules/spring-testing-2/src/test/java/com/baeldung/concurrent/Spring5JUnit4ConcurrentIntegrationTest.java index 7e494465b2..8a0947ba44 100644 --- a/spring-5/src/test/java/com/baeldung/Spring5JUnit4ConcurrentIntegrationTest.java +++ b/testing-modules/spring-testing-2/src/test/java/com/baeldung/concurrent/Spring5JUnit4ConcurrentIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung; +package com.baeldung.concurrent; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/spring-5/src/test/java/com/baeldung/jupiter/EnabledOnJava8.java b/testing-modules/spring-testing-2/src/test/java/com/baeldung/enabledif/EnabledOnJava8.java similarity index 93% rename from spring-5/src/test/java/com/baeldung/jupiter/EnabledOnJava8.java rename to testing-modules/spring-testing-2/src/test/java/com/baeldung/enabledif/EnabledOnJava8.java index c6d3b7ff10..01bdc176e0 100644 --- a/spring-5/src/test/java/com/baeldung/jupiter/EnabledOnJava8.java +++ b/testing-modules/spring-testing-2/src/test/java/com/baeldung/enabledif/EnabledOnJava8.java @@ -1,4 +1,4 @@ -package com.baeldung.jupiter; +package com.baeldung.enabledif; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5EnabledAnnotationIntegrationTest.java b/testing-modules/spring-testing-2/src/test/java/com/baeldung/enabledif/Spring5EnabledAnnotationIntegrationTest.java similarity index 97% rename from spring-5/src/test/java/com/baeldung/jupiter/Spring5EnabledAnnotationIntegrationTest.java rename to testing-modules/spring-testing-2/src/test/java/com/baeldung/enabledif/Spring5EnabledAnnotationIntegrationTest.java index 35363e0ea3..b6ccb2204b 100644 --- a/spring-5/src/test/java/com/baeldung/jupiter/Spring5EnabledAnnotationIntegrationTest.java +++ b/testing-modules/spring-testing-2/src/test/java/com/baeldung/enabledif/Spring5EnabledAnnotationIntegrationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.jupiter; +package com.baeldung.enabledif; import static org.junit.jupiter.api.Assertions.assertTrue; diff --git a/testing-modules/spring-testing/pom.xml b/testing-modules/spring-testing/pom.xml index c5e94f3afc..9e0c986bb2 100644 --- a/testing-modules/spring-testing/pom.xml +++ b/testing-modules/spring-testing/pom.xml @@ -3,16 +3,15 @@ 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 - com.baeldung spring-testing 0.1-SNAPSHOT spring-testing com.baeldung - parent-java + parent-boot-2 0.0.1-SNAPSHOT - ../../parent-java + ../../parent-boot-2 @@ -32,25 +31,34 @@ org.springframework.boot spring-boot-starter - LATEST org.springframework.boot spring-boot-starter-test - LATEST test + + org.junit.vintage + junit-vintage-engine + test + + + org.hamcrest + hamcrest-core + + + org.springframework spring-core - LATEST + ${spring.version} org.springframework spring-context - LATEST + ${spring.version} org.springframework @@ -65,7 +73,6 @@ org.springframework.data spring-data-jpa - LATEST org.junit.jupiter @@ -116,9 +123,9 @@ 2.0.0.0 3.1.6 - 5.5.0 - 1.5.2 - 5.1.4.RELEASE + 5.7.0 + 1.7.0 + 5.3.0 4.0.1 2.1.1 diff --git a/testing-modules/testing-libraries-2/README.md b/testing-modules/testing-libraries-2/README.md index 3325600b5e..f8361904b8 100644 --- a/testing-modules/testing-libraries-2/README.md +++ b/testing-modules/testing-libraries-2/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Guide to the System Rules Library](https://www.baeldung.com/java-system-rules-junit) +- [Guide to the System Stubs Library](https://www.baeldung.com/java-system-stubs) diff --git a/testing-modules/testing-libraries-2/pom.xml b/testing-modules/testing-libraries-2/pom.xml index 282583c882..42c84d0da9 100644 --- a/testing-modules/testing-libraries-2/pom.xml +++ b/testing-modules/testing-libraries-2/pom.xml @@ -9,9 +9,16 @@ com.baeldung testing-modules 1.0.0-SNAPSHOT + ../ + + org.assertj + assertj-core + 3.16.1 + test + com.github.stefanbirkner system-rules @@ -24,6 +31,44 @@ ${system-lambda.version} test + + uk.org.webcompere + system-stubs-jupiter + ${system-stubs.version} + test + + + uk.org.webcompere + system-stubs-junit4 + ${system-stubs.version} + test + + + + + org.junit.jupiter + junit-jupiter + ${junit.jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-engine + ${junit.jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-params + ${junit.jupiter.version} + test + + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.version} + test + @@ -39,5 +84,7 @@ 1.19.0 1.0.0 + 1.1.0 + 5.6.2 diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/FakeDatabaseJUnit5UnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/FakeDatabaseJUnit5UnitTest.java new file mode 100644 index 0000000000..cb9371bd69 --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/FakeDatabaseJUnit5UnitTest.java @@ -0,0 +1,16 @@ +package com.baeldung.systemstubs; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(SystemStubsExtension.class) +class FakeDatabaseJUnit5UnitTest { + + @Test + void useFakeDatabase(FakeDatabaseTestResource fakeDatabase) { + assertThat(fakeDatabase.getDatabaseConnection()).isEqualTo("open"); + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/FakeDatabaseTestResource.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/FakeDatabaseTestResource.java new file mode 100644 index 0000000000..6cb1b1d607 --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/FakeDatabaseTestResource.java @@ -0,0 +1,22 @@ +package com.baeldung.systemstubs; + +import uk.org.webcompere.systemstubs.resource.TestResource; + +public class FakeDatabaseTestResource implements TestResource { + // let's pretend this is a database connection + private String databaseConnection = "closed"; + + @Override + public void setup() throws Exception { + databaseConnection = "open"; + } + + @Override + public void teardown() throws Exception { + databaseConnection = "closed"; + } + + public String getDatabaseConnection() { + return databaseConnection; + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/FakeDatabaseTestResourceUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/FakeDatabaseTestResourceUnitTest.java new file mode 100644 index 0000000000..6b8fdcecdd --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/FakeDatabaseTestResourceUnitTest.java @@ -0,0 +1,21 @@ +package com.baeldung.systemstubs; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class FakeDatabaseTestResourceUnitTest { + @Nested + class ExecuteAround { + @Test + void theResourceIsClosedToStartWith() throws Exception { + FakeDatabaseTestResource fake = new FakeDatabaseTestResource(); + assertThat(fake.getDatabaseConnection()).isEqualTo("closed"); + + fake.execute(() -> { + assertThat(fake.getDatabaseConnection()).isEqualTo("open"); + }); + } + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/GettingStartedWithSystemStubsJUnit4UnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/GettingStartedWithSystemStubsJUnit4UnitTest.java new file mode 100644 index 0000000000..6eaffac7ed --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/GettingStartedWithSystemStubsJUnit4UnitTest.java @@ -0,0 +1,58 @@ +package com.baeldung.systemstubs; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.runners.Enclosed; +import org.junit.runner.RunWith; +import uk.org.webcompere.systemstubs.rules.EnvironmentVariablesRule; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(Enclosed.class) +public class GettingStartedWithSystemStubsJUnit4UnitTest { + public static class SetEnvironmentInsideTest { + @Rule + public EnvironmentVariablesRule environmentVariablesRule = new EnvironmentVariablesRule(); + + @Test + public void givenEnvironmentCanBeModified_whenSetEnvironment_thenItIsSet() { + environmentVariablesRule.set("ENV", "value1"); + + assertThat(System.getenv("ENV")).isEqualTo("value1"); + } + } + + public static class SetEnvironmentAtConstruction { + @Rule + public EnvironmentVariablesRule environmentVariablesRule = + new EnvironmentVariablesRule("ENV", "value1", + "ENV2", "value2"); + + + @Test + public void givenEnvironmentCanBeModified_whenSetEnvironment_thenItIsSet() { + assertThat(System.getenv("ENV")).isEqualTo("value1"); + assertThat(System.getenv("ENV2")).isEqualTo("value2"); + } + } + + public static class SetEnvironmentInBefore { + @Rule + public EnvironmentVariablesRule environmentVariablesRule = + new EnvironmentVariablesRule(); + + @Before + public void before() { + environmentVariablesRule.set("ENV", "value1") + .set("ENV2", "value2"); + } + + + @Test + public void givenEnvironmentCanBeModified_whenSetEnvironment_thenItIsSet() { + assertThat(System.getenv("ENV")).isEqualTo("value1"); + assertThat(System.getenv("ENV2")).isEqualTo("value2"); + } + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/GettingStartedWithSystemStubsUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/GettingStartedWithSystemStubsUnitTest.java new file mode 100644 index 0000000000..76fb768d34 --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/GettingStartedWithSystemStubsUnitTest.java @@ -0,0 +1,109 @@ +package com.baeldung.systemstubs; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import uk.org.webcompere.systemstubs.environment.EnvironmentVariables; +import uk.org.webcompere.systemstubs.jupiter.SystemStub; +import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; +import uk.org.webcompere.systemstubs.properties.SystemProperties; + +import static org.assertj.core.api.Assertions.assertThat; +import static uk.org.webcompere.systemstubs.SystemStubs.withEnvironmentVariable; +import static uk.org.webcompere.systemstubs.resource.Resources.with; + +class GettingStartedWithSystemStubsUnitTest { + @Nested + @ExtendWith(SystemStubsExtension.class) + class EnvironmentVariablesJUnit5 { + @SystemStub + private EnvironmentVariables environmentVariables; + + @Test + void givenEnvironmentCanBeModified_whenSetEnvironment_thenItIsSet() { + environmentVariables.set("ENV", "value1"); + + assertThat(System.getenv("ENV")).isEqualTo("value1"); + } + } + + @Nested + @ExtendWith(SystemStubsExtension.class) + class EnvironmentVariablesConstructedJUnit5 { + @SystemStub + private EnvironmentVariables environmentVariables = + new EnvironmentVariables("ENV", "value1"); + + @Test + void givenEnvironmentCanBeModified_whenSetEnvironment_thenItIsSet() { + assertThat(System.getenv("ENV")).isEqualTo("value1"); + } + } + + @Nested + @ExtendWith(SystemStubsExtension.class) + class EnvironmentVariablesConstructedWithSetJUnit5 { + @SystemStub + private EnvironmentVariables environmentVariables = + new EnvironmentVariables() + .set("ENV", "value1") + .set("ENV2", "value2"); + + @Test + void givenEnvironmentCanBeModified_whenSetEnvironment_thenItIsSet() { + assertThat(System.getenv("ENV")).isEqualTo("value1"); + } + } + + @Nested + @ExtendWith(SystemStubsExtension.class) + class EnvironmentVariablesJUnit5ParameterInjection { + @Test + void givenEnvironmentCanBeModified_whenSetEnvironment_thenItIsSet(EnvironmentVariables environmentVariables) { + environmentVariables.set("ENV", "value1"); + + assertThat(System.getenv("ENV")).isEqualTo("value1"); + } + } + + @Nested + class EnvironmentVariablesExecuteAround { + @Test + void givenSetupUsingWithEnvironmentVariable_thenItIsSet() throws Exception { + withEnvironmentVariable("ENV3", "val") + .execute(() -> { + assertThat(System.getenv("ENV3")).isEqualTo("val"); + }); + } + + @Test + void givenSetupUsingConstructor_thenItIsSet() throws Exception { + EnvironmentVariables environment = new EnvironmentVariables() + .set("ENV3", "val"); + environment.execute(() -> { + assertThat(System.getenv("ENV3")).isEqualTo("val"); + }); + } + + @Test + void givenEnvironment_thenCanReturnValue() throws Exception { + String extracted = new EnvironmentVariables("PROXY", "none") + .execute(() -> System.getenv("PROXY")); + + assertThat(extracted).isEqualTo("none"); + } + } + + @Nested + class RunMultiple { + @Test + void runMultiple() throws Exception { + with(new EnvironmentVariables("FOO", "bar"), + new SystemProperties("prop", "val")) + .execute(() -> { + assertThat(System.getenv("FOO")).isEqualTo("bar"); + assertThat(System.getProperty("prop")).isEqualTo("val"); + }); + } + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/JUnit4SystemPropertiesUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/JUnit4SystemPropertiesUnitTest.java new file mode 100644 index 0000000000..111baf9e9c --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/JUnit4SystemPropertiesUnitTest.java @@ -0,0 +1,42 @@ +package com.baeldung.systemstubs; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import uk.org.webcompere.systemstubs.rules.SystemPropertiesRule; + +import static org.assertj.core.api.Assertions.assertThat; + +public class JUnit4SystemPropertiesUnitTest { + @Rule + public SystemPropertiesRule systemProperties = + new SystemPropertiesRule("db.connection", "false"); + + @Before + public void before() { + systemProperties.set("before.prop", "before"); + } + + @Test + public void givenPropertyIsSet_thenCanBeUsedInTest() { + assertThat(System.getProperty("db.connection")).isEqualTo("false"); + } + + @Test + public void givenPropertyIsSet_thenAnotherCanBeSetAndBeUsedInTest() { + assertThat(System.getProperty("db.connection")).isEqualTo("false"); + + systemProperties.set("prop2", "true"); + assertThat(System.getProperty("prop2")).isEqualTo("true"); + } + + @Test + public void givenPropertySetInBefore_thenCanBeSeenInTest() { + assertThat(System.getProperty("before.prop")).isEqualTo("before"); + } + + @Test + public void givenPropertySetEarlier_thenNotVisibleLater() { + assertThat(System.getProperty("prop2")).isNull(); + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/JUnit5SystemPropertiesUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/JUnit5SystemPropertiesUnitTest.java new file mode 100644 index 0000000000..7aaf4cebad --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/JUnit5SystemPropertiesUnitTest.java @@ -0,0 +1,89 @@ +package com.baeldung.systemstubs; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import uk.org.webcompere.systemstubs.jupiter.SystemStub; +import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; +import uk.org.webcompere.systemstubs.properties.SystemProperties; +import uk.org.webcompere.systemstubs.resource.PropertySource; + +import static org.assertj.core.api.Assertions.assertThat; + +class JUnit5SystemPropertiesUnitTest { + + @ExtendWith(SystemStubsExtension.class) + @Nested + class RestoreSystemProperties { + @SystemStub + private SystemProperties systemProperties; + + @Test + void givenAPropertyIsSet_thenItIsOnlyAvailableInsideThisTest1() { + assertThat(System.getProperty("localProperty")).isNull(); + + System.setProperty("localProperty", "nonnull"); + assertThat(System.getProperty("localProperty")).isEqualTo("nonnull"); + } + + @Test + void givenAPropertyIsSet_thenItIsOnlyAvailableInsideThisTest2() { + assertThat(System.getProperty("localProperty")).isNull(); + + System.setProperty("localProperty", "true"); + assertThat(System.getProperty("localProperty")).isEqualTo("true"); + } + } + + @ExtendWith(SystemStubsExtension.class) + @Nested + class RestoreSystemPropertiesByParameter { + + @Test + void givenAPropertyIsSet_thenItIsOnlyAvailableInsideThisTest1(SystemProperties systemProperties) { + assertThat(System.getProperty("localProperty")).isNull(); + + System.setProperty("localProperty", "nonnull"); + assertThat(System.getProperty("localProperty")).isEqualTo("nonnull"); + } + + @Test + void givenAPropertyIsSet_thenItIsOnlyAvailableInsideThisTest2(SystemProperties systemProperties) { + assertThat(System.getProperty("localProperty")).isNull(); + + System.setProperty("localProperty", "true"); + assertThat(System.getProperty("localProperty")).isEqualTo("true"); + } + } + + @ExtendWith(SystemStubsExtension.class) + @Nested + class SetSomeSystemProperties { + @SystemStub + private SystemProperties systemProperties; + + @BeforeEach + void before() { + systemProperties.set("beforeProperty", "before"); + } + + @Test + void givenAPropertyIsSetInBefore_thenItIsAvailableInsideThisTest() { + assertThat(System.getProperty("beforeProperty")).isEqualTo("before"); + } + } + + @ExtendWith(SystemStubsExtension.class) + @Nested + class SetSomeSystemPropertiesFromResources { + @SystemStub + private SystemProperties systemProperties = + new SystemProperties(PropertySource.fromResource("test.properties")); + + @Test + void givenPropertiesReadFromResources_thenCanBeUsed() { + assertThat(System.getProperty("name")).isEqualTo("baeldung"); + } + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/OutputMutingJUnit4UnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/OutputMutingJUnit4UnitTest.java new file mode 100644 index 0000000000..a178efbb9d --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/OutputMutingJUnit4UnitTest.java @@ -0,0 +1,16 @@ +package com.baeldung.systemstubs; + +import org.junit.Rule; +import org.junit.Test; +import uk.org.webcompere.systemstubs.rules.SystemOutRule; +import uk.org.webcompere.systemstubs.stream.output.NoopStream; + +public class OutputMutingJUnit4UnitTest { + @Rule + public SystemOutRule systemOutRule = new SystemOutRule(new NoopStream()); + + @Test + public void givenMuteSystemOut() throws Exception { + System.out.println("nothing is output"); + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/OutputMutingUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/OutputMutingUnitTest.java new file mode 100644 index 0000000000..c75a523fff --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/OutputMutingUnitTest.java @@ -0,0 +1,35 @@ +package com.baeldung.systemstubs; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import uk.org.webcompere.systemstubs.jupiter.SystemStub; +import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; +import uk.org.webcompere.systemstubs.stream.SystemOut; +import uk.org.webcompere.systemstubs.stream.output.NoopStream; + +import static uk.org.webcompere.systemstubs.SystemStubs.muteSystemOut; + +class OutputMutingUnitTest { + @Nested + class MutingWithFacade { + @Test + void givenMuteSystemOut() throws Exception { + muteSystemOut(() -> { + System.out.println("nothing is output"); + }); + } + } + + @ExtendWith(SystemStubsExtension.class) + @Nested + class MutingWithJUnit5 { + @SystemStub + private SystemOut systemOut = new SystemOut(new NoopStream()); + + @Test + void givenMuteSystemOut() throws Exception { + System.out.println("nothing is output"); + } + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemExitExecuteAroundUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemExitExecuteAroundUnitTest.java new file mode 100644 index 0000000000..b42cc43307 --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemExitExecuteAroundUnitTest.java @@ -0,0 +1,17 @@ +package com.baeldung.systemstubs; + +import org.junit.jupiter.api.Test; + + +import static org.assertj.core.api.Assertions.assertThat; +import static uk.org.webcompere.systemstubs.SystemStubs.catchSystemExit; + +class SystemExitExecuteAroundUnitTest { + @Test + void canCheckExitCode() throws Exception { + int exitCode = catchSystemExit(() -> { + System.exit(123); + }); + assertThat(exitCode).isEqualTo(123); + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemExitJUnit4UnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemExitJUnit4UnitTest.java new file mode 100644 index 0000000000..c044e250dd --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemExitJUnit4UnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.systemstubs; + +import org.junit.Rule; +import org.junit.Test; +import uk.org.webcompere.systemstubs.rules.SystemExitRule; +import uk.org.webcompere.systemstubs.security.AbortExecutionException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class SystemExitJUnit4UnitTest { + @Rule + public SystemExitRule systemExitRule = new SystemExitRule(); + + @Test + public void whenAccidentalSystemExit_thenTestFailsRatherThanJVMKilled() { + // uncomment this to try it + //System.exit(1); + } + + @Test + public void whenExit_thenExitCodeIsAvailable() { + assertThatThrownBy(() -> { + System.exit(123); + }).isInstanceOf(AbortExecutionException.class); + + assertThat(systemExitRule.getExitCode()).isEqualTo(123); + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemExitJUnit5UnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemExitJUnit5UnitTest.java new file mode 100644 index 0000000000..4451d7e31f --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemExitJUnit5UnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.systemstubs; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import uk.org.webcompere.systemstubs.jupiter.SystemStub; +import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; +import uk.org.webcompere.systemstubs.security.AbortExecutionException; +import uk.org.webcompere.systemstubs.security.SystemExit; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@ExtendWith(SystemStubsExtension.class) +class SystemExitJUnit5UnitTest { + @SystemStub + private SystemExit systemExit; + + @Test + void whenExit_thenExitCodeIsAvailable() { + assertThatThrownBy(() -> { + System.exit(123); + }).isInstanceOf(AbortExecutionException.class); + + assertThat(systemExit.getExitCode()).isEqualTo(123); + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemInExecuteAroundUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemInExecuteAroundUnitTest.java new file mode 100644 index 0000000000..5a1d510e35 --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemInExecuteAroundUnitTest.java @@ -0,0 +1,20 @@ +package com.baeldung.systemstubs; + +import org.junit.jupiter.api.Test; + +import java.util.Scanner; + +import static org.assertj.core.api.Assertions.assertThat; +import static uk.org.webcompere.systemstubs.SystemStubs.withTextFromSystemIn; + +class SystemInExecuteAroundUnitTest { + + @Test + void givenTextInSystemIn_thenCanReadIt() throws Exception { + withTextFromSystemIn("line1", "line2", "line3") + .execute(() -> { + assertThat(new Scanner(System.in).nextLine()) + .isEqualTo("line1"); + }); + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemInJUnit4UnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemInJUnit4UnitTest.java new file mode 100644 index 0000000000..ccd422ea24 --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemInJUnit4UnitTest.java @@ -0,0 +1,21 @@ +package com.baeldung.systemstubs; + +import org.junit.Rule; +import org.junit.Test; +import uk.org.webcompere.systemstubs.rules.SystemInRule; + +import java.util.Scanner; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SystemInJUnit4UnitTest { + @Rule + public SystemInRule systemInRule = + new SystemInRule("line1", "line2", "line3"); + + @Test + public void givenInput_canReadFirstLine() { + assertThat(new Scanner(System.in).nextLine()) + .isEqualTo("line1"); + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemInJUnit5UnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemInJUnit5UnitTest.java new file mode 100644 index 0000000000..ed506eb40e --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemInJUnit5UnitTest.java @@ -0,0 +1,23 @@ +package com.baeldung.systemstubs; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import uk.org.webcompere.systemstubs.jupiter.SystemStub; +import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; +import uk.org.webcompere.systemstubs.stream.SystemIn; + +import java.util.Scanner; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(SystemStubsExtension.class) +class SystemInJUnit5UnitTest { + @SystemStub + private SystemIn systemIn = new SystemIn("line1", "line2", "line3"); + + @Test + void givenInput_canReadFirstLine() { + assertThat(new Scanner(System.in).nextLine()) + .isEqualTo("line1"); + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemLambdaComparisonUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemLambdaComparisonUnitTest.java new file mode 100644 index 0000000000..23e65767a8 --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemLambdaComparisonUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung.systemstubs; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import uk.org.webcompere.systemstubs.environment.EnvironmentVariables; +import uk.org.webcompere.systemstubs.jupiter.SystemStub; +import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; +import uk.org.webcompere.systemstubs.properties.SystemProperties; + +import static com.github.stefanbirkner.systemlambda.SystemLambda.restoreSystemProperties; +import static com.github.stefanbirkner.systemlambda.SystemLambda.withEnvironmentVariable; +import static org.junit.Assert.assertEquals; + +@ExtendWith(SystemStubsExtension.class) +class SystemLambdaComparisonUnitTest { + @SystemStub + private EnvironmentVariables environmentVariables = + new EnvironmentVariables("ADDRESS", "https://www.baeldung.com"); + + @SystemStub + private SystemProperties systemProperties = new SystemProperties(); + + @Test + void aSingleSystemLambda() throws Exception { + restoreSystemProperties(() -> { + System.setProperty("log_dir", "test/resources"); + assertEquals("test/resources", System.getProperty("log_dir")); + }); + } + + @Test + void multipleSystemLambdas() throws Exception { + restoreSystemProperties(() -> { + withEnvironmentVariable("URL", "https://www.baeldung.com") + .execute(() -> { + System.setProperty("log_dir", "test/resources"); + assertEquals("test/resources", System.getProperty("log_dir")); + assertEquals("https://www.baeldung.com", System.getenv("URL")); + }); + }); + } + + @Test + void multipleSystemStubs() { + System.setProperty("log_dir", "test/resources"); + assertEquals("test/resources", System.getProperty("log_dir")); + assertEquals("https://www.baeldung.com", System.getenv("ADDRESS")); + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemOutAndErrExecuteAroundUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemOutAndErrExecuteAroundUnitTest.java new file mode 100644 index 0000000000..36b127d3cb --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemOutAndErrExecuteAroundUnitTest.java @@ -0,0 +1,43 @@ +package com.baeldung.systemstubs; + +import org.junit.jupiter.api.Test; +import uk.org.webcompere.systemstubs.properties.SystemProperties; +import uk.org.webcompere.systemstubs.stream.SystemOut; +import uk.org.webcompere.systemstubs.stream.output.DisallowWriteStream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static uk.org.webcompere.systemstubs.SystemStubs.tapSystemOutNormalized; +import static uk.org.webcompere.systemstubs.resource.Resources.with; + +class SystemOutAndErrExecuteAroundUnitTest { + @Test + void givenTapOutput_thenGetOutput() throws Exception { + String output = tapSystemOutNormalized(() -> { + System.out.println("a"); + System.out.println("b"); + }); + + assertThat(output).isEqualTo("a\nb\n"); + } + + @Test + void givenCaptureOutputWithSystemOut_thenGetOutput() throws Exception { + SystemOut systemOut = new SystemOut(); + SystemProperties systemProperties = new SystemProperties("a", "!"); + with(systemOut, systemProperties) + .execute(() -> { + System.out.println("a: " + System.getProperty("a")); + }); + + assertThat(systemOut.getLines()).containsExactly("a: !"); + } + + @Test + void givenCannotWrite_thenWritingIsError() { + assertThatThrownBy(() -> { + new SystemOut(new DisallowWriteStream()) + .execute(() -> System.out.println("boo")); + }).isInstanceOf(AssertionError.class); + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemOutJUnit4UnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemOutJUnit4UnitTest.java new file mode 100644 index 0000000000..d6ff70a49b --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemOutJUnit4UnitTest.java @@ -0,0 +1,52 @@ +package com.baeldung.systemstubs; + +import org.junit.Rule; +import org.junit.Test; +import uk.org.webcompere.systemstubs.rules.SystemErrRule; +import uk.org.webcompere.systemstubs.rules.SystemOutRule; + +import static org.assertj.core.api.Assertions.assertThat; + +public class SystemOutJUnit4UnitTest { + @Rule + public SystemOutRule systemOutRule = new SystemOutRule(); + + @Rule + public SystemErrRule systemErrRule = new SystemErrRule(); + + @Test + public void whenCodeWritesToSystemOut_itCanBeRead() { + System.out.println("line1"); + System.out.println("line2"); + + assertThat(systemOutRule.getLines()) + .containsExactly("line1", "line2"); + } + + @Test + public void whenCodeWritesToSystemOut_itCanBeReadAsText() { + System.out.println("line1"); + System.out.println("line2"); + + assertThat(systemOutRule.getText()) + .startsWith("line1"); + } + + @Test + public void whenCodeWritesToSystemOut_itCanBeReadAsNormalizedLines() { + System.out.println("line1"); + System.out.println("line2"); + + assertThat(systemOutRule.getLinesNormalized()) + .isEqualTo("line1\nline2\n"); + } + + @Test + public void whenCodeWritesToSystemErr_itCanBeRead() { + System.err.println("line1"); + System.err.println("line2"); + + assertThat(systemErrRule.getLines()) + .containsExactly("line1", "line2"); + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemOutJUnit5UnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemOutJUnit5UnitTest.java new file mode 100644 index 0000000000..caa8a9264d --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemOutJUnit5UnitTest.java @@ -0,0 +1,28 @@ +package com.baeldung.systemstubs; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import uk.org.webcompere.systemstubs.jupiter.SystemStub; +import uk.org.webcompere.systemstubs.jupiter.SystemStubsExtension; +import uk.org.webcompere.systemstubs.stream.SystemErr; +import uk.org.webcompere.systemstubs.stream.SystemOut; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(SystemStubsExtension.class) +class SystemOutJUnit5UnitTest { + @SystemStub + private SystemOut systemOut; + + @SystemStub + private SystemErr systemErr; + + @Test + void whenWriteToOutput_thenItCanBeAsserted() { + System.out.println("to out"); + System.err.println("to err"); + + assertThat(systemOut.getLines()).containsExactly("to out"); + assertThat(systemErr.getLines()).containsExactly("to err"); + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemPropertiesExecuteAroundUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemPropertiesExecuteAroundUnitTest.java new file mode 100644 index 0000000000..3f0f780238 --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/SystemPropertiesExecuteAroundUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.systemstubs; + +import org.junit.jupiter.api.Test; +import uk.org.webcompere.systemstubs.properties.SystemProperties; + +import static org.assertj.core.api.Assertions.assertThat; +import static uk.org.webcompere.systemstubs.SystemStubs.restoreSystemProperties; + +class SystemPropertiesExecuteAroundUnitTest { + @Test + void givenRestoreSystemProperties_thenPropertyRestored() throws Exception { + restoreSystemProperties(() -> { + // test code + System.setProperty("unrestored", "true"); + }); + + assertThat(System.getProperty("unrestored")).isNull(); + } + + @Test + void givenSystemPropertiesObject_thenPropertyRestored() throws Exception { + String result = new SystemProperties() + .execute(() -> { + System.setProperty("unrestored", "true"); + return "it works"; + }); + + assertThat(result).isEqualTo("it works"); + assertThat(System.getProperty("unrestored")).isNull(); + } +} diff --git a/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/WithMockedInputStreamUnitTest.java b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/WithMockedInputStreamUnitTest.java new file mode 100644 index 0000000000..1019781837 --- /dev/null +++ b/testing-modules/testing-libraries-2/src/test/java/com/baeldung/systemstubs/WithMockedInputStreamUnitTest.java @@ -0,0 +1,18 @@ +package com.baeldung.systemstubs; + +import org.junit.jupiter.api.Test; +import uk.org.webcompere.systemstubs.stream.input.LinesAltStream; + +import java.util.Scanner; + +import static org.assertj.core.api.Assertions.assertThat; + +class WithMockedInputStreamUnitTest { + @Test + void givenInputStream_thenCanRead() { + LinesAltStream testInput = new LinesAltStream("line1", "line2"); + + Scanner scanner = new Scanner(testInput); + assertThat(scanner.nextLine()).isEqualTo("line1"); + } +} diff --git a/vavr/src/test/java/com/baeldung/vavr/VavrUnitTest.java b/vavr/src/test/java/com/baeldung/vavr/VavrUnitTest.java index 7beb75632e..b1a9405605 100644 --- a/vavr/src/test/java/com/baeldung/vavr/VavrUnitTest.java +++ b/vavr/src/test/java/com/baeldung/vavr/VavrUnitTest.java @@ -93,6 +93,37 @@ public class VavrUnitTest { assertEquals("JavaVavr 4", transformed); } + @Test + public void editTupleValueForNewTupleInstance(){ + final Tuple2 java9 = Tuple.of("Java", 8); + final Tuple2 transformed = java9.update2(9); + int num = transformed._2(); + assertEquals(9,num); + } + + @Test + public void editTupleValueForSameInstance(){ + Tuple2 java9 = Tuple.of("Java", 8); + java9 = java9.update2(9); + final int num = java9._2(); + assertEquals(9,num); + } + + @Test + public void getNumberOfElementTuple(){ + Tuple2 java8 = Tuple.of("Java", 8); + Tuple3 java8Triple = Tuple.of("Java", 8, 1.8); + Tuple3 java8TripleWnull = Tuple.of("Java", null, 1.8); + + int num = java8.arity(); + int numTriple = java8Triple.arity(); + int numTripleWnull = java8TripleWnull.arity(); + assertEquals(2,num); + assertEquals(3,numTriple); + assertEquals(3,numTripleWnull); + } + + /* * Functions */ diff --git a/webrtc/src/main/resources/static/client.js b/webrtc/src/main/resources/static/client.js index 059dc84bcb..9b3de9ef6d 100644 --- a/webrtc/src/main/resources/static/client.js +++ b/webrtc/src/main/resources/static/client.js @@ -38,11 +38,7 @@ var input = document.getElementById("messageInput"); function initialize() { var configuration = null; - peerConnection = new RTCPeerConnection(configuration, { - optional : [ { - RtpDataChannels : true - } ] - }); + peerConnection = new RTCPeerConnection(configuration); // Setup ice handling peerConnection.onicecandidate = function(event) { @@ -71,6 +67,11 @@ function initialize() { dataChannel.onclose = function() { console.log("data channel is closed"); }; + + peerConnection.ondatachannel = function (event) { + dataChannel = event.channel; + }; + } function createOffer() { diff --git a/xml/pom.xml b/xml/pom.xml index 8b2df41af6..837f918b46 100644 --- a/xml/pom.xml +++ b/xml/pom.xml @@ -364,7 +364,6 @@ 1.2.0 2.0.6 1.6.2 - 2.5 4.1 1.2.4.5 2.3.1 @@ -379,7 +378,6 @@ 2.3.29 0.9.6 - 3.5 2.4 1.8