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
+
@@ -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 extends ApplicationContextInitializer
+ extends ConfigurableApplicationContext>>[] 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}]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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
```