diff --git a/algorithms/.gitignore b/algorithms/.gitignore new file mode 100644 index 0000000000..b83d22266a --- /dev/null +++ b/algorithms/.gitignore @@ -0,0 +1 @@ +/target/ diff --git a/algorithms/README.md b/algorithms/README.md index a0e10246e0..00e0646f47 100644 --- a/algorithms/README.md +++ b/algorithms/README.md @@ -4,3 +4,4 @@ - [Introduction to Cobertura](http://www.baeldung.com/cobertura) - [Ant Colony Optimization](http://www.baeldung.com/java-ant-colony-optimization) - [Validating Input With Finite Automata in Java](http://www.baeldung.com/finite-automata-java) +- [Introduction to Jenetics Library](http://www.baeldung.com/jenetics) diff --git a/algorithms/pom.xml b/algorithms/pom.xml index 529af19686..884c804d13 100644 --- a/algorithms/pom.xml +++ b/algorithms/pom.xml @@ -31,6 +31,11 @@ ${lombok.version} provided + + io.jenetics + jenetics + 3.7.0 + diff --git a/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/Knapsack.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/Knapsack.java new file mode 100644 index 0000000000..cc99ccf204 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/Knapsack.java @@ -0,0 +1,47 @@ +package com.baeldung.algorithms.ga.jenetics; + +import static org.jenetics.engine.EvolutionResult.toBestPhenotype; +import static org.jenetics.engine.limit.bySteadyFitness; + +import java.util.stream.Stream; + +import org.jenetics.BitChromosome; +import org.jenetics.BitGene; +import org.jenetics.Mutator; +import org.jenetics.Phenotype; +import org.jenetics.RouletteWheelSelector; +import org.jenetics.SinglePointCrossover; +import org.jenetics.TournamentSelector; +import org.jenetics.engine.Engine; +import org.jenetics.engine.EvolutionStatistics; + +//The main class. +public class Knapsack { + + public static void main(String[] args) { + int nItems = 15; + double ksSize = nItems * 100.0 / 3.0; + + KnapsackFF ff = new KnapsackFF(Stream.generate(KnapsackItem::random) + .limit(nItems) + .toArray(KnapsackItem[]::new), ksSize); + + Engine engine = Engine.builder(ff, BitChromosome.of(nItems, 0.5)) + .populationSize(500) + .survivorsSelector(new TournamentSelector<>(5)) + .offspringSelector(new RouletteWheelSelector<>()) + .alterers(new Mutator<>(0.115), new SinglePointCrossover<>(0.16)) + .build(); + + EvolutionStatistics statistics = EvolutionStatistics.ofNumber(); + + Phenotype best = engine.stream() + .limit(bySteadyFitness(7)) + .limit(100) + .peek(statistics) + .collect(toBestPhenotype()); + + System.out.println(statistics); + System.out.println(best); + } +} \ No newline at end of file diff --git a/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/KnapsackFF.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/KnapsackFF.java new file mode 100644 index 0000000000..e3e06d301a --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/KnapsackFF.java @@ -0,0 +1,25 @@ +package com.baeldung.algorithms.ga.jenetics; + +import java.util.function.Function; + +import org.jenetics.BitChromosome; +import org.jenetics.BitGene; +import org.jenetics.Genotype; + +public class KnapsackFF implements Function, Double> { + private KnapsackItem[] items; + private double size; + + public KnapsackFF(KnapsackItem[] items, double size) { + this.items = items; + this.size = size; + } + + @Override + public Double apply(Genotype gt) { + KnapsackItem sum = ((BitChromosome) gt.getChromosome()).ones() + .mapToObj(i -> items[i]) + .collect(KnapsackItem.toSum()); + return sum.size <= this.size ? sum.value : 0; + } +} diff --git a/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/KnapsackItem.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/KnapsackItem.java new file mode 100644 index 0000000000..876df0ba25 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/KnapsackItem.java @@ -0,0 +1,34 @@ +package com.baeldung.algorithms.ga.jenetics; + +import java.util.Random; +import java.util.stream.Collector; + +import org.jenetics.util.RandomRegistry; + +public class KnapsackItem { + + public double size; + public double value; + + public KnapsackItem(double size, double value) { + this.size = size; + this.value = value; + } + + protected static KnapsackItem random() { + Random r = RandomRegistry.getRandom(); + return new KnapsackItem(r.nextDouble() * 100, r.nextDouble() * 100); + } + + protected static Collector toSum() { + return Collector.of(() -> new double[2], (a, b) -> { + a[0] += b.size; + a[1] += b.value; + } , (a, b) -> { + a[0] += b[0]; + a[1] += b[1]; + return a; + } , r -> new KnapsackItem(r[0], r[1])); + } + +} diff --git a/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/SimpleGeneticAlgorithm.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/SimpleGeneticAlgorithm.java new file mode 100644 index 0000000000..845e11b349 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/SimpleGeneticAlgorithm.java @@ -0,0 +1,33 @@ +package com.baeldung.algorithms.ga.jenetics; + +import org.jenetics.BitChromosome; +import org.jenetics.BitGene; +import org.jenetics.Genotype; +import org.jenetics.engine.Engine; +import org.jenetics.engine.EvolutionResult; +import org.jenetics.util.Factory; + +public class SimpleGeneticAlgorithm { + + private static Integer eval(Genotype gt) { + return gt.getChromosome() + .as(BitChromosome.class) + .bitCount(); + } + + public static void main(String[] args) { + Factory> gtf = Genotype.of(BitChromosome.of(10, 0.5)); + System.out.println("Before the evolution:\n" + gtf); + + Engine engine = Engine.builder(SimpleGeneticAlgorithm::eval, gtf) + .build(); + + Genotype result = engine.stream() + .limit(500) + .collect(EvolutionResult.toBestGenotype()); + + System.out.println("After the evolution:\n" + result); + + } + +} diff --git a/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/SpringsteenProblem.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/SpringsteenProblem.java new file mode 100644 index 0000000000..55f2f7af0a --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/SpringsteenProblem.java @@ -0,0 +1,86 @@ +package com.baeldung.algorithms.ga.jenetics; + +import static java.util.Objects.requireNonNull; + +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.jenetics.BitGene; +import org.jenetics.engine.Codec; +import org.jenetics.engine.Engine; +import org.jenetics.engine.EvolutionResult; +import org.jenetics.engine.Problem; +import org.jenetics.engine.codecs; +import org.jenetics.util.ISeq; + +public class SpringsteenProblem implements Problem, BitGene, Double> { + + private ISeq records; + private double maxPricePerUniqueSong; + + public SpringsteenProblem(ISeq records, double maxPricePerUniqueSong) { + this.records = requireNonNull(records); + this.maxPricePerUniqueSong = maxPricePerUniqueSong; + } + + @Override + public Function, Double> fitness() { + return SpringsteenRecords -> { + double cost = SpringsteenRecords.stream() + .mapToDouble(r -> r.price) + .sum(); + + int uniqueSongCount = SpringsteenRecords.stream() + .flatMap(r -> r.songs.stream()) + .collect(Collectors.toSet()) + .size(); + + double pricePerUniqueSong = cost / uniqueSongCount; + + return pricePerUniqueSong <= maxPricePerUniqueSong ? uniqueSongCount : 0.0; + }; + } + + @Override + public Codec, BitGene> codec() { + return codecs.ofSubSet(records); + } + + public static void main(String[] args) { + double maxPricePerUniqueSong = 2.5; + + SpringsteenProblem springsteen = new SpringsteenProblem( + ISeq.of(new SpringsteenRecord("SpringsteenRecord1", 25, ISeq.of("Song1", "Song2", "Song3", "Song4", "Song5", "Song6")), new SpringsteenRecord("SpringsteenRecord2", 15, ISeq.of("Song2", "Song3", "Song4", "Song5", "Song6", "Song7")), + new SpringsteenRecord("SpringsteenRecord3", 35, ISeq.of("Song5", "Song6", "Song7", "Song8", "Song9", "Song10")), new SpringsteenRecord("SpringsteenRecord4", 17, ISeq.of("Song9", "Song10", "Song12", "Song4", "Song13", "Song14")), + new SpringsteenRecord("SpringsteenRecord5", 29, ISeq.of("Song1", "Song2", "Song13", "Song14", "Song15", "Song16")), new SpringsteenRecord("SpringsteenRecord6", 5, ISeq.of("Song18", "Song20", "Song30", "Song40"))), + maxPricePerUniqueSong); + + Engine engine = Engine.builder(springsteen) + .build(); + + ISeq result = springsteen.codec() + .decoder() + .apply(engine.stream() + .limit(10) + .collect(EvolutionResult.toBestGenotype())); + + double cost = result.stream() + .mapToDouble(r -> r.price) + .sum(); + + int uniqueSongCount = result.stream() + .flatMap(r -> r.songs.stream()) + .collect(Collectors.toSet()) + .size(); + + double pricePerUniqueSong = cost / uniqueSongCount; + + System.out.println("Overall cost: " + cost); + System.out.println("Unique songs: " + uniqueSongCount); + System.out.println("Cost per song: " + pricePerUniqueSong); + System.out.println("Records: " + result.map(r -> r.name) + .toString(", ")); + + } + +} \ No newline at end of file diff --git a/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/SpringsteenRecord.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/SpringsteenRecord.java new file mode 100644 index 0000000000..b49709e7f5 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/SpringsteenRecord.java @@ -0,0 +1,24 @@ +package com.baeldung.algorithms.ga.jenetics; + +import static java.util.Objects.requireNonNull; + +import org.jenetics.util.ISeq; + +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class SpringsteenRecord { + + String name; + double price; + ISeq songs; + + public SpringsteenRecord(String name, double price, ISeq songs) { + this.name = requireNonNull(name); + this.price = price; + this.songs = requireNonNull(songs); + } + +} diff --git a/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/SubsetSum.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/SubsetSum.java new file mode 100644 index 0000000000..db1e11239f --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/SubsetSum.java @@ -0,0 +1,66 @@ +package com.baeldung.algorithms.ga.jenetics; + +import static java.util.Objects.requireNonNull; + +import java.util.Random; +import java.util.function.Function; + +import org.jenetics.EnumGene; +import org.jenetics.Mutator; +import org.jenetics.PartiallyMatchedCrossover; +import org.jenetics.Phenotype; +import org.jenetics.engine.Codec; +import org.jenetics.engine.Engine; +import org.jenetics.engine.EvolutionResult; +import org.jenetics.engine.Problem; +import org.jenetics.engine.codecs; +import org.jenetics.engine.limit; +import org.jenetics.util.ISeq; +import org.jenetics.util.LCG64ShiftRandom; + +public class SubsetSum implements Problem, EnumGene, Integer> { + + private ISeq basicSet; + private int size; + + public SubsetSum(ISeq basicSet, int size) { + this.basicSet = requireNonNull(basicSet); + this.size = size; + } + + @Override + public Function, Integer> fitness() { + return subset -> Math.abs(subset.stream() + .mapToInt(Integer::intValue) + .sum()); + } + + @Override + public Codec, EnumGene> codec() { + return codecs.ofSubSet(basicSet, size); + } + + public static SubsetSum of(int n, int k, Random random) { + return new SubsetSum(random.doubles() + .limit(n) + .mapToObj(d -> (int) ((d - 0.5) * n)) + .collect(ISeq.toISeq()), k); + } + + public static void main(String[] args) { + SubsetSum problem = of(500, 15, new LCG64ShiftRandom(101010)); + + Engine, Integer> engine = Engine.builder(problem) + .minimizing() + .maximalPhenotypeAge(5) + .alterers(new PartiallyMatchedCrossover<>(0.4), new Mutator<>(0.3)) + .build(); + + Phenotype, Integer> result = engine.stream() + .limit(limit.bySteadyFitness(55)) + .collect(EvolutionResult.toBestPhenotype()); + + System.out.print(result); + } + +} \ No newline at end of file diff --git a/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/TravelingSalesman.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/TravelingSalesman.java new file mode 100644 index 0000000000..80ede0f8c5 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/ga/jenetics/TravelingSalesman.java @@ -0,0 +1,67 @@ +package com.baeldung.algorithms.ga.jenetics; + +import static java.lang.Math.PI; +import static java.lang.Math.abs; +import static java.lang.Math.sin; +import static org.jenetics.engine.EvolutionResult.toBestPhenotype; +import static org.jenetics.engine.limit.bySteadyFitness; + +import java.util.stream.IntStream; + +import org.jenetics.EnumGene; +import org.jenetics.Optimize; +import org.jenetics.PartiallyMatchedCrossover; +import org.jenetics.Phenotype; +import org.jenetics.SwapMutator; +import org.jenetics.engine.Engine; +import org.jenetics.engine.EvolutionStatistics; +import org.jenetics.engine.codecs; + +public class TravelingSalesman { + + private static final int STOPS = 50; + private static final double[][] ADJACENCE = matrix(STOPS); + + private static double[][] matrix(int stops) { + final double radius = 100.0; + double[][] matrix = new double[stops][stops]; + + for (int i = 0; i < stops; ++i) { + for (int j = 0; j < stops; ++j) { + matrix[i][j] = chord(stops, abs(i - j), radius); + } + } + return matrix; + } + + private static double chord(int stops, int i, double r) { + return 2.0 * r * abs(sin(PI * i / stops)); + } + + private static double dist(final int[] path) { + return IntStream.range(0, STOPS) + .mapToDouble(i -> ADJACENCE[path[i]][path[(i + 1) % STOPS]]) + .sum(); + } + + public static void main(String[] args) { + final Engine, Double> engine = Engine.builder(TravelingSalesman::dist, codecs.ofPermutation(STOPS)) + .optimize(Optimize.MINIMUM) + .maximalPhenotypeAge(11) + .populationSize(500) + .alterers(new SwapMutator<>(0.2), new PartiallyMatchedCrossover<>(0.35)) + .build(); + + final EvolutionStatistics statistics = EvolutionStatistics.ofNumber(); + + final Phenotype, Double> best = engine.stream() + .limit(bySteadyFitness(15)) + .limit(250) + .peek(statistics) + .collect(toBestPhenotype()); + + System.out.println(statistics); + System.out.println(best); + } + +} diff --git a/core-java/README.md b/core-java/README.md index 096ff51df6..a7c8b0e855 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -11,7 +11,9 @@ - [Converting between a List and a Set in Java](http://www.baeldung.com/convert-list-to-set-and-set-to-list) - [Convert a Map to an Array, List or Set in Java](http://www.baeldung.com/convert-map-values-to-array-list-set) - [Java – Write to File](http://www.baeldung.com/java-write-to-file) -- [Java - Convert File to InputStream] (http://www.baeldung.com/convert-file-to-input-stream) +- [Java - Convert File to InputStream](http://www.baeldung.com/convert-file-to-input-stream) +- [Java – Random Long, Float, Integer and Double](http://www.baeldung.com/java-generate-random-long-float-integer-double) +- [Java – Generate Random String](http://www.baeldung.com/java-random-string) - [Java Scanner](http://www.baeldung.com/java-scanner) - [Java Timer](http://www.baeldung.com/java-timer-and-timertask) - [Java – Byte Array to Writer](http://www.baeldung.com/java-convert-byte-array-to-writer) @@ -86,4 +88,7 @@ - [Java Primitive Conversions](http://www.baeldung.com/java-primitive-conversions) - [Java Money and the Currency API](http://www.baeldung.com/java-money-and-currency) - [Guide to Java 8 Comparator.comparing()](http://www.baeldung.com/java-8-comparator-comparing) +- [Avoiding ConcurrentModificationException when iterating and removing](http://www.baeldung.com/avoiding-concurrentmodificationexception-when-iterating-and-removing) +- [Removing all nulls from a List in Java](http://www.baeldung.com/java-remove-nulls-from-list) +- [Removing all duplicates from a List in Java](http://www.baeldung.com/java-remove-duplicates-from-list) diff --git a/core-java/src/main/java/com/baeldung/stringtokenizer/Application.java b/core-java/src/main/java/com/baeldung/stringtokenizer/MyTokenizer.java similarity index 83% rename from core-java/src/main/java/com/baeldung/stringtokenizer/Application.java rename to core-java/src/main/java/com/baeldung/stringtokenizer/MyTokenizer.java index 4560e40697..130218acc2 100644 --- a/core-java/src/main/java/com/baeldung/stringtokenizer/Application.java +++ b/core-java/src/main/java/com/baeldung/stringtokenizer/MyTokenizer.java @@ -9,10 +9,10 @@ import java.util.List; import java.util.StringTokenizer; import java.util.stream.Collectors; -public class Application { +public class MyTokenizer { public List getTokens(String str) { - List tokens = new ArrayList(); + List tokens = new ArrayList<>(); // StringTokenizer tokenizer = new StringTokenizer( str ); StringTokenizer tokenizer = new StringTokenizer(str, ","); // StringTokenizer tokenizer = new StringTokenizer( str , "," , true ); @@ -25,18 +25,18 @@ public class Application { } public List getTokensWithCollection(String str) { - StringTokenizer tokenizer = new StringTokenizer(str, ","); - - return Collections.list(tokenizer).stream() + return Collections + .list(new StringTokenizer(str, ",")) + .stream() .map(token -> (String) token) .collect(Collectors.toList()); } public List getTokensFromFile(String path, String delim) { List tokens = new ArrayList<>(); - String currLine = ""; + String currLine; StringTokenizer tokenizer; - try (BufferedReader br = new BufferedReader(new InputStreamReader(Application.class.getResourceAsStream("/" + path)))) { + try (BufferedReader br = new BufferedReader(new InputStreamReader(MyTokenizer.class.getResourceAsStream("/" + path)))) { while ((currLine = br.readLine()) != null) { tokenizer = new StringTokenizer(currLine, delim); while (tokenizer.hasMoreElements()) { diff --git a/core-java/src/test/java/com/baeldung/java/collections/ConcurrentModificationExceptionTest.java b/core-java/src/test/java/com/baeldung/java/collections/ConcurrentModificationExceptionTest.java new file mode 100644 index 0000000000..100d25ab8d --- /dev/null +++ b/core-java/src/test/java/com/baeldung/java/collections/ConcurrentModificationExceptionTest.java @@ -0,0 +1,82 @@ +package com.baeldung.java.collections; + +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; + +import static java.util.Arrays.asList; +import static org.testng.Assert.assertEquals; + +public class ConcurrentModificationExceptionTest { + @Test + public void changingContentWithSetDoesNotThrowConcurrentModificationException() throws Exception { + ArrayList array = new ArrayList<>(asList(0, "one", 2, "three")); + + for (Object item : array) { + array.set(3, 3); + } + } + + @Test + public void removingElementUsingIteratorAPI() throws Exception { + List originalList = new ArrayList<>(asList("zero", "one", "two", "three")); + + Iterator iterator = originalList.iterator(); + + while (iterator.hasNext()) { + String next = iterator.next(); + if (Objects.equals(next, "one")) iterator.remove(); + } + + assertEquals(originalList, asList("zero", "two", "three")); + } + + @Test + public void modifyingContentAndIteratingUsingListIteratorAPI() throws Exception { + List originalList = new ArrayList<>(asList("zero", "one", "two", "three")); + + ListIterator iterator = originalList.listIterator(); + + while (iterator.hasNext()) { + String next = iterator.next(); + if (Objects.equals(next, "one")) { + iterator.set("another"); + } + + if (Objects.equals(next, "two")) { + iterator.remove(); + } + + if (Objects.equals(next, "three")) { + iterator.add("four"); + } + } + + assertEquals(originalList, asList("zero", "another", "three", "four")); + } + + @Test + public void removingElementUsingCopyAndListAPI() throws Exception { + List originalList = new ArrayList<>(asList("zero", "one", "two", "three")); + + List listCopy = new ArrayList<>(originalList); + + for (String next : listCopy) { + if (Objects.equals(next, "one")) originalList.remove(originalList.indexOf(next) - 1); + } + + assertEquals(originalList, asList("one", "two", "three")); + } + + @Test + public void copyOnWriteList() throws Exception { + List originalList = new CopyOnWriteArrayList<>(asList("zero", "one", "two", "three")); + + for (String next : originalList) { + if (Objects.equals(next, "one")) originalList.remove(originalList.indexOf(next) - 1); + } + + assertEquals(originalList, asList("one", "two", "three")); + } +} diff --git a/core-java/src/test/java/com/baeldung/stringtokenizer/ApplicationTest.java b/core-java/src/test/java/com/baeldung/stringtokenizer/ApplicationTest.java deleted file mode 100644 index 5d475d2fbb..0000000000 --- a/core-java/src/test/java/com/baeldung/stringtokenizer/ApplicationTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.baeldung.stringtokenizer; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class ApplicationTest { - - Application application = new Application(); - List expectedTokensForString = new ArrayList(); - List expectedTokensForFile = new ArrayList(); - - @Before - public void init() { - expectedTokensForString.add("Welcome"); - expectedTokensForString.add("to"); - expectedTokensForString.add("baeldung.com"); - - expectedTokensForFile.add("1"); - expectedTokensForFile.add("IND"); - expectedTokensForFile.add("India"); - expectedTokensForFile.add("2"); - expectedTokensForFile.add("MY"); - expectedTokensForFile.add("Malaysia"); - expectedTokensForFile.add("3"); - expectedTokensForFile.add("AU"); - expectedTokensForFile.add("Australia"); - } - - @Test - public void givenString_thenGetListOfString() { - String str = "Welcome,to,baeldung.com"; - List actualTokens = application.getTokens(str); - assertEquals(expectedTokensForString, actualTokens); - } - - @Test - public void givenFile_thenGetListOfString() { - List actualTokens = application.getTokensFromFile("data.csv", "|"); - assertEquals(expectedTokensForFile, actualTokens); - } - -} diff --git a/core-java/src/test/java/com/baeldung/stringtokenizer/TokenizerTest.java b/core-java/src/test/java/com/baeldung/stringtokenizer/TokenizerTest.java new file mode 100644 index 0000000000..eed42a2f96 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/stringtokenizer/TokenizerTest.java @@ -0,0 +1,29 @@ +package com.baeldung.stringtokenizer; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class TokenizerTest { + + private final MyTokenizer myTokenizer = new MyTokenizer(); + private final List expectedTokensForString = Arrays.asList("Welcome", "to", "baeldung.com"); + private final List expectedTokensForFile = Arrays.asList("1", "IND", "India", "2", "MY", "Malaysia", "3", "AU", "Australia"); + + @Test + public void givenString_thenGetListOfString() { + String str = "Welcome,to,baeldung.com"; + List actualTokens = myTokenizer.getTokens(str); + assertEquals(expectedTokensForString, actualTokens); + } + + @Test + public void givenFile_thenGetListOfString() { + List actualTokens = myTokenizer.getTokensFromFile("data.csv", "|"); + assertEquals(expectedTokensForFile, actualTokens); + } + +} diff --git a/guava/src/test/java/org/baeldung/guava/GuavaMathTest.java b/guava/src/test/java/org/baeldung/guava/GuavaMathTest.java index d0c551032c..b8e13f0650 100644 --- a/guava/src/test/java/org/baeldung/guava/GuavaMathTest.java +++ b/guava/src/test/java/org/baeldung/guava/GuavaMathTest.java @@ -1,167 +1,195 @@ package org.baeldung.guava; -import com.google.common.math.DoubleMath; -import com.google.common.math.IntMath; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.*; import java.math.BigInteger; import java.math.RoundingMode; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +import org.junit.Test; + +import com.google.common.math.DoubleMath; +import com.google.common.math.IntMath; public class GuavaMathTest { - @Test - public void testIntMathAdd() { - try { - IntMath.checkedAdd(Integer.MAX_VALUE, 1); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } + @Test(expected = ArithmeticException.class) + public void whenSumOverflow_thenThrowException() { + IntMath.checkedAdd(Integer.MAX_VALUE, 1); + } - try { - IntMath.checkedAdd(Integer.MIN_VALUE, -1); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } - - int result1 = IntMath.checkedAdd(2, 1); - assertThat(result1, equalTo(3)); - - int result2 = IntMath.saturatedAdd(Integer.MAX_VALUE, 100); - assertThat(result2, equalTo(Integer.MAX_VALUE)); - - int result3 = IntMath.saturatedAdd(Integer.MIN_VALUE, -100); - assertThat(result3, equalTo(Integer.MIN_VALUE)); + @Test(expected = ArithmeticException.class) + public void whenSumUnderflow_thenThrowException() { + IntMath.checkedAdd(Integer.MIN_VALUE, -1); } @Test - public void testIntMathSubtract() { - try { - IntMath.checkedSubtract(Integer.MIN_VALUE, 1); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } - - try { - IntMath.checkedSubtract(Integer.MAX_VALUE, -1); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - }; - - int result1 = IntMath.checkedSubtract(200, 100); - assertThat(result1, equalTo(100)); - - int result2 = IntMath.saturatedSubtract(Integer.MIN_VALUE, 1); - assertThat(result2, equalTo(Integer.MIN_VALUE)); - - int result3 = IntMath.saturatedSubtract(Integer.MAX_VALUE, -1); - assertThat(result3, equalTo(Integer.MAX_VALUE)); + public void should_calculate_sum() { + int result = IntMath.checkedAdd(2, 1); + assertThat(result, equalTo(3)); } @Test - public void testIntMathMultiply() { - try { - IntMath.checkedMultiply(Integer.MAX_VALUE, 2); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } - - try { - IntMath.checkedMultiply(Integer.MIN_VALUE, 2); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } - - int result1 = IntMath.checkedMultiply(21, 3); - assertThat(result1, equalTo(63)); - - int result2 = IntMath.saturatedMultiply(Integer.MAX_VALUE, 2); - assertThat(result2, equalTo(Integer.MAX_VALUE)); - - int result3 = IntMath.saturatedMultiply(Integer.MIN_VALUE, 2); - assertThat(result3, equalTo(Integer.MIN_VALUE)); + public void whenSumOverflow_thenReturnMaxInteger() { + int result = IntMath.saturatedAdd(Integer.MAX_VALUE, 100); + assertThat(result, equalTo(Integer.MAX_VALUE)); } @Test - public void testIntMathPow() { - try { - IntMath.checkedPow(Integer.MAX_VALUE, 2); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } + public void whenSumUnderflow_thenReturnMinInteger() { + int result = IntMath.saturatedAdd(Integer.MIN_VALUE, -100); + assertThat(result, equalTo(Integer.MIN_VALUE)); + } - try { - IntMath.checkedPow(Integer.MIN_VALUE, 3); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } + @Test(expected = ArithmeticException.class) + public void whenDifferenceOverflow_thenThrowException() { + IntMath.checkedSubtract(Integer.MAX_VALUE, -1); + } - int result1 = IntMath.saturatedPow(3, 3); - assertThat(result1, equalTo(27)); - - int result2 = IntMath.saturatedPow(Integer.MAX_VALUE, 2); - assertThat(result2, equalTo(Integer.MAX_VALUE)); - - int result3 = IntMath.saturatedPow(Integer.MIN_VALUE, 3); - assertThat(result3, equalTo(Integer.MIN_VALUE)); + @Test(expected = ArithmeticException.class) + public void whenDifferenceUnderflow_thenThrowException() { + IntMath.checkedSubtract(Integer.MIN_VALUE, 1); } @Test - public void testIntMathRound() { + public void should_calculate_difference() { + int result = IntMath.checkedSubtract(200, 100); + assertThat(result, equalTo(100)); + } + + @Test + public void whenDifferenceOverflow_thenReturnMaxInteger() { + int result = IntMath.saturatedSubtract(Integer.MAX_VALUE, -1); + assertThat(result, equalTo(Integer.MAX_VALUE)); + } + + @Test + public void whenDifferenceUnderflow_thenReturnMinInteger() { + int result = IntMath.saturatedSubtract(Integer.MIN_VALUE, 1); + assertThat(result, equalTo(Integer.MIN_VALUE)); + } + + @Test(expected = ArithmeticException.class) + public void whenProductOverflow_thenThrowException() { + IntMath.checkedMultiply(Integer.MAX_VALUE, 2); + } + + @Test(expected = ArithmeticException.class) + public void whenProductUnderflow_thenThrowException() { + IntMath.checkedMultiply(Integer.MIN_VALUE, 2); + } + + @Test + public void should_calculate_product() { + int result = IntMath.checkedMultiply(21, 3); + assertThat(result, equalTo(63)); + } + + @Test + public void whenProductOverflow_thenReturnMaxInteger() { + int result = IntMath.saturatedMultiply(Integer.MAX_VALUE, 2); + assertThat(result, equalTo(Integer.MAX_VALUE)); + } + + @Test + public void whenProductUnderflow_thenReturnMinInteger() { + int result = IntMath.saturatedMultiply(Integer.MIN_VALUE, 2); + assertThat(result, equalTo(Integer.MIN_VALUE)); + } + + @Test(expected = ArithmeticException.class) + public void whenPowerOverflow_thenThrowException() { + IntMath.checkedPow(Integer.MAX_VALUE, 2); + } + + @Test(expected = ArithmeticException.class) + public void whenPowerUnderflow_thenThrowException() { + IntMath.checkedPow(Integer.MIN_VALUE, 3); + } + + @Test + public void should_calculate_power() { + int result = IntMath.saturatedPow(3, 3); + assertThat(result, equalTo(27)); + } + + @Test + public void whenPowerOverflow_thenReturnMaxInteger() { + int result = IntMath.saturatedPow(Integer.MAX_VALUE, 2); + assertThat(result, equalTo(Integer.MAX_VALUE)); + } + + @Test + public void whenPowerUnderflow_thenReturnMinInteger() { + int result = IntMath.saturatedPow(Integer.MIN_VALUE, 3); + assertThat(result, equalTo(Integer.MIN_VALUE)); + } + + @Test + public void should_round_divide_result() { int result1 = IntMath.divide(3, 2, RoundingMode.DOWN); assertThat(result1, equalTo(1)); + int result2 = IntMath.divide(3, 2, RoundingMode.UP); assertThat(result2, equalTo(2)); - - int result3 = IntMath.log2(5, RoundingMode.FLOOR); - assertThat(result3, equalTo(2)); - int result4 = IntMath.log2(5, RoundingMode.CEILING); - assertThat(result4, equalTo(3)); - - int result5 = IntMath.log10(11, RoundingMode.HALF_UP); - assertThat(result5, equalTo(1)); - - int result6 = IntMath.sqrt(4, RoundingMode.UNNECESSARY); - assertThat(result6, equalTo(2)); - try { - IntMath.sqrt(5, RoundingMode.UNNECESSARY); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } } @Test - public void testIntMathAdditionalFunctions() { - int result1 = IntMath.gcd(15, 20); - assertThat(result1, equalTo(5)); + public void should_round_log2_result() { + int result1 = IntMath.log2(5, RoundingMode.FLOOR); + assertThat(result1, equalTo(2)); - int result2 = IntMath.mod(8, 3); - assertThat(result2, equalTo(2)); + int result2 = IntMath.log2(5, RoundingMode.CEILING); + assertThat(result2, equalTo(3)); + } - boolean result3 = IntMath.isPowerOfTwo(8); - assertTrue(result3); - boolean result4 = IntMath.isPowerOfTwo(9); - assertFalse(result4); + @Test + public void should_round_log10_result() { + int result = IntMath.log10(11, RoundingMode.HALF_UP); + assertThat(result, equalTo(1)); + } - int result5 = IntMath.factorial(4); - assertThat(result5, equalTo(24)); + @Test + public void should_round_sqrt_result() { + int result = IntMath.sqrt(4, RoundingMode.UNNECESSARY); + assertThat(result, equalTo(2)); + } - int result6 = IntMath.binomial(7, 3); - assertThat(result6, equalTo(35)); + @Test(expected = ArithmeticException.class) + public void whenNeedRounding_thenThrowException() { + IntMath.sqrt(5, RoundingMode.UNNECESSARY); + } + + @Test + public void should_calculate_gcd() { + int result = IntMath.gcd(15, 20); + assertThat(result, equalTo(5)); + } + + @Test + public void should_calculate_mod() { + int result = IntMath.mod(8, 3); + assertThat(result, equalTo(2)); + } + + @Test + public void should_test_if_is_power_of_two() { + boolean result1 = IntMath.isPowerOfTwo(8); + assertTrue(result1); + + boolean result2 = IntMath.isPowerOfTwo(9); + assertFalse(result2); + } + + @Test + public void should_calculate_factorial() { + int result = IntMath.factorial(4); + assertThat(result, equalTo(24)); + } + + @Test + public void should_calculate_binomial() { + int result = IntMath.binomial(7, 3); + assertThat(result, equalTo(35)); } @Test diff --git a/jee7/pom.xml b/jee7/pom.xml index 26d433df78..addb586b74 100644 --- a/jee7/pom.xml +++ b/jee7/pom.xml @@ -7,7 +7,6 @@ jee7 1.0-SNAPSHOT JavaEE 7 Arquillian Archetype Sample - war 1.8 @@ -28,6 +27,7 @@ 3.6.0 2.6 + 2.19.1 @@ -43,6 +43,13 @@ import pom + + org.jboss.arquillian.extension + arquillian-drone-bom + 2.0.1.Final + pom + import + @@ -65,6 +72,13 @@ arquillian-junit-container test + + org.jboss.arquillian.graphene + graphene-webdriver + 2.1.0.Final + pom + test + com.jayway.awaitility awaitility @@ -85,6 +99,37 @@ test + + com.sun.faces + jsf-api + 2.2.14 + + + com.sun.faces + jsf-impl + 2.2.14 + + + javax.servlet + jstl + 1.2 + + + javax.servlet + javax.servlet-api + 3.1.0 + + + javax.servlet.jsp + jsp-api + 2.2 + provided + + + taglibs + standard + 1.1.2 + @@ -167,6 +212,7 @@ + maven-dependency-plugin @@ -206,6 +252,7 @@ + diff --git a/jee7/src/main/java/com/baeldung/convListVal/ConvListVal.java b/jee7/src/main/java/com/baeldung/convListVal/ConvListVal.java new file mode 100644 index 0000000000..245c69f2bb --- /dev/null +++ b/jee7/src/main/java/com/baeldung/convListVal/ConvListVal.java @@ -0,0 +1,56 @@ +package com.baeldung.convListVal; + +import java.util.Date; + +import javax.faces.bean.ManagedBean; + +@ManagedBean +public class ConvListVal { + + private Integer age; + private Double average; + private Date myDate; + private String name; + private String surname; + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public Double getAverage() { + return average; + } + + public void setAverage(Double average) { + this.average = average; + } + + public Date getMyDate() { + return myDate; + } + + public void setMyDate(Date myDate) { + this.myDate = myDate; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSurname() { + return surname; + } + + public void setSurname(String surname) { + this.surname = surname; + } + +} diff --git a/jee7/src/main/java/com/baeldung/convListVal/MyListener.java b/jee7/src/main/java/com/baeldung/convListVal/MyListener.java new file mode 100644 index 0000000000..784bddd59a --- /dev/null +++ b/jee7/src/main/java/com/baeldung/convListVal/MyListener.java @@ -0,0 +1,21 @@ +package com.baeldung.convListVal; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.faces.event.AbortProcessingException; +import javax.faces.event.ValueChangeEvent; +import javax.faces.event.ValueChangeListener; + +public class MyListener implements ValueChangeListener { + + private static final Logger LOG = Logger.getLogger(MyListener.class.getName()); + @Override + public void processValueChange(ValueChangeEvent event) throws AbortProcessingException { + if (event.getNewValue() != null) { + LOG.log(Level.INFO, "\tNew Value:{0}", event.getNewValue()); + } + + } + +} diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/README.txt b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/README.txt index 063856b2be..0f95e588b8 100644 --- a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/README.txt +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/README.txt @@ -12,8 +12,17 @@ NOTES: @WebServlet annotation designates the AccountServlet class as a Servlet c An initialization parameter 'type' is being set to denote the type of the bank account. @ServletSecurity annotation imposes security constraints on the AccountServlet based on - the tomcat-users.xml (this code assumes there is a role 'admin' in your tomcat-users.xml) - + the tomcat-users.xml. +   + This code assumes that your tomcat-users.xml looks as follows: + + + + + + + +   N.B : To see @ServletSecurity annotation in action, please uncomment the annotation code for @ServletSecurity. diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/AccountServlet.java b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/AccountServlet.java index a8ed74984b..a487d4c3b1 100644 --- a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/AccountServlet.java +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/AccountServlet.java @@ -1,4 +1,4 @@ -package com.baeldung.javaeeannotations; +package com.baeldung.javaeeannotations.JavaEEAnnotationsSample.src.main.java.com.baeldung.javaeeannotations; import java.io.IOException; import java.io.PrintWriter; @@ -17,8 +17,8 @@ import javax.servlet.http.HttpServletResponse; initParams = { @WebInitParam(name = "type", value = "savings") } ) /*@ServletSecurity( - value = @HttpConstraint(rolesAllowed = {"admin"}), - httpMethodConstraints = {@HttpMethodConstraint(value = "POST", rolesAllowed = {"admin"})} + value = @HttpConstraint(rolesAllowed = {"Member"}), + httpMethodConstraints = {@HttpMethodConstraint(value = "POST", rolesAllowed = {"Admin"})} )*/ public class AccountServlet extends javax.servlet.http.HttpServlet { diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/BankAppServletContextListener.java b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/BankAppServletContextListener.java index ee1b624cd1..dc9a91d059 100644 --- a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/BankAppServletContextListener.java +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/BankAppServletContextListener.java @@ -1,4 +1,4 @@ -package com.baeldung.javaeeannotations; +package com.baeldung.javaeeannotations.JavaEEAnnotationsSample.src.main.java.com.baeldung.javaeeannotations; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/LogInFilter.java b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/LogInFilter.java index 5ee420f6a2..bfe1a39377 100644 --- a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/LogInFilter.java +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/LogInFilter.java @@ -1,4 +1,4 @@ -package com.baeldung.javaeeannotations; +package com.baeldung.javaeeannotations.JavaEEAnnotationsSample.src.main.java.com.baeldung.javaeeannotations; import java.io.IOException; diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/UploadCustomerDocumentsServlet.java b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/UploadCustomerDocumentsServlet.java index 28922dba46..6945f663bb 100644 --- a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/UploadCustomerDocumentsServlet.java +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/UploadCustomerDocumentsServlet.java @@ -1,4 +1,4 @@ -package com.baeldung.javaeeannotations; +package com.baeldung.javaeeannotations.JavaEEAnnotationsSample.src.main.java.com.baeldung.javaeeannotations; import java.io.IOException; import java.io.PrintWriter; diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/webapp/web.xml b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/webapp/WEB-INF/web.xml similarity index 97% rename from jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/webapp/web.xml rename to jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/webapp/WEB-INF/web.xml index f01eb341e4..a92885ec11 100644 --- a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/webapp/web.xml +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/webapp/WEB-INF/web.xml @@ -7,5 +7,4 @@ BASIC default - - \ No newline at end of file + diff --git a/jee7/src/main/webapp/ConvListVal.xhtml b/jee7/src/main/webapp/ConvListVal.xhtml new file mode 100644 index 0000000000..e5425e87a5 --- /dev/null +++ b/jee7/src/main/webapp/ConvListVal.xhtml @@ -0,0 +1,50 @@ + + + + + Converters, Listeners and Validators + + +

Testing converters

+ + + + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + + + + +
+ +
+
+ diff --git a/jee7/src/test/java/com/baeldung/jaxws/EmployeeServiceLiveTest.java b/jee7/src/test/java/com/baeldung/jaxws/EmployeeServiceLiveTest.java index 5311b3c5fe..4429703468 100644 --- a/jee7/src/test/java/com/baeldung/jaxws/EmployeeServiceLiveTest.java +++ b/jee7/src/test/java/com/baeldung/jaxws/EmployeeServiceLiveTest.java @@ -1,4 +1,4 @@ -package com.baeldung.jaxws; +/*package com.baeldung.jaxws; import static org.junit.Assert.assertEquals; @@ -108,3 +108,4 @@ public class EmployeeServiceLiveTest { } } +*/ \ No newline at end of file diff --git a/libraries/pom.xml b/libraries/pom.xml index 0f33c42dc4..1d908c453a 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -20,6 +20,31 @@ 1.8 + + org.apache.maven.plugins + maven-dependency-plugin + + + org.apache.felix + maven-bundle-plugin + 3.3.0 + maven-plugin + + + + true + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + **/*IntegrationTest.java + **/*LiveTest.java + + +
@@ -92,6 +117,56 @@ commons-io ${commons.io.version} + + org.eclipse.jetty + jetty-server + ${jetty.version} + + + org.eclipse.jetty + jetty-servlet + ${jetty.version} + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + commons-io + commons-io + ${commons.io.version} + + + org.apache.flink + flink-core + ${flink.version} + + + org.apache.flink + flink-java + ${flink.version} + + + org.apache.flink + flink-test-utils_2.10 + ${flink.version} + + + org.apache.flink + flink-core + ${flink.version} + + + org.apache.flink + flink-java + ${flink.version} + + + org.apache.flink + flink-test-utils_2.10 + ${flink.version} + @@ -104,9 +179,14 @@ 3.6.2 1.5.0 3.1.0 + 9.4.3.v20170317 + 4.5.3 + 2.5 9.4.2.v20170220 4.5.3 2.5 + 1.2.0 + 2.19.1 \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/flink/LineSplitter.java b/libraries/src/main/java/com/baeldung/flink/LineSplitter.java new file mode 100644 index 0000000000..8deeeb01c4 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/flink/LineSplitter.java @@ -0,0 +1,20 @@ +package com.baeldung.flink; + +import org.apache.flink.api.common.functions.FlatMapFunction; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.util.Collector; + +import java.util.stream.Stream; + +@SuppressWarnings("serial") +public class LineSplitter implements FlatMapFunction> { + + @Override + public void flatMap(String value, Collector> out) { + + String[] tokens = value.toLowerCase().split("\\W+"); + Stream.of(tokens) + .filter(t -> t.length() > 0) + .forEach(token -> out.collect(new Tuple2<>(token, 1))); + } +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/flink/WordCount.java b/libraries/src/main/java/com/baeldung/flink/WordCount.java new file mode 100644 index 0000000000..ab109bdbce --- /dev/null +++ b/libraries/src/main/java/com/baeldung/flink/WordCount.java @@ -0,0 +1,20 @@ +package com.baeldung.flink; + +import org.apache.flink.api.java.DataSet; +import org.apache.flink.api.java.ExecutionEnvironment; +import org.apache.flink.api.java.aggregation.Aggregations; +import org.apache.flink.api.java.tuple.Tuple2; + +import java.util.List; + +public class WordCount { + + public static DataSet> startWordCount(ExecutionEnvironment env, List lines) throws Exception { + DataSet text = env.fromCollection(lines); + + return text.flatMap(new LineSplitter()) + .groupBy(0) + .aggregate(Aggregations.SUM, 1); + + } +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/jetty/JettyServer.java b/libraries/src/main/java/com/baeldung/jetty/JettyServer.java index 1365de866a..1033a7266d 100644 --- a/libraries/src/main/java/com/baeldung/jetty/JettyServer.java +++ b/libraries/src/main/java/com/baeldung/jetty/JettyServer.java @@ -4,6 +4,7 @@ import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.ServletHandler; +import org.eclipse.jetty.util.thread.QueuedThreadPool; public class JettyServer { @@ -11,7 +12,13 @@ public class JettyServer { public void start() throws Exception { - server = new Server(); + int maxThreads = 100; + int minThreads = 10; + int idleTimeout = 120; + + QueuedThreadPool threadPool = new QueuedThreadPool(maxThreads, minThreads, idleTimeout); + + server = new Server(threadPool); ServerConnector connector = new ServerConnector(server); connector.setPort(8090); server.setConnectors(new Connector[]{connector}); diff --git a/libraries/src/test/java/com/baeldung/flink/WordCountIntegrationTest.java b/libraries/src/test/java/com/baeldung/flink/WordCountIntegrationTest.java new file mode 100644 index 0000000000..3190debef8 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/flink/WordCountIntegrationTest.java @@ -0,0 +1,186 @@ +package com.baeldung.flink; + +import org.apache.flink.api.common.operators.Order; +import org.apache.flink.api.java.DataSet; +import org.apache.flink.api.java.ExecutionEnvironment; +import org.apache.flink.api.java.functions.KeySelector; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.tuple.Tuple3; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; +import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows; +import org.apache.flink.streaming.api.windowing.time.Time; +import org.junit.Test; + +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class WordCountIntegrationTest { + final ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); + + @Test + public void givenDataSet_whenExecuteWordCount_thenReturnWordCount() throws Exception { + //given + List lines = Arrays.asList("This is a first sentence", "This is a second sentence with a one word"); + + //when + DataSet> result = WordCount.startWordCount(env, lines); + + //then + List> collect = result.collect(); + assertThat(collect).containsExactlyInAnyOrder( + new Tuple2<>("a", 3), new Tuple2<>("sentence", 2), new Tuple2<>("word", 1), + new Tuple2<>("is", 2), new Tuple2<>("this", 2), new Tuple2<>("second", 1), + new Tuple2<>("first", 1), new Tuple2<>("with", 1), new Tuple2<>("one", 1)); + } + + @Test + public void givenListOfAmounts_whenUseMapReduce_thenSumAmountsThatAreOnlyAboveThreshold() throws Exception { + //given + DataSet amounts = env.fromElements(1, 29, 40, 50); + int threshold = 30; + + //when + List collect = amounts + .filter(a -> a > threshold) + .reduce((integer, t1) -> integer + t1) + .collect(); + + //then + assertThat(collect.get(0)).isEqualTo(90); + } + + @Test + public void givenDataSetOfComplexObjects_whenMapToGetOneField_thenReturnedListHaveProperElements() throws Exception { + //given + DataSet personDataSource = env.fromCollection(Arrays.asList(new Person(23, "Tom"), new Person(75, "Michael"))); + + //when + List ages = personDataSource.map(p -> p.age).collect(); + + //then + assertThat(ages.size()).isEqualTo(2); + assertThat(ages.containsAll(Arrays.asList(23, 75))).isTrue(); + + } + + @Test + public void givenDataSet_whenSortItByOneField_thenShouldReturnSortedDataSet() throws Exception { + //given + Tuple2 secondPerson = new Tuple2<>(4, "Tom"); + Tuple2 thirdPerson = new Tuple2<>(5, "Scott"); + Tuple2 fourthPerson = new Tuple2<>(200, "Michael"); + Tuple2 firstPerson = new Tuple2<>(1, "Jack"); + DataSet> transactions = env.fromElements(fourthPerson, secondPerson, + thirdPerson, firstPerson); + + + //when + List> sorted = transactions + .sortPartition(new IdKeySelectorTransaction(), Order.ASCENDING) + .collect(); + + //then + assertThat(sorted).containsExactly(firstPerson, secondPerson, thirdPerson, fourthPerson); + } + + + @Test + public void giveTwoDataSets_whenJoinUsingId_thenProduceJoinedData() throws Exception { + //given + Tuple3 address = new Tuple3<>(1, "5th Avenue", "London"); + DataSet> addresses = env.fromElements(address); + + Tuple2 firstTransaction = new Tuple2<>(1, "Transaction_1"); + DataSet> transactions = + env.fromElements(firstTransaction, new Tuple2<>(12, "Transaction_2")); + + + //when + List, Tuple3>> joined = + transactions.join(addresses) + .where(new IdKeySelectorTransaction()) + .equalTo(new IdKeySelectorAddress()) + .collect(); + + //then + assertThat(joined.size()).isEqualTo(1); + assertThat(joined.contains(new Tuple2<>(firstTransaction, address))); + + } + + @Test + public void givenStreamOfEvents_whenProcessEvents_thenShouldPrintResultsOnSinkOperation() throws Exception { + //given + final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + DataStream text + = env.fromElements("This is a first sentence", "This is a second sentence with a one word"); + + + SingleOutputStreamOperator upperCase = text.map(String::toUpperCase); + + upperCase.print(); + + //when + env.execute(); + } + + + @Test + public void givenStreamOfEvents_whenProcessEvents_thenShouldApplyWindowingOnTransformation() throws Exception { + //given + final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + SingleOutputStreamOperator> windowed = env.fromElements( + new Tuple2<>(16, ZonedDateTime.now().plusMinutes(25).toInstant().getEpochSecond()), + new Tuple2<>(15, ZonedDateTime.now().plusMinutes(2).toInstant().getEpochSecond()) + ).assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor>(Time.seconds(20)) { + @Override + public long extractTimestamp(Tuple2 element) { + return element.f1 * 1000; + } + }); + + SingleOutputStreamOperator> reduced = windowed + .windowAll(TumblingEventTimeWindows.of(Time.seconds(5))) + .maxBy(0, true); + + reduced.print(); + + //when + env.execute(); + } + + + private static class IdKeySelectorTransaction implements KeySelector, Integer> { + @Override + public Integer getKey(Tuple2 value) { + return value.f0; + } + } + + private static class IdKeySelectorAddress implements KeySelector, Integer> { + @Override + public Integer getKey(Tuple3 value) { + return value.f0; + } + } + + private static class Person { + private final int age; + private final String name; + + private Person(int age, String name) { + this.age = age; + this.name = name; + } + } + +} \ No newline at end of file diff --git a/mockito/src/test/java/org/baeldung/mockito/MockitoConfigExamplesTest.java b/mockito/src/test/java/org/baeldung/mockito/MockitoConfigExamplesTest.java index de6e7fca72..5050a2d6bc 100644 --- a/mockito/src/test/java/org/baeldung/mockito/MockitoConfigExamplesTest.java +++ b/mockito/src/test/java/org/baeldung/mockito/MockitoConfigExamplesTest.java @@ -2,8 +2,6 @@ package org.baeldung.mockito; import org.junit.Test; import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.hamcrest.Matchers.equalTo; @@ -69,7 +67,7 @@ public class MockitoConfigExamplesTest { } @Test - public final void whenMockMethodCallIsConfiguredToCallTheRealMethod_thenRealMetehodIsCalled() { + public final void whenMockMethodCallIsConfiguredToCallTheRealMethod_thenRealMethodIsCalled() { final MyList listMock = Mockito.mock(MyList.class); when(listMock.size()).thenCallRealMethod(); @@ -77,14 +75,9 @@ public class MockitoConfigExamplesTest { } @Test - public final void whenMockMethodCallIsConfiguredWithCustomAnswer_thenRealMetehodIsCalled() { + public final void whenMockMethodCallIsConfiguredWithCustomAnswer_thenRealMethodIsCalled() { final MyList listMock = Mockito.mock(MyList.class); - doAnswer(new Answer() { - @Override - public final String answer(final InvocationOnMock invocation) { - return "Always the same"; - } - }).when(listMock).get(anyInt()); + doAnswer(invocation -> "Always the same").when(listMock).get(anyInt()); final String element = listMock.get(1); assertThat(element, is(equalTo("Always the same"))); diff --git a/pom.xml b/pom.xml index b21d656772..1a11bd055f 100644 --- a/pom.xml +++ b/pom.xml @@ -153,7 +153,6 @@ spring-mvc-email spring-mvc-forms spring-mvc-java - spring-mvc-no-xml spring-mvc-tiles spring-mvc-velocity spring-mvc-web-vs-initializer diff --git a/rest-testing/pom.xml b/rest-testing/pom.xml index f7f94a49a6..746752133c 100644 --- a/rest-testing/pom.xml +++ b/rest-testing/pom.xml @@ -1,164 +1,171 @@ - 4.0.0 - com.baeldung - rest-testing - 0.1-SNAPSHOT + 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 + rest-testing + 0.1-SNAPSHOT - rest-testing + rest-testing - + - + - - com.google.guava - guava - ${guava.version} - + + com.google.guava + guava + ${guava.version} + - - commons-io - commons-io - ${commons-io.version} - + + commons-io + commons-io + ${commons-io.version} + - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + - + - - org.apache.httpcomponents - httpclient - ${httpclient.version} - - - org.apache.httpcomponents - httpcore - ${httpcore.version} - + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + org.apache.httpcomponents + httpcore + ${httpcore.version} + - + - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + - + - - org.slf4j - slf4j-api - ${org.slf4j.version} - - - ch.qos.logback - logback-classic - ${logback.version} - - - - org.slf4j - jcl-over-slf4j - ${org.slf4j.version} - runtime - - - org.slf4j - log4j-over-slf4j - ${org.slf4j.version} - + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + runtime + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + - + - - junit - junit - ${junit.version} - test - + + junit + junit + ${junit.version} + test + - - org.hamcrest - hamcrest-core - ${org.hamcrest.version} - test - - - org.hamcrest - hamcrest-library - ${org.hamcrest.version} - test - + + org.hamcrest + hamcrest-core + ${org.hamcrest.version} + test + + + org.hamcrest + hamcrest-library + ${org.hamcrest.version} + test + - - org.mockito - mockito-core - ${mockito.version} - test - - - com.github.tomakehurst - wiremock - ${wiremock.version} - test - + + org.mockito + mockito-core + ${mockito.version} + test + + + com.github.tomakehurst + wiremock + ${wiremock.version} + test + - - info.cukes - cucumber-java - ${cucumber.version} - test - - - info.cukes - cucumber-junit - ${cucumber.version} - - + + info.cukes + cucumber-java + ${cucumber.version} + test + + + info.cukes + cucumber-junit + ${cucumber.version} + - - rest-testing - - - src/main/resources - true - - + + org.jbehave + jbehave-core + ${jbehave.version} + test + + - + + rest-testing + + + src/main/resources + true + + - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - 1.8 - 1.8 - - + - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + **/*IntegrationTest.java **/*LiveTest.java - + - + - + @@ -177,10 +184,10 @@ **/*UnitTest.java + **/*LiveTest.java **/*IntegrationTest.java - **/*LiveTest.java @@ -195,37 +202,38 @@ - - - - 2.8.5 - - 1.7.21 - 1.1.7 + + + 2.8.5 - - 19.0 - 3.5 - 2.5 + + 1.7.21 + 1.1.7 - - 1.3 - 4.12 - 1.10.19 + + 19.0 + 3.5 + 2.5 + + + 1.3 + 4.12 + 1.10.19 2.9.0 1.2.5 2.4.1 - 4.4.5 - 4.5.2 + 4.4.5 + 4.5.2 + 4.1 - - 3.6.0 - 2.6 - 2.19.1 + + 3.6.0 + 2.6 + 2.19.1 - + \ No newline at end of file diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/AbstractStory.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/AbstractStory.java new file mode 100644 index 0000000000..ce3c98d07e --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/AbstractStory.java @@ -0,0 +1,45 @@ +package com.baeldung.rest.jbehave; + +import org.jbehave.core.configuration.Configuration; +import org.jbehave.core.configuration.MostUsefulConfiguration; +import org.jbehave.core.io.LoadFromClasspath; +import org.jbehave.core.junit.JUnitStories; +import org.jbehave.core.reporters.StoryReporterBuilder; +import org.jbehave.core.steps.InjectableStepsFactory; +import org.jbehave.core.steps.InstanceStepsFactory; + +import java.util.Arrays; +import java.util.List; + +import static org.jbehave.core.io.CodeLocations.codeLocationFromClass; +import static org.jbehave.core.reporters.Format.CONSOLE; + +/** + * @author aiet + */ +public abstract class AbstractStory extends JUnitStories { + + abstract String storyName(); + + @Override + public Configuration configuration() { + return new MostUsefulConfiguration() + .useStoryLoader(new LoadFromClasspath(this.getClass())) + .useStoryReporterBuilder(new StoryReporterBuilder() + .withCodeLocation(codeLocationFromClass(this.getClass())) + .withFormats(CONSOLE)); + } + + abstract Object stepInstance(); + + @Override + public InjectableStepsFactory stepsFactory() { + return new InstanceStepsFactory(configuration(), stepInstance()); + } + + @Override + protected List storyPaths() { + return Arrays.asList(storyName()); + } + +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserNotFoundSteps.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserNotFoundSteps.java new file mode 100644 index 0000000000..54d3b0b155 --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserNotFoundSteps.java @@ -0,0 +1,59 @@ +package com.baeldung.rest.jbehave; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.HttpClientBuilder; +import org.jbehave.core.annotations.Given; +import org.jbehave.core.annotations.Then; +import org.jbehave.core.annotations.When; + +import java.io.IOException; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.apache.http.HttpStatus.SC_NOT_FOUND; +import static org.junit.Assert.assertTrue; + +public class GithubUserNotFoundSteps { + + private String api; + private String nonExistentUser; + private int githubResponseCode; + + @Given("github user profile api") + public void givenGithubUserProfileApi() { + api = "https://api.github.com/users/%s"; + } + + @Given("a random non-existent username") + public void givenANonexistentUsername() { + nonExistentUser = randomAlphabetic(8); + } + + @When("I look for the random user via the api") + public void whenILookForTheUserViaTheApi() throws IOException { + githubResponseCode = getGithubUserProfile(api, nonExistentUser) + .getStatusLine() + .getStatusCode(); + } + + @When("I look for $user via the api") + public void whenILookForSomeNonExistentUserViaTheApi(String user) throws IOException { + githubResponseCode = getGithubUserProfile(api, user) + .getStatusLine() + .getStatusCode(); + } + + static HttpResponse getGithubUserProfile(String api, String username) throws IOException { + HttpUriRequest request = new HttpGet(String.format(api, username)); + return HttpClientBuilder + .create() + .build() + .execute(request); + } + + @Then("github respond: 404 not found") + public void thenGithubRespond404NotFound() { + assertTrue(SC_NOT_FOUND == githubResponseCode); + } +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserNotFoundStoryLiveTest.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserNotFoundStoryLiveTest.java new file mode 100644 index 0000000000..f681fb085a --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserNotFoundStoryLiveTest.java @@ -0,0 +1,18 @@ +package com.baeldung.rest.jbehave; + +/** + * @author aiet + */ +public class GithubUserNotFoundStoryLiveTest extends AbstractStory { + + @Override + String storyName() { + return "github_user_not_found.story"; + } + + @Override + Object stepInstance() { + return new GithubUserNotFoundSteps(); + } + +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponseMediaTypeSteps.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponseMediaTypeSteps.java new file mode 100644 index 0000000000..a1a9aceee5 --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponseMediaTypeSteps.java @@ -0,0 +1,40 @@ +package com.baeldung.rest.jbehave; + +import org.apache.http.entity.ContentType; +import org.jbehave.core.annotations.Given; +import org.jbehave.core.annotations.Then; +import org.jbehave.core.annotations.When; + +import java.io.IOException; + +import static com.baeldung.rest.jbehave.GithubUserNotFoundSteps.getGithubUserProfile; +import static org.junit.Assert.assertEquals; + +public class GithubUserResponseMediaTypeSteps { + + private String api; + private String validUser; + private String mediaType; + + @Given("github user profile api") + public void givenGithubUserProfileApi() { + api = "https://api.github.com/users/%s"; + } + + @Given("a valid username") + public void givenAValidUsername() { + validUser = "eugenp"; + } + + @When("I look for the user via the api") + public void whenILookForTheUserViaTheApi() throws IOException { + mediaType = ContentType + .getOrDefault(getGithubUserProfile(api, validUser).getEntity()) + .getMimeType(); + } + + @Then("github respond data of type json") + public void thenGithubRespondDataOfTypeJson() { + assertEquals("application/json", mediaType); + } +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponseMediaTypeStoryLiveTest.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponseMediaTypeStoryLiveTest.java new file mode 100644 index 0000000000..c14f7aad75 --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponseMediaTypeStoryLiveTest.java @@ -0,0 +1,18 @@ +package com.baeldung.rest.jbehave; + +/** + * @author aiet + */ +public class GithubUserResponseMediaTypeStoryLiveTest extends AbstractStory { + + @Override + String storyName() { + return "github_user_response_mediatype.story"; + } + + @Override + Object stepInstance() { + return new GithubUserResponseMediaTypeSteps(); + } + +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponsePayloadSteps.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponsePayloadSteps.java new file mode 100644 index 0000000000..d9401a5d00 --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponsePayloadSteps.java @@ -0,0 +1,40 @@ +package com.baeldung.rest.jbehave; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.HttpClientBuilder; +import org.baeldung.rest.GitHubUser; +import org.baeldung.rest.RetrieveUtil; +import org.hamcrest.Matchers; +import org.jbehave.core.annotations.Given; +import org.jbehave.core.annotations.Then; +import org.jbehave.core.annotations.When; + +import java.io.IOException; + +import static com.baeldung.rest.jbehave.GithubUserNotFoundSteps.getGithubUserProfile; +import static org.hamcrest.MatcherAssert.assertThat; + +public class GithubUserResponsePayloadSteps { + + private String api; + private GitHubUser resource; + + @Given("github user profile api") + public void givenGithubUserProfileApi() { + api = "https://api.github.com/users/%s"; + } + + @When("I look for $user via the api") + public void whenILookForEugenpViaTheApi(String user) throws IOException { + HttpResponse httpResponse = getGithubUserProfile(api, user); + resource = RetrieveUtil.retrieveResourceFromResponse(httpResponse, GitHubUser.class); + } + + @Then("github's response contains a 'login' payload same as $username") + public void thenGithubsResponseContainsAloginPayloadSameAsEugenp(String username) { + assertThat(username, Matchers.is(resource.getLogin())); + } + +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponsePayloadStoryLiveTest.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponsePayloadStoryLiveTest.java new file mode 100644 index 0000000000..cd7974869a --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponsePayloadStoryLiveTest.java @@ -0,0 +1,18 @@ +package com.baeldung.rest.jbehave; + +/** + * @author aiet + */ +public class GithubUserResponsePayloadStoryLiveTest extends AbstractStory { + + @Override + String storyName() { + return "github_user_response_payload.story"; + } + + @Override + Object stepInstance() { + return new GithubUserResponsePayloadSteps(); + } + +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/IncreaseSteps.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/IncreaseSteps.java new file mode 100644 index 0000000000..3bc6fb2aa2 --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/IncreaseSteps.java @@ -0,0 +1,34 @@ +package com.baeldung.rest.jbehave; + +import org.jbehave.core.annotations.Given; +import org.jbehave.core.annotations.Then; +import org.jbehave.core.annotations.When; + +import java.util.Random; + +import static org.junit.Assert.assertTrue; + +public class IncreaseSteps { + private int counter; + private int previousValue; + + @Given("a counter") + public void aCounter() { + } + + @Given("the counter has any integral value") + public void counterHasAnyIntegralValue() { + counter = new Random().nextInt(); + previousValue = counter; + } + + @When("the user increases the counter") + public void increasesTheCounter() { + counter++; + } + + @Then("the value of the counter must be 1 greater than previous value") + public void theValueOfTheCounterMustBe1Greater() { + assertTrue(1 == counter - previousValue); + } +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/IncreaseStoryLiveTest.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/IncreaseStoryLiveTest.java new file mode 100644 index 0000000000..9033dbfbdc --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/IncreaseStoryLiveTest.java @@ -0,0 +1,38 @@ +package com.baeldung.rest.jbehave; + +import org.jbehave.core.configuration.Configuration; +import org.jbehave.core.configuration.MostUsefulConfiguration; +import org.jbehave.core.io.LoadFromClasspath; +import org.jbehave.core.junit.JUnitStories; +import org.jbehave.core.reporters.StoryReporterBuilder; +import org.jbehave.core.steps.InjectableStepsFactory; +import org.jbehave.core.steps.InstanceStepsFactory; + +import java.util.Arrays; +import java.util.List; + +import static org.jbehave.core.io.CodeLocations.codeLocationFromClass; +import static org.jbehave.core.reporters.Format.CONSOLE; + +public class IncreaseStoryLiveTest extends JUnitStories { + + @Override + public Configuration configuration() { + return new MostUsefulConfiguration() + .useStoryLoader(new LoadFromClasspath(this.getClass())) + .useStoryReporterBuilder(new StoryReporterBuilder() + .withCodeLocation(codeLocationFromClass(this.getClass())) + .withFormats(CONSOLE)); + } + + @Override + public InjectableStepsFactory stepsFactory() { + return new InstanceStepsFactory(configuration(), new IncreaseSteps()); + } + + @Override + protected List storyPaths() { + return Arrays.asList("increase.story"); + } + +} diff --git a/rest-testing/src/test/resources/github_user_not_found.story b/rest-testing/src/test/resources/github_user_not_found.story new file mode 100644 index 0000000000..1ab6920eee --- /dev/null +++ b/rest-testing/src/test/resources/github_user_not_found.story @@ -0,0 +1,19 @@ +Meta: + +Narrative: +As a user +I want to look up a non-existent user's profile on github +So that I can be sure that the username can not be found on github + +Scenario: when a user checks a non-existent user on github, github would respond 'not found' + +Given github user profile api +And a random non-existent username +When I look for the random user via the api +Then github respond: 404 not found + +When I look for eugenp1 via the api +Then github respond: 404 not found + +When I look for eugenp2 via the api +Then github respond: 404 not found diff --git a/rest-testing/src/test/resources/github_user_response_mediatype.story b/rest-testing/src/test/resources/github_user_response_mediatype.story new file mode 100644 index 0000000000..7c4a0b9e2d --- /dev/null +++ b/rest-testing/src/test/resources/github_user_response_mediatype.story @@ -0,0 +1,13 @@ +Meta: + +Narrative: +As a user +I want to look up a valid user's profile on github +So that I can know that github responds data of type json + +Scenario: when a user checks a valid user's profile on github, github would respond json data + +Given github user profile api +And a valid username +When I look for the user via the api +Then github respond data of type json \ No newline at end of file diff --git a/rest-testing/src/test/resources/github_user_response_payload.story b/rest-testing/src/test/resources/github_user_response_payload.story new file mode 100644 index 0000000000..788b43eba6 --- /dev/null +++ b/rest-testing/src/test/resources/github_user_response_payload.story @@ -0,0 +1,12 @@ +Meta: + +Narrative: +As a user +I want to look up a valid user's profile on github +So that I can know the login payload should be the same as username + +Scenario: when a user checks a valid user's profile on github, github's response json should include a login payload with the same username + +Given github user profile api +When I look for eugenp via the api +Then github's response contains a 'login' payload same as eugenp diff --git a/rest-testing/src/test/resources/increase.story b/rest-testing/src/test/resources/increase.story new file mode 100644 index 0000000000..fef91298bc --- /dev/null +++ b/rest-testing/src/test/resources/increase.story @@ -0,0 +1,15 @@ +JBehave Story - An increase test + +Meta: + +Narrative: +As a user +I want to increase a counter +So that I can have the counter's value increase by 1 + +Scenario: when a user increases a counter, its value is increased by 1 + +Given a counter +And the counter has any integral value +When the user increases the counter +Then the value of the counter must be 1 greater than previous value \ No newline at end of file diff --git a/spring-5/pom.xml b/spring-5/pom.xml index 2c96bae9bc..ec55a878c7 100644 --- a/spring-5/pom.xml +++ b/spring-5/pom.xml @@ -1,6 +1,6 @@ + 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 @@ -15,7 +15,7 @@ org.springframework.boot spring-boot-starter-parent 2.0.0.BUILD-SNAPSHOT - + @@ -58,11 +58,39 @@ h2 runtime + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.version} + + + org.springframework + spring-test + ${spring.test.version} + org.springframework.boot spring-boot-starter-test test + + org.junit.jupiter + junit-jupiter-engine + ${junit.jupiter.version} + test + + + org.junit.platform + junit-platform-surefire-provider + ${junit.platform.version} + test + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + @@ -92,7 +120,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.19.1 + ${maven-surefire-plugin.version} methods true @@ -143,6 +171,10 @@ UTF-8 UTF-8 1.8 + 1.0.0-M3 + 5.0.0-M3 + 4.3.7.RELEASE + 2.19.1 diff --git a/spring-5/src/main/java/com/baeldung/jupiter/MethodParameterFactory.java b/spring-5/src/main/java/com/baeldung/jupiter/MethodParameterFactory.java new file mode 100644 index 0000000000..85bd505d11 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/jupiter/MethodParameterFactory.java @@ -0,0 +1,46 @@ +package com.baeldung.jupiter; + +import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.SynthesizingMethodParameter; +import org.springframework.util.Assert; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; + +abstract class MethodParameterFactory { + + private MethodParameterFactory() { + } + + public static MethodParameter createMethodParameter(Parameter parameter) { + Assert.notNull(parameter, "Parameter must not be null"); + Executable executable = parameter.getDeclaringExecutable(); + if (executable instanceof Method) { + return new MethodParameter((Method) executable, getIndex(parameter)); + } + return new MethodParameter((Constructor) executable, getIndex(parameter)); + } + + public static SynthesizingMethodParameter createSynthesizingMethodParameter(Parameter parameter) { + Assert.notNull(parameter, "Parameter must not be null"); + Executable executable = parameter.getDeclaringExecutable(); + if (executable instanceof Method) { + return new SynthesizingMethodParameter((Method) executable, getIndex(parameter)); + } + throw new UnsupportedOperationException("Cannot create a SynthesizingMethodParameter for a constructor parameter: " + parameter); + } + + private static int getIndex(Parameter parameter) { + Assert.notNull(parameter, "Parameter must not be null"); + Executable executable = parameter.getDeclaringExecutable(); + Parameter[] parameters = executable.getParameters(); + for (int i = 0; i < parameters.length; i++) { + if (parameters[i] == parameter) { + return i; + } + } + throw new IllegalStateException(String.format("Failed to resolve index of parameter [%s] in executable [%s]", parameter, executable.toGenericString())); + } +} diff --git a/spring-5/src/main/java/com/baeldung/jupiter/ParameterAutowireUtils.java b/spring-5/src/main/java/com/baeldung/jupiter/ParameterAutowireUtils.java new file mode 100644 index 0000000000..068c6af381 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/jupiter/ParameterAutowireUtils.java @@ -0,0 +1,46 @@ +package com.baeldung.jupiter; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.config.DependencyDescriptor; +import org.springframework.context.ApplicationContext; +import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.AnnotatedElementUtils; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.Optional; + +import static org.springframework.core.annotation.AnnotatedElementUtils.hasAnnotation; + +abstract class ParameterAutowireUtils { + + private ParameterAutowireUtils() { + } + + public static boolean isAutowirable(Parameter parameter) { + return ApplicationContext.class.isAssignableFrom(parameter.getType()) || hasAnnotation(parameter, Autowired.class) || hasAnnotation(parameter, Qualifier.class) || hasAnnotation(parameter, Value.class); + } + + public static Object resolveDependency(Parameter parameter, Class containingClass, ApplicationContext applicationContext) { + + boolean required = findMergedAnnotation(parameter, Autowired.class) + .map(Autowired::required) + .orElse(true); + MethodParameter methodParameter = (parameter.getDeclaringExecutable() instanceof Method ? MethodParameterFactory.createSynthesizingMethodParameter(parameter) : MethodParameterFactory.createMethodParameter(parameter)); + DependencyDescriptor descriptor = new DependencyDescriptor(methodParameter, required); + descriptor.setContainingClass(containingClass); + + return applicationContext + .getAutowireCapableBeanFactory() + .resolveDependency(descriptor, null); + } + + private static Optional findMergedAnnotation(AnnotatedElement element, Class annotationType) { + + return Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(element, annotationType)); + } +} diff --git a/spring-5/src/main/java/com/baeldung/jupiter/SpringExtension.java b/spring-5/src/main/java/com/baeldung/jupiter/SpringExtension.java new file mode 100644 index 0000000000..08fa0c4768 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/jupiter/SpringExtension.java @@ -0,0 +1,94 @@ +package com.baeldung.jupiter; + +import org.junit.jupiter.api.extension.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.test.context.TestContextManager; +import org.springframework.util.Assert; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; + +public class SpringExtension implements BeforeAllCallback, AfterAllCallback, TestInstancePostProcessor, BeforeEachCallback, AfterEachCallback, ParameterResolver { + + private static final ExtensionContext.Namespace namespace = ExtensionContext.Namespace.create(SpringExtension.class); + + @Override + public void beforeAll(ContainerExtensionContext context) throws Exception { + getTestContextManager(context).beforeTestClass(); + } + + @Override + public void afterAll(ContainerExtensionContext context) throws Exception { + try { + getTestContextManager(context).afterTestClass(); + } finally { + context + .getStore(namespace) + .remove(context + .getTestClass() + .get()); + } + } + + @Override + public void postProcessTestInstance(Object testInstance, ExtensionContext context) throws Exception { + getTestContextManager(context).prepareTestInstance(testInstance); + } + + @Override + public void beforeEach(TestExtensionContext context) throws Exception { + Object testInstance = context.getTestInstance(); + Method testMethod = context + .getTestMethod() + .get(); + getTestContextManager(context).beforeTestMethod(testInstance, testMethod); + } + + @Override + public void afterEach(TestExtensionContext context) throws Exception { + Object testInstance = context.getTestInstance(); + Method testMethod = context + .getTestMethod() + .get(); + Throwable testException = context + .getTestException() + .orElse(null); + getTestContextManager(context).afterTestMethod(testInstance, testMethod, testException); + } + + @Override + public boolean supports(ParameterContext parameterContext, ExtensionContext extensionContext) { + Parameter parameter = parameterContext.getParameter(); + Executable executable = parameter.getDeclaringExecutable(); + return (executable instanceof Constructor && AnnotatedElementUtils.hasAnnotation(executable, Autowired.class)) || ParameterAutowireUtils.isAutowirable(parameter); + } + + @Override + public Object resolve(ParameterContext parameterContext, ExtensionContext extensionContext) { + Parameter parameter = parameterContext.getParameter(); + Class testClass = extensionContext + .getTestClass() + .get(); + ApplicationContext applicationContext = getApplicationContext(extensionContext); + return ParameterAutowireUtils.resolveDependency(parameter, testClass, applicationContext); + } + + private ApplicationContext getApplicationContext(ExtensionContext context) { + return getTestContextManager(context) + .getTestContext() + .getApplicationContext(); + } + + private TestContextManager getTestContextManager(ExtensionContext context) { + Assert.notNull(context, "ExtensionContext must not be null"); + Class testClass = context + .getTestClass() + .get(); + ExtensionContext.Store store = context.getStore(namespace); + return store.getOrComputeIfAbsent(testClass, TestContextManager::new, TestContextManager.class); + } +} diff --git a/spring-5/src/main/java/com/baeldung/jupiter/SpringJUnit5Config.java b/spring-5/src/main/java/com/baeldung/jupiter/SpringJUnit5Config.java new file mode 100644 index 0000000000..e8b9cc500f --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/jupiter/SpringJUnit5Config.java @@ -0,0 +1,40 @@ +package com.baeldung.jupiter; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.annotation.AliasFor; +import org.springframework.test.context.ContextConfiguration; + +import java.lang.annotation.*; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration +@Documented +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface SpringJUnit5Config { + + @AliasFor(annotation = ContextConfiguration.class, attribute = "classes") + Class[] value() default {}; + + @AliasFor(annotation = ContextConfiguration.class) + Class[] classes() default {}; + + @AliasFor(annotation = ContextConfiguration.class) + String[] locations() default {}; + + @AliasFor(annotation = ContextConfiguration.class) + Class>[] initializers() default {}; + + @AliasFor(annotation = ContextConfiguration.class) + boolean inheritLocations() default true; + + @AliasFor(annotation = ContextConfiguration.class) + boolean inheritInitializers() default true; + + @AliasFor(annotation = ContextConfiguration.class) + String name() default ""; +} diff --git a/spring-5/src/main/java/com/baeldung/jupiter/TestConfig.java b/spring-5/src/main/java/com/baeldung/jupiter/TestConfig.java new file mode 100644 index 0000000000..a29f77c5df --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/jupiter/TestConfig.java @@ -0,0 +1,20 @@ +package com.baeldung.jupiter; + +import com.baeldung.web.reactive.Task; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; + +@Configuration +public class TestConfig { + + @Bean + static PropertySourcesPlaceholderConfigurer placeholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + @Bean + Task taskName() { + return new Task("taskName", 1); + } +} diff --git a/spring-5/src/main/java/com/baeldung/web/reactive/Task.java b/spring-5/src/main/java/com/baeldung/web/reactive/Task.java new file mode 100644 index 0000000000..84193d9354 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/web/reactive/Task.java @@ -0,0 +1,31 @@ +package com.baeldung.web.reactive; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Task { + + private final String name; + + private final int id; + + public Task(@JsonProperty("name") String name, @JsonProperty("id") int id) { + this.name = name; + this.id = id; + } + + public String getName() { + return this.name; + } + + public int getId() { + return this.id; + } + + @Override + public String toString() { + return "Task{" + + "name='" + name + '\'' + + ", id=" + id + + '}'; + } +} diff --git a/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java b/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java index bf28ed1e7d..dda25f46f7 100644 --- a/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java +++ b/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java @@ -7,7 +7,7 @@ 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.test.web.reactive.server.WebTestClient; +//import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.BodyInserters; @@ -15,140 +15,141 @@ import org.springframework.web.reactive.function.BodyInserters; import static org.springframework.web.reactive.function.BodyInserters.fromObject; import static org.springframework.web.reactive.function.BodyInserters.fromResource; +// TODO The class does not compile, WebTestClient cannot be resolved. Missing dependency? public class FunctionalWebApplicationIntegrationTest { - private static WebTestClient client; - private static WebServer server; - - @BeforeClass - public static void setup() throws Exception { - server = new FunctionalWebApplication().start(); - client = WebTestClient - .bindToServer() - .baseUrl("http://localhost:" + server.getPort()) - .build(); - } - - @AfterClass - public static void destroy() { - server.stop(); - } - - @Test - public void givenRouter_whenGetTest_thenGotHelloWorld() throws Exception { - client - .get() - .uri("/test") - .exchange() - .expectStatus() - .isOk() - .expectBody(String.class) - .value() - .isEqualTo("helloworld"); - } - - @Test - public void givenIndexFilter_whenRequestRoot_thenRewrittenToTest() throws Exception { - client - .get() - .uri("/") - .exchange() - .expectStatus() - .isOk() - .expectBody(String.class) - .value() - .isEqualTo("helloworld"); - } - - @Test - public void givenLoginForm_whenPostValidToken_thenSuccess() throws Exception { - MultiValueMap formData = new LinkedMultiValueMap<>(1); - formData.add("user", "baeldung"); - formData.add("token", "you_know_what_to_do"); - - client - .post() - .uri("/login") - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .exchange(BodyInserters.fromFormData(formData)) - .expectStatus() - .isOk() - .expectBody(String.class) - .value() - .isEqualTo("welcome back!"); - } - - @Test - public void givenLoginForm_whenRequestWithInvalidToken_thenFail() throws Exception { - MultiValueMap formData = new LinkedMultiValueMap<>(2); - formData.add("user", "baeldung"); - formData.add("token", "try_again"); - - client - .post() - .uri("/login") - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .exchange(BodyInserters.fromFormData(formData)) - .expectStatus() - .isBadRequest(); - } - - @Test - public void givenUploadForm_whenRequestWithMultipartData_thenSuccess() throws Exception { - Resource resource = new ClassPathResource("/baeldung-weekly.png"); - client - .post() - .uri("/upload") - .contentType(MediaType.MULTIPART_FORM_DATA) - .exchange(fromResource(resource)) - .expectStatus() - .isOk() - .expectBody(String.class) - .value() - .isEqualTo(String.valueOf(resource.contentLength())); - } - - @Test - public void givenActors_whenAddActor_thenAdded() throws Exception { - client - .get() - .uri("/actor") - .exchange() - .expectStatus() - .isOk() - .expectBody(Actor.class) - .list() - .hasSize(2); - - client - .post() - .uri("/actor") - .exchange(fromObject(new Actor("Clint", "Eastwood"))) - .expectStatus() - .isOk(); - - client - .get() - .uri("/actor") - .exchange() - .expectStatus() - .isOk() - .expectBody(Actor.class) - .list() - .hasSize(3); - } - - @Test - public void givenResources_whenAccess_thenGot() throws Exception { - client - .get() - .uri("/files/hello.txt") - .exchange() - .expectStatus() - .isOk() - .expectBody(String.class) - .value() - .isEqualTo("hello"); - } +// private static WebTestClient client; +// private static WebServer server; +// +// @BeforeClass +// public static void setup() throws Exception { +// server = new FunctionalWebApplication().start(); +// client = WebTestClient +// .bindToServer() +// .baseUrl("http://localhost:" + server.getPort()) +// .build(); +// } +// +// @AfterClass +// public static void destroy() { +// server.stop(); +// } +// +// @Test +// public void givenRouter_whenGetTest_thenGotHelloWorld() throws Exception { +// client +// .get() +// .uri("/test") +// .exchange() +// .expectStatus() +// .isOk() +// .expectBody(String.class) +// .value() +// .isEqualTo("helloworld"); +// } +// +// @Test +// public void givenIndexFilter_whenRequestRoot_thenRewrittenToTest() throws Exception { +// client +// .get() +// .uri("/") +// .exchange() +// .expectStatus() +// .isOk() +// .expectBody(String.class) +// .value() +// .isEqualTo("helloworld"); +// } +// +// @Test +// public void givenLoginForm_whenPostValidToken_thenSuccess() throws Exception { +// MultiValueMap formData = new LinkedMultiValueMap<>(1); +// formData.add("user", "baeldung"); +// formData.add("token", "you_know_what_to_do"); +// +// client +// .post() +// .uri("/login") +// .contentType(MediaType.APPLICATION_FORM_URLENCODED) +// .exchange(BodyInserters.fromFormData(formData)) +// .expectStatus() +// .isOk() +// .expectBody(String.class) +// .value() +// .isEqualTo("welcome back!"); +// } +// +// @Test +// public void givenLoginForm_whenRequestWithInvalidToken_thenFail() throws Exception { +// MultiValueMap formData = new LinkedMultiValueMap<>(2); +// formData.add("user", "baeldung"); +// formData.add("token", "try_again"); +// +// client +// .post() +// .uri("/login") +// .contentType(MediaType.APPLICATION_FORM_URLENCODED) +// .exchange(BodyInserters.fromFormData(formData)) +// .expectStatus() +// .isBadRequest(); +// } +// +// @Test +// public void givenUploadForm_whenRequestWithMultipartData_thenSuccess() throws Exception { +// Resource resource = new ClassPathResource("/baeldung-weekly.png"); +// client +// .post() +// .uri("/upload") +// .contentType(MediaType.MULTIPART_FORM_DATA) +// .exchange(fromResource(resource)) +// .expectStatus() +// .isOk() +// .expectBody(String.class) +// .value() +// .isEqualTo(String.valueOf(resource.contentLength())); +// } +// +// @Test +// public void givenActors_whenAddActor_thenAdded() throws Exception { +// client +// .get() +// .uri("/actor") +// .exchange() +// .expectStatus() +// .isOk() +// .expectBody(Actor.class) +// .list() +// .hasSize(2); +// +// client +// .post() +// .uri("/actor") +// .exchange(fromObject(new Actor("Clint", "Eastwood"))) +// .expectStatus() +// .isOk(); +// +// client +// .get() +// .uri("/actor") +// .exchange() +// .expectStatus() +// .isOk() +// .expectBody(Actor.class) +// .list() +// .hasSize(3); +// } +// +// @Test +// public void givenResources_whenAccess_thenGot() throws Exception { +// client +// .get() +// .uri("/files/hello.txt") +// .exchange() +// .expectStatus() +// .isOk() +// .expectBody(String.class) +// .value() +// .isEqualTo("hello"); +// } } diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ComposedAnnotationTests.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ComposedAnnotationTests.java new file mode 100644 index 0000000000..d15857e0a5 --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ComposedAnnotationTests.java @@ -0,0 +1,38 @@ +package com.baeldung.jupiter; + +import com.baeldung.web.reactive.Task; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@SpringJUnit5Config(TestConfig.class) +@DisplayName("@SpringJUnit5Config Tests") +class Spring5JUnit5ComposedAnnotationTests { + + @Autowired + Task task; + + @Autowired + List tasks; + + @Test + @DisplayName("ApplicationContext injected into method") + void givenAMethodName_whenInjecting_thenApplicationContextInjectedIntoMethod(ApplicationContext applicationContext) { + assertNotNull(applicationContext, "ApplicationContext should have been injected into method by Spring"); + assertEquals(this.task, applicationContext.getBean("taskName", Task.class)); + } + + @Test + @DisplayName("Spring @Beans injected into fields") + void givenAnObject_whenInjecting_thenSpringBeansInjected() { + assertNotNull(task, "Task should have been @Autowired by Spring"); + assertEquals("taskName", task.getName(), "Task's name"); + assertEquals(1, tasks.size(), "Number of Tasks in context"); + } +} diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ParallelTest.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ParallelTest.java new file mode 100644 index 0000000000..a060b78c93 --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ParallelTest.java @@ -0,0 +1,29 @@ +package com.baeldung.jupiter; + +import com.baeldung.IntegrationTestExample1; +import com.baeldung.IntegrationTestExample2; +import org.junit.experimental.ParallelComputer; +import org.junit.jupiter.api.Test; +import org.junit.runner.Computer; +import org.junit.runner.JUnitCore; + +public class Spring5JUnit5ParallelTest { + + @Test + public void givenTwoTestClasses_whenJUnitRunParallel_thenTheTestsExecutingParallel() { + final Class[] classes = { + IntegrationTestExample1.class, IntegrationTestExample2.class + }; + + JUnitCore.runClasses(new ParallelComputer(true, true), classes); + } + + @Test + public void givenTwoTestClasses_whenJUnitRunParallel_thenTheTestsExecutingLinear() { + final Class[] classes = { + IntegrationTestExample1.class, IntegrationTestExample2.class + }; + + JUnitCore.runClasses(new Computer(), classes); + } +} \ No newline at end of file diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5Tests.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5Tests.java new file mode 100644 index 0000000000..c4c3148b1e --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5Tests.java @@ -0,0 +1,27 @@ +package com.baeldung.jupiter; + +import com.baeldung.web.reactive.Task; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.Test; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = TestConfig.class) +class Spring5JUnit5Tests { + + @Autowired + Task task; + + @Test + void givenAMethodName_whenInjecting_thenApplicationContextInjectedIntoMetho(ApplicationContext applicationContext) { + assertNotNull(applicationContext, "ApplicationContext should have been injected by Spring"); + assertEquals(this.task, applicationContext.getBean("taskName", Task.class)); + } +} diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5Java8NewFeaturesTest.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5Java8NewFeaturesTest.java new file mode 100644 index 0000000000..36adf1f7ff --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5Java8NewFeaturesTest.java @@ -0,0 +1,33 @@ +package com.baeldung.jupiter; + +import org.junit.jupiter.api.Test; +import java.util.function.Supplier; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class Spring5Java8NewFeaturesTest { + + @FunctionalInterface + public interface FunctionalInterfaceExample { + Result reverseString(Input input); + } + + public class StringUtils{ + public FunctionalInterfaceExample + functionLambdaString = s -> { + return Pattern.compile(" +").splitAsStream(s) + .map(word->new StringBuilder(word).reverse()) + .collect(Collectors.joining(" ")); + }; + } + + @Test + void givenStringUtil_whenSupplierCall_thenFunctionalInterfaceReverseString() + throws Exception { + Supplier stringUtilsSupplier = StringUtils::new; + + assertEquals(stringUtilsSupplier.get().functionLambdaString + .reverseString("hello"), "olleh"); + } +} diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5ReactiveServerClientTest.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5ReactiveServerClientTest.java new file mode 100644 index 0000000000..2252c255ee --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5ReactiveServerClientTest.java @@ -0,0 +1,110 @@ +package com.baeldung.jupiter; + +import com.baeldung.web.reactive.Task; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpMethod; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.http.server.reactive.HttpHandler; +import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.ClientRequest; +import org.springframework.web.reactive.function.client.ExchangeFunction; +import org.springframework.web.reactive.function.client.ExchangeFunctions; +import org.springframework.web.reactive.function.client.WebClient; +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 reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.ipc.netty.NettyContext; +import reactor.ipc.netty.http.server.HttpServer; + +import java.net.URI; +import java.time.Duration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RequestPredicates.POST; + +public class Spring5ReactiveServerClientTest { + + private static NettyContext nettyContext; + + @BeforeAll + public static void setUp() throws Exception { + HttpServer server = HttpServer.create("localhost", 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); + nettyContext = server + .newHandler(adapter) + .block(); + } + + @AfterAll + public static void shutDown() { + nettyContext.dispose(); + } + + @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-all/pom.xml b/spring-all/pom.xml index a3a51425e2..1b12d7e42c 100644 --- a/spring-all/pom.xml +++ b/spring-all/pom.xml @@ -106,6 +106,12 @@ guava ${guava.version} + + + net.sf.jasperreports + jasperreports + ${jasperreports.version} + @@ -296,6 +302,7 @@ 3.1.3 3.4 3.6.1 + 6.4.0 diff --git a/spring-all/src/main/java/org/baeldung/jasperreports/Main.java b/spring-all/src/main/java/org/baeldung/jasperreports/Main.java new file mode 100644 index 0000000000..79aee100a6 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/jasperreports/Main.java @@ -0,0 +1,39 @@ +package org.baeldung.jasperreports; + +import java.util.HashMap; +import java.util.Map; +import org.baeldung.jasperreports.config.JasperRerportsSimpleConfig; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +public class Main { + public static void main(String[] args) { + + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + ctx.register(JasperRerportsSimpleConfig.class); + ctx.refresh(); + + SimpleReportFiller simpleReportFiller = ctx.getBean(SimpleReportFiller.class); + simpleReportFiller.setReportFileName("employeeEmailReport.jrxml"); + simpleReportFiller.compileReport(); + + simpleReportFiller.setReportFileName("employeeReport.jrxml"); + simpleReportFiller.compileReport(); + + Map parameters = new HashMap<>(); + parameters.put("title", "Employee Report Example"); + parameters.put("minSalary", 15000.0); + parameters.put("condition", " LAST_NAME ='Smith' ORDER BY FIRST_NAME"); + + simpleReportFiller.setParameters(parameters); + simpleReportFiller.fillReport(); + + SimpleReportExporter simpleExporter = ctx.getBean(SimpleReportExporter.class); + simpleExporter.setJasperPrint(simpleReportFiller.getJasperPrint()); + + simpleExporter.exportToPdf("employeeReport.pdf", "baeldung"); + simpleExporter.exportToXlsx("employeeReport.xlsx", "Employee Data"); + simpleExporter.exportToCsv("employeeReport.csv"); + simpleExporter.exportToHtml("employeeReport.html"); + + } +} diff --git a/spring-all/src/main/java/org/baeldung/jasperreports/SimpleReportExporter.java b/spring-all/src/main/java/org/baeldung/jasperreports/SimpleReportExporter.java new file mode 100644 index 0000000000..1252dcda4d --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/jasperreports/SimpleReportExporter.java @@ -0,0 +1,115 @@ +package org.baeldung.jasperreports; + +import java.util.logging.Level; +import java.util.logging.Logger; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.export.HtmlExporter; +import net.sf.jasperreports.engine.export.JRCsvExporter; +import net.sf.jasperreports.engine.export.JRPdfExporter; +import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter; +import net.sf.jasperreports.export.SimpleExporterInput; +import net.sf.jasperreports.export.SimpleHtmlExporterOutput; +import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput; +import net.sf.jasperreports.export.SimplePdfExporterConfiguration; +import net.sf.jasperreports.export.SimplePdfReportConfiguration; +import net.sf.jasperreports.export.SimpleWriterExporterOutput; +import net.sf.jasperreports.export.SimpleXlsxReportConfiguration; +import org.springframework.stereotype.Component; + +@Component +public class SimpleReportExporter { + + private JasperPrint jasperPrint; + + public SimpleReportExporter() { + } + + public SimpleReportExporter (JasperPrint jasperPrint){ + this.jasperPrint = jasperPrint; + } + + public JasperPrint getJasperPrint() { + return jasperPrint; + } + + public void setJasperPrint(JasperPrint jasperPrint) { + this.jasperPrint = jasperPrint; + } + + + + public void exportToPdf(String fileName, String author) { + + // print report to file + JRPdfExporter exporter = new JRPdfExporter(); + + exporter.setExporterInput(new SimpleExporterInput(jasperPrint)); + exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(fileName)); + + SimplePdfReportConfiguration reportConfig = new SimplePdfReportConfiguration(); + reportConfig.setSizePageToContent(true); + reportConfig.setForceLineBreakPolicy(false); + + SimplePdfExporterConfiguration exportConfig = new SimplePdfExporterConfiguration(); + exportConfig.setMetadataAuthor(author); + exportConfig.setEncrypted(true); + exportConfig.setAllowedPermissionsHint("PRINTING"); + + exporter.setConfiguration(reportConfig); + exporter.setConfiguration(exportConfig); + try { + exporter.exportReport(); + } catch (JRException ex) { + Logger.getLogger(SimpleReportFiller.class.getName()) + .log(Level.SEVERE, null, ex); + } + } + + public void exportToXlsx(String fileName,String sheetName) { + JRXlsxExporter exporter = new JRXlsxExporter(); + + exporter.setExporterInput(new SimpleExporterInput(jasperPrint)); + exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(fileName)); + + SimpleXlsxReportConfiguration reportConfig = new SimpleXlsxReportConfiguration(); + reportConfig.setSheetNames(new String[]{sheetName}); + + exporter.setConfiguration(reportConfig); + + try { + exporter.exportReport(); + } catch (JRException ex) { + Logger.getLogger(SimpleReportFiller.class.getName()) + .log(Level.SEVERE, null, ex); + } + } + + public void exportToCsv(String fileName) { + JRCsvExporter exporter = new JRCsvExporter(); + + exporter.setExporterInput(new SimpleExporterInput(jasperPrint)); + exporter.setExporterOutput(new SimpleWriterExporterOutput(fileName)); + + try { + exporter.exportReport(); + } catch (JRException ex) { + Logger.getLogger(SimpleReportFiller.class.getName()) + .log(Level.SEVERE, null, ex); + } + } + + public void exportToHtml(String fileName) { + HtmlExporter exporter = new HtmlExporter(); + + exporter.setExporterInput(new SimpleExporterInput(jasperPrint)); + exporter.setExporterOutput(new SimpleHtmlExporterOutput(fileName)); + + try { + exporter.exportReport(); + } catch (JRException ex) { + Logger.getLogger(SimpleReportFiller.class.getName()) + .log(Level.SEVERE, null, ex); + } + } +} diff --git a/spring-all/src/main/java/org/baeldung/jasperreports/SimpleReportFiller.java b/spring-all/src/main/java/org/baeldung/jasperreports/SimpleReportFiller.java new file mode 100644 index 0000000000..ae675dd280 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/jasperreports/SimpleReportFiller.java @@ -0,0 +1,90 @@ +package org.baeldung.jasperreports; + +import java.io.InputStream; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.sql.DataSource; +import net.sf.jasperreports.engine.JRException; +import net.sf.jasperreports.engine.JasperCompileManager; +import net.sf.jasperreports.engine.JasperFillManager; +import net.sf.jasperreports.engine.JasperPrint; +import net.sf.jasperreports.engine.JasperReport; +import net.sf.jasperreports.engine.util.JRSaver; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SimpleReportFiller { + + private String reportFileName; + + private JasperReport jasperReport; + + private JasperPrint jasperPrint; + + @Autowired + private DataSource dataSource; + + private Map parameters; + + public SimpleReportFiller() { + parameters = new HashMap<>(); + } + + public void prepareReport() { + compileReport(); + fillReport(); + } + + public void compileReport() { + try { + InputStream reportStream = getClass().getResourceAsStream("/".concat(reportFileName)); + jasperReport = JasperCompileManager.compileReport(reportStream); + JRSaver.saveObject(jasperReport, reportFileName.replace(".jrxml", ".jasper")); + } catch (JRException ex) { + Logger.getLogger(SimpleReportFiller.class.getName()) + .log(Level.SEVERE, null, ex); + } + } + + public void fillReport() { + try { + jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, dataSource.getConnection()); + } catch (JRException | SQLException ex) { + Logger.getLogger(SimpleReportFiller.class.getName()) + .log(Level.SEVERE, null, ex); + } + } + + public DataSource getDataSource() { + return dataSource; + } + + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + + public Map getParameters() { + return parameters; + } + + public void setParameters(Map parameters) { + this.parameters = parameters; + } + + public String getReportFileName() { + return reportFileName; + } + + public void setReportFileName(String reportFileName) { + this.reportFileName = reportFileName; + } + + public JasperPrint getJasperPrint() { + return jasperPrint; + } + +} diff --git a/spring-all/src/main/java/org/baeldung/jasperreports/config/JasperRerportsSimpleConfig.java b/spring-all/src/main/java/org/baeldung/jasperreports/config/JasperRerportsSimpleConfig.java new file mode 100644 index 0000000000..90fc96cdbb --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/jasperreports/config/JasperRerportsSimpleConfig.java @@ -0,0 +1,32 @@ +package org.baeldung.jasperreports.config; + +import javax.sql.DataSource; +import org.baeldung.jasperreports.SimpleReportExporter; +import org.baeldung.jasperreports.SimpleReportFiller; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; + +@Configuration +public class JasperRerportsSimpleConfig { + + @Bean + public DataSource dataSource() { + return new EmbeddedDatabaseBuilder() + .setType(EmbeddedDatabaseType.HSQL) + .addScript("classpath:employee-schema.sql") + .build(); + } + + @Bean + public SimpleReportFiller reportFiller() { + return new SimpleReportFiller(); + } + + @Bean + public SimpleReportExporter reportExporter() { + return new SimpleReportExporter(); + } + +} diff --git a/spring-all/src/main/resources/employee-schema.sql b/spring-all/src/main/resources/employee-schema.sql new file mode 100644 index 0000000000..011ff162e1 --- /dev/null +++ b/spring-all/src/main/resources/employee-schema.sql @@ -0,0 +1,27 @@ +CREATE TABLE EMPLOYEE( + ID INT NOT NULL PRIMARY KEY, + FIRST_NAME VARCHAR(255), + LAST_NAME VARCHAR(255), + SALARY DOUBLE, +); + +CREATE TABLE EMAIL( + ID INT NOT NULL PRIMARY KEY, + ID_EMPLOYEE VARCHAR(255), + ADDRESS VARCHAR(255) +); + +INSERT INTO EMPLOYEE VALUES (1, 'John', 'Doe', 10000.10); +INSERT INTO EMPLOYEE VALUES (2, 'Kevin', 'Smith', 20000.20); +INSERT INTO EMPLOYEE VALUES (3, 'Kim', 'Smith', 30000.30); +INSERT INTO EMPLOYEE VALUES (4, 'Stephen', 'Torvalds', 40000.40); +INSERT INTO EMPLOYEE VALUES (5, 'Christian', 'Reynolds', 50000.50); + +INSERT INTO EMAIL VALUES (1, 1, 'john@baeldung.com'); +INSERT INTO EMAIL VALUES (2, 1, 'john@gmail.com'); +INSERT INTO EMAIL VALUES (3, 2, 'kevin@baeldung.com'); +INSERT INTO EMAIL VALUES (4, 3, 'kim@baeldung.com'); +INSERT INTO EMAIL VALUES (5, 3, 'kim@gmail.com'); +INSERT INTO EMAIL VALUES (6, 3, 'kim@outlook.com'); +INSERT INTO EMAIL VALUES (7, 4, 'stephen@baeldung.com'); +INSERT INTO EMAIL VALUES (8, 5, 'christian@gmail.com'); diff --git a/spring-all/src/main/resources/employeeEmailReport.jrxml b/spring-all/src/main/resources/employeeEmailReport.jrxml new file mode 100644 index 0000000000..ad4aaaac90 --- /dev/null +++ b/spring-all/src/main/resources/employeeEmailReport.jrxml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/spring-all/src/main/resources/employeeReport.jrxml b/spring-all/src/main/resources/employeeReport.jrxml new file mode 100644 index 0000000000..3d2be226fb --- /dev/null +++ b/spring-all/src/main/resources/employeeReport.jrxml @@ -0,0 +1,51 @@ + + + + + + + + + = $P{minSalary} AND $P!{condition}]]> + + + + + + + <band height="20" splitType="Stretch"> + <textField> + <reportElement x="238" y="0" width="100" height="20"/> + <textElement/> + <textFieldExpression class="java.lang.String"><![CDATA[$P{title}]]></textFieldExpression> + </textField> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-boot/README.MD b/spring-boot/README.MD index beb780ec3c..1874f621b5 100644 --- a/spring-boot/README.MD +++ b/spring-boot/README.MD @@ -16,4 +16,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Using Custom Banners in Spring Boot](http://www.baeldung.com/spring-boot-custom-banners) - [Guide to Internationalization in Spring Boot](http://www.baeldung.com/spring-boot-internationalization) - [Create a Custom FailureAnalyzer with Spring Boot](http://www.baeldung.com/spring-boot-failure-analyzer) +- [Configuring Separate Spring DataSource for Tests](http://www.baeldung.com/spring-testing-separate-data-source) diff --git a/spring-boot/src/main/resources/schema.sql b/spring-boot/src/main/resources/schema.sql index 27859c1652..4cd345c762 100644 --- a/spring-boot/src/main/resources/schema.sql +++ b/spring-boot/src/main/resources/schema.sql @@ -1,3 +1,5 @@ +drop table if exists USERS; + create table USERS( ID int not null AUTO_INCREMENT, NAME varchar(100) not null, diff --git a/spring-boot/src/test/java/org/baeldung/SpringBootApplicationIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/SpringBootApplicationIntegrationTest.java index 87c59a4662..4ce0678bdd 100644 --- a/spring-boot/src/test/java/org/baeldung/SpringBootApplicationIntegrationTest.java +++ b/spring-boot/src/test/java/org/baeldung/SpringBootApplicationIntegrationTest.java @@ -63,4 +63,4 @@ public class SpringBootApplicationIntegrationTest { mockMvc.perform(MockMvcRequestBuilders.get("/entity/findbyversion").header("Version", "1.0.0")).andExpect(MockMvcResultMatchers.status().isOk()).andExpect(MockMvcResultMatchers.content().contentType(contentType)) .andExpect(jsonPath("$.id", equalTo(1))); } -} +} \ No newline at end of file diff --git a/spring-boot/src/test/resources/import.sql b/spring-boot/src/test/resources/import.sql index a382410271..9095b9468c 100644 --- a/spring-boot/src/test/resources/import.sql +++ b/spring-boot/src/test/resources/import.sql @@ -1 +1 @@ -Insert into Foo values(1,'Foo_Name'); \ No newline at end of file +--insert into Foo values(1,'Foo_Name'); \ No newline at end of file diff --git a/spring-boot/src/test/resources/persistence-generic-entity.properties b/spring-boot/src/test/resources/persistence-generic-entity.properties index c60e7488b6..b19304cb1f 100644 --- a/spring-boot/src/test/resources/persistence-generic-entity.properties +++ b/spring-boot/src/test/resources/persistence-generic-entity.properties @@ -1,8 +1,8 @@ jdbc.driverClassName=org.h2.Driver jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 -jdbc.username=sa -jdbc.password=sa +jdbc.user=sa +jdbc.pass=sa hibernate.dialect=org.hibernate.dialect.H2Dialect hibernate.show_sql=true -hibernate.hbm2ddl.auto=create-drop \ No newline at end of file +hibernate.hbm2ddl.auto=create-drop diff --git a/spring-cloud-data-flow/data-flow-server/pom.xml b/spring-cloud-data-flow/data-flow-server/pom.xml index 1ed2d4fb74..bd3b4ab150 100644 --- a/spring-cloud-data-flow/data-flow-server/pom.xml +++ b/spring-cloud-data-flow/data-flow-server/pom.xml @@ -77,39 +77,4 @@ - - - integration - - - - org.apache.maven.plugins - maven-surefire-plugin - - - integration-test - - test - - - - **/*LiveTest.java - - - **/*IntegrationTest.java - - - - - - - json - - - - - - - - diff --git a/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml b/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml index 4d19741210..de76c86a24 100644 --- a/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml +++ b/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml @@ -35,11 +35,6 @@ spring-cloud-starter-feign 1.2.5.RELEASE - - org.springframework.boot - spring-boot-starter-thymeleaf - 1.5.2.RELEASE - junit junit diff --git a/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/GreetingApplication.java b/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/GreetingApplication.java index e8beebeadf..8a1662999b 100644 --- a/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/GreetingApplication.java +++ b/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/GreetingApplication.java @@ -5,16 +5,9 @@ */ package com.baeldung.spring.cloud.greeting; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; -import org.springframework.cloud.netflix.feign.EnableFeignClients; -import org.springframework.stereotype.Controller; -import org.springframework.ui.Model; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @EnableDiscoveryClient diff --git a/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/GreetingController.java b/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/GreetingController.java index d701a2c762..d98e22f822 100644 --- a/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/GreetingController.java +++ b/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/GreetingController.java @@ -6,16 +6,11 @@ package com.baeldung.spring.cloud.greeting; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cloud.netflix.feign.EnableFeignClients; -import org.springframework.stereotype.Controller; - -import org.springframework.ui.Model; 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.bind.annotation.RestController; -@Controller +@RestController public class GreetingController { @Autowired @@ -23,10 +18,9 @@ public class GreetingController { @RequestMapping(value = "/get-greeting", method = RequestMethod.GET) - public String greeting(Model model) { + public String greeting() { - model.addAttribute("greeting", helloWorldClient.HelloWorld()); - return "greeting-view"; + return helloWorldClient.HelloWorld(); } diff --git a/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/HelloWorldClient.java b/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/HelloWorldClient.java index d2b91ca715..c56cb1907a 100644 --- a/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/HelloWorldClient.java +++ b/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/HelloWorldClient.java @@ -5,8 +5,6 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.feign.EnableFeignClients; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.context.annotation.Configuration; -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.ResponseBody; @@ -36,12 +34,6 @@ public class HelloWorldClient { String HelloWorld(); } - /** - * Initiate call to Validation. - * - * @param name - * @return the response - */ public String HelloWorld() { return theClient.HelloWorld(); } diff --git a/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/main/java/com/baeldung/spring/cloud/helloworld/HelloWorldController.java b/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/main/java/com/baeldung/spring/cloud/helloworld/HelloWorldController.java index d5ea84de19..9048e6bed8 100644 --- a/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/main/java/com/baeldung/spring/cloud/helloworld/HelloWorldController.java +++ b/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/main/java/com/baeldung/spring/cloud/helloworld/HelloWorldController.java @@ -5,7 +5,6 @@ */ package com.baeldung.spring.cloud.helloworld; -import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; diff --git a/spring-data-solr/pom.xml b/spring-data-solr/pom.xml index e43b3ff774..fd6c442abf 100644 --- a/spring-data-solr/pom.xml +++ b/spring-data-solr/pom.xml @@ -72,38 +72,4 @@ - - - integration - - - - org.apache.maven.plugins - maven-surefire-plugin - - - integration-test - - test - - - - **/*LiveTest.java - - - **/*IntegrationTest.java - - - - - - - json - - - - - - - \ No newline at end of file diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java index ca8c37175e..b628228b7e 100644 --- a/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java +++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/GreetControllerIntegrationTest.java @@ -21,10 +21,11 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; import com.baeldung.spring.web.config.ApplicationConfig; +import com.baeldung.spring.web.config.WebConfig; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration -@ContextConfiguration(classes = { ApplicationConfig.class }) +@ContextConfiguration(classes = { ApplicationConfig.class, WebConfig.class }) public class GreetControllerIntegrationTest { @Autowired diff --git a/spring-mvc-no-xml/.gitignore b/spring-mvc-no-xml/.gitignore deleted file mode 100644 index 83c05e60c8..0000000000 --- a/spring-mvc-no-xml/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -*.class - -#folders# -/target -/neoDb* -/data -/src/main/webapp/WEB-INF/classes -*/META-INF/* - -# Packaged files # -*.jar -*.war -*.ear \ No newline at end of file diff --git a/spring-mvc-no-xml/README.md b/spring-mvc-no-xml/README.md deleted file mode 100644 index 208cb35f78..0000000000 --- a/spring-mvc-no-xml/README.md +++ /dev/null @@ -1,9 +0,0 @@ -========= - -## Spring MVC with NO XML Configuration Example Project - -###The Course -The "REST With Spring" Classes: http://bit.ly/restwithspring - -### Relevant Articles: -- diff --git a/spring-mvc-no-xml/pom.xml b/spring-mvc-no-xml/pom.xml deleted file mode 100644 index 4437661199..0000000000 --- a/spring-mvc-no-xml/pom.xml +++ /dev/null @@ -1,175 +0,0 @@ - - 4.0.0 - com.baeldung - 0.1-SNAPSHOT - spring-mvc-no-xml - - spring-mvc-no-xml - war - - - - - - - org.springframework - spring-web - ${org.springframework.version} - - - org.springframework - spring-webmvc - ${org.springframework.version} - - - - - - javax.servlet - javax.servlet-api - ${javax.servlet-api.version} - provided - - - - javax.servlet - jstl - ${jstl.version} - runtime - - - - - - org.slf4j - slf4j-api - ${org.slf4j.version} - - - ch.qos.logback - logback-classic - ${logback.version} - - - - org.slf4j - jcl-over-slf4j - ${org.slf4j.version} - - - - org.slf4j - log4j-over-slf4j - ${org.slf4j.version} - - - - - - junit - junit - ${junit.version} - test - - - - org.hamcrest - hamcrest-core - ${org.hamcrest.version} - test - - - org.hamcrest - hamcrest-library - ${org.hamcrest.version} - test - - - - org.mockito - mockito-core - ${mockito.version} - test - - - - - - spring-mvc-no-xml - - - src/main/resources - true - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - 1.8 - 1.8 - - - - - org.apache.maven.plugins - maven-war-plugin - ${maven-war-plugin.version} - - false - - - - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - - - - - - - - - - - - - - - - - 4.3.4.RELEASE - - - 1.7.21 - 1.1.7 - - - 1.3 - 4.12 - 1.10.19 - - 3.1.0 - 1.2 - - 4.4.5 - 4.5.2 - - 2.9.0 - - - 3.6.0 - 2.6 - 2.19.1 - 2.7 - 1.6.1 - - - - \ No newline at end of file diff --git a/spring-mvc-no-xml/src/main/java/org/baeldung/servlet/WebAppNew.java b/spring-mvc-no-xml/src/main/java/org/baeldung/servlet/WebAppNew.java deleted file mode 100644 index 2422f2110a..0000000000 --- a/spring-mvc-no-xml/src/main/java/org/baeldung/servlet/WebAppNew.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.baeldung.servlet; - -import javax.servlet.ServletRegistration.Dynamic; - -import org.baeldung.spring.ClientWebConfig; -import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; - -/** - * Further reading:
- * - http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-container-config
- * - http://geowarin.wordpress.com/2013/01/23/complete-example-of-a-spring-mvc-3-2-project/
- * - http://www.objectpartners.com/2012/01/16/introduction-to-servlet-3-0/
- */ -public class WebAppNew extends AbstractAnnotationConfigDispatcherServletInitializer { - - public WebAppNew() { - super(); - } - - // API - - @Override - protected Class[] getRootConfigClasses() { - return null; - } - - @Override - protected Class[] getServletConfigClasses() { - return new Class[] { ClientWebConfig.class }; - } - - @Override - protected String[] getServletMappings() { - return new String[] { "/" }; - } - - @Override - protected void customizeRegistration(final Dynamic registration) { - super.customizeRegistration(registration); - } - -} diff --git a/spring-mvc-no-xml/src/main/java/org/baeldung/servlet/WebAppOld.java b/spring-mvc-no-xml/src/main/java/org/baeldung/servlet/WebAppOld.java deleted file mode 100644 index 85c67c094d..0000000000 --- a/spring-mvc-no-xml/src/main/java/org/baeldung/servlet/WebAppOld.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.baeldung.servlet; - -// public class WebApp implements WebApplicationInitializer { -// -// public WebApp() { -// super(); -// } -// -// // API -// -// @Override -// public void onStartup(final ServletContext servletContext) throws ServletException { -// final AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext(); -// root.setServletContext(servletContext); -// root.scan("org.baeldung.spring"); -// root.refresh(); -// -// final Dynamic servlet = servletContext.addServlet("mvc", new DispatcherServlet(root)); -// servlet.setLoadOnStartup(1); -// servlet.addMapping("/"); -// } -// -// } diff --git a/spring-mvc-no-xml/src/main/java/org/baeldung/spring/ClientWebConfig.java b/spring-mvc-no-xml/src/main/java/org/baeldung/spring/ClientWebConfig.java deleted file mode 100644 index eaefb0984b..0000000000 --- a/spring-mvc-no-xml/src/main/java/org/baeldung/spring/ClientWebConfig.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.baeldung.spring; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.ViewResolver; -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.springframework.web.servlet.view.InternalResourceViewResolver; -import org.springframework.web.servlet.view.JstlView; - -@EnableWebMvc -@Configuration -public class ClientWebConfig extends WebMvcConfigurerAdapter { - - public ClientWebConfig() { - super(); - } - - // API - - @Override - public void addViewControllers(final ViewControllerRegistry registry) { - super.addViewControllers(registry); - - registry.addViewController("/sample.html"); - } - - @Bean - public ViewResolver viewResolver() { - final InternalResourceViewResolver bean = new InternalResourceViewResolver(); - - bean.setViewClass(JstlView.class); - bean.setPrefix("/WEB-INF/view/"); - bean.setSuffix(".jsp"); - - return bean; - } -} \ No newline at end of file diff --git a/spring-mvc-no-xml/src/main/resources/logback.xml b/spring-mvc-no-xml/src/main/resources/logback.xml deleted file mode 100644 index 1146dade63..0000000000 --- a/spring-mvc-no-xml/src/main/resources/logback.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - web - %date [%thread] %-5level %logger{36} - %message%n - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-mvc-no-xml/src/main/resources/webSecurityConfig.xml b/spring-mvc-no-xml/src/main/resources/webSecurityConfig.xml deleted file mode 100644 index febac349b0..0000000000 --- a/spring-mvc-no-xml/src/main/resources/webSecurityConfig.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-mvc-no-xml/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-mvc-no-xml/src/main/webapp/WEB-INF/mvc-servlet.xml deleted file mode 100644 index 4ba9642448..0000000000 --- a/spring-mvc-no-xml/src/main/webapp/WEB-INF/mvc-servlet.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/spring-mvc-no-xml/src/main/webapp/WEB-INF/view/sample.jsp b/spring-mvc-no-xml/src/main/webapp/WEB-INF/view/sample.jsp deleted file mode 100644 index 7cc14b5dcd..0000000000 --- a/spring-mvc-no-xml/src/main/webapp/WEB-INF/view/sample.jsp +++ /dev/null @@ -1,7 +0,0 @@ - - - - -

This is the body of the sample view

- - \ No newline at end of file diff --git a/spring-mvc-no-xml/src/main/webapp/WEB-INF/web_old.xml b/spring-mvc-no-xml/src/main/webapp/WEB-INF/web_old.xml deleted file mode 100644 index e2f52148c3..0000000000 --- a/spring-mvc-no-xml/src/main/webapp/WEB-INF/web_old.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - Spring MVC No XML Application - - - - contextClass - - org.springframework.web.context.support.AnnotationConfigWebApplicationContext - - - - contextConfigLocation - org.baeldung.spring - - - - org.springframework.web.context.ContextLoaderListener - - - - - mvc - org.springframework.web.servlet.DispatcherServlet - 1 - - - mvc - / - - - - - - index.html - - - \ No newline at end of file diff --git a/spring-mvc-no-xml/src/test/resources/.gitignore b/spring-mvc-no-xml/src/test/resources/.gitignore deleted file mode 100644 index 83c05e60c8..0000000000 --- a/spring-mvc-no-xml/src/test/resources/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -*.class - -#folders# -/target -/neoDb* -/data -/src/main/webapp/WEB-INF/classes -*/META-INF/* - -# Packaged files # -*.jar -*.war -*.ear \ No newline at end of file diff --git a/spring-security-cache-control/pom.xml b/spring-security-cache-control/pom.xml index f25e85012e..b24b9db484 100644 --- a/spring-security-cache-control/pom.xml +++ b/spring-security-cache-control/pom.xml @@ -81,6 +81,9 @@ + UTF-8 + 1.8 + 3.1.0 2.9.0 diff --git a/spring-security-rest-full/README.md b/spring-security-rest-full/README.md index faeeac1ec2..e7f543a407 100644 --- a/spring-security-rest-full/README.md +++ b/spring-security-rest-full/README.md @@ -29,6 +29,7 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com - [Changing Spring Model Parameters with Handler Interceptor](http://www.baeldung.com/spring-model-parameters-with-handler-interceptor) - [Introduction to Spring MVC HandlerInterceptor](http://www.baeldung.com/spring-mvc-handlerinterceptor) - [Using a Custom Spring MVC’s Handler Interceptor to Manage Sessions](http://www.baeldung.com/spring-mvc-custom-handler-interceptor) +- [Bootstrap a Web Application with Spring 4](http://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration) ### Build the Project ```