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/algorithms/src/main/java/com/baeldung/algorithms/primechecker/BigIntegerPrimeChecker.java b/algorithms/src/main/java/com/baeldung/algorithms/primechecker/BigIntegerPrimeChecker.java index bd4708b661..752e659fa3 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/primechecker/BigIntegerPrimeChecker.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/primechecker/BigIntegerPrimeChecker.java @@ -2,10 +2,10 @@ package com.baeldung.algorithms.primechecker; import java.math.BigInteger; -public class BigIntegerPrimeChecker implements PrimeChecker{ +public class BigIntegerPrimeChecker implements PrimeChecker{ @Override - public boolean isPrime(int number) { + public boolean isPrime(Long number) { BigInteger bigInt = BigInteger.valueOf(number); return bigInt.isProbablePrime(100); } diff --git a/algorithms/src/main/java/com/baeldung/algorithms/primechecker/BruteForcePrimeChecker.java b/algorithms/src/main/java/com/baeldung/algorithms/primechecker/BruteForcePrimeChecker.java index 0dfcfa1505..47ffb3e224 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/primechecker/BruteForcePrimeChecker.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/primechecker/BruteForcePrimeChecker.java @@ -1,12 +1,15 @@ package com.baeldung.algorithms.primechecker; import java.util.stream.IntStream; +import java.util.stream.LongStream; -public class BruteForcePrimeChecker implements PrimeChecker{ +public class BruteForcePrimeChecker implements PrimeChecker{ @Override - public boolean isPrime(int number) { - return IntStream.range(2, number).noneMatch(n -> (number % n == 0)); + public boolean isPrime(Integer number) { + + return number > 2 ? IntStream.range(2, number) + .noneMatch(n -> (number % n == 0)) : false; } diff --git a/algorithms/src/main/java/com/baeldung/algorithms/primechecker/OptimisedPrimeChecker.java b/algorithms/src/main/java/com/baeldung/algorithms/primechecker/OptimisedPrimeChecker.java index f7e3e09be0..06ae4acc7f 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/primechecker/OptimisedPrimeChecker.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/primechecker/OptimisedPrimeChecker.java @@ -1,13 +1,14 @@ package com.baeldung.algorithms.primechecker; import java.util.stream.IntStream; +import java.util.stream.LongStream; -public class OptimisedPrimeChecker implements PrimeChecker{ +public class OptimisedPrimeChecker implements PrimeChecker{ @Override - public boolean isPrime(int number) { - return IntStream.range(2, (int)Math.sqrt(number) + 1) - .noneMatch(n -> (number % n == 0)); + public boolean isPrime(Integer number) { + return number > 2 ? IntStream.rangeClosed(2, (int) Math.sqrt(number)) + .noneMatch(n -> (number % n == 0)) : false; } diff --git a/algorithms/src/main/java/com/baeldung/algorithms/primechecker/PrimeChecker.java b/algorithms/src/main/java/com/baeldung/algorithms/primechecker/PrimeChecker.java index f31af1ca4f..5f7a15a939 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/primechecker/PrimeChecker.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/primechecker/PrimeChecker.java @@ -1,6 +1,6 @@ package com.baeldung.algorithms.primechecker; -public interface PrimeChecker { +public interface PrimeChecker { - public boolean isPrime( int number ); + public boolean isPrime( T number ); } diff --git a/algorithms/src/main/java/com/baeldung/algorithms/primechecker/PrimesPrimeChecker.java b/algorithms/src/main/java/com/baeldung/algorithms/primechecker/PrimesPrimeChecker.java index ee66d5d2ab..08b095cb79 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/primechecker/PrimesPrimeChecker.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/primechecker/PrimesPrimeChecker.java @@ -2,10 +2,10 @@ package com.baeldung.algorithms.primechecker; import org.apache.commons.math3.primes.Primes; -public class PrimesPrimeChecker implements PrimeChecker{ +public class PrimesPrimeChecker implements PrimeChecker{ @Override - public boolean isPrime(int number) { + public boolean isPrime(Integer number) { return Primes.isPrime(number); } diff --git a/algorithms/src/test/java/com/baeldung/algorithms/primechecker/BigIntegerPrimeCheckerTest.java b/algorithms/src/test/java/com/baeldung/algorithms/primechecker/BigIntegerPrimeCheckerTest.java index 95eb85749d..8980397c68 100644 --- a/algorithms/src/test/java/com/baeldung/algorithms/primechecker/BigIntegerPrimeCheckerTest.java +++ b/algorithms/src/test/java/com/baeldung/algorithms/primechecker/BigIntegerPrimeCheckerTest.java @@ -9,18 +9,20 @@ import com.baeldung.algorithms.primechecker.PrimeChecker; public class BigIntegerPrimeCheckerTest { - PrimeChecker primeChecker = new BigIntegerPrimeChecker(); + BigIntegerPrimeChecker primeChecker = new BigIntegerPrimeChecker(); @Test public void givenPrimeNumber_whenCheckIsPrime_thenTrue(){ - assertTrue(primeChecker.isPrime(13)); - assertTrue(primeChecker.isPrime(1009)); + assertTrue(primeChecker.isPrime(13l)); + assertTrue(primeChecker.isPrime(1009L)); + assertTrue(primeChecker.isPrime(74207281L)); } @Test public void givenNonPrimeNumber_whenCheckIsPrime_thenFalse(){ - assertTrue(!primeChecker.isPrime(50)); - assertTrue(!primeChecker.isPrime(1001)); + assertTrue(!primeChecker.isPrime(50L)); + assertTrue(!primeChecker.isPrime(1001L)); + assertTrue(!primeChecker.isPrime(74207282L)); } } diff --git a/algorithms/src/test/java/com/baeldung/algorithms/primechecker/OptimisedPrimeCheckerTest.java b/algorithms/src/test/java/com/baeldung/algorithms/primechecker/OptimisedPrimeCheckerTest.java index 21ad55467f..64ecae7cc3 100644 --- a/algorithms/src/test/java/com/baeldung/algorithms/primechecker/OptimisedPrimeCheckerTest.java +++ b/algorithms/src/test/java/com/baeldung/algorithms/primechecker/OptimisedPrimeCheckerTest.java @@ -9,7 +9,7 @@ import com.baeldung.algorithms.primechecker.PrimeChecker; public class OptimisedPrimeCheckerTest { - PrimeChecker primeChecker = new OptimisedPrimeChecker(); + OptimisedPrimeChecker primeChecker = new OptimisedPrimeChecker(); @Test public void givenPrimeNumber_whenCheckIsPrime_thenTrue(){ diff --git a/algorithms/src/test/java/com/baeldung/algorithms/primechecker/PrimesPrimeCheckerTest.java b/algorithms/src/test/java/com/baeldung/algorithms/primechecker/PrimesPrimeCheckerTest.java index 63de593b44..cb294d6643 100644 --- a/algorithms/src/test/java/com/baeldung/algorithms/primechecker/PrimesPrimeCheckerTest.java +++ b/algorithms/src/test/java/com/baeldung/algorithms/primechecker/PrimesPrimeCheckerTest.java @@ -8,7 +8,7 @@ import com.baeldung.algorithms.primechecker.PrimeChecker; import com.baeldung.algorithms.primechecker.PrimesPrimeChecker; public class PrimesPrimeCheckerTest { - PrimeChecker primeChecker = new PrimesPrimeChecker(); + PrimesPrimeChecker primeChecker = new PrimesPrimeChecker(); @Test public void givenPrimeNumber_whenCheckIsPrime_thenTrue() { diff --git a/apache-fop/pom.xml b/apache-fop/pom.xml index 6f89497a7d..6075c23d21 100644 --- a/apache-fop/pom.xml +++ b/apache-fop/pom.xml @@ -101,9 +101,7 @@ org.dbdoclet herold - 6.1.0 - system - ${basedir}/src/test/resources/jars/herold.jar + 8.0.4 @@ -140,6 +138,8 @@ maven-surefire-plugin ${maven-surefire-plugin.version} + 3 + true **/*IntegrationTest.java **/*LiveTest.java diff --git a/apache-fop/src/test/java/org/baeldung/java/ApacheFOPConvertHTMLIntegrationTest.java b/apache-fop/src/test/java/org/baeldung/java/ApacheFOPConvertHTMLIntegrationTest.java index 99487c8fdf..5e2da6fd1e 100644 --- a/apache-fop/src/test/java/org/baeldung/java/ApacheFOPConvertHTMLIntegrationTest.java +++ b/apache-fop/src/test/java/org/baeldung/java/ApacheFOPConvertHTMLIntegrationTest.java @@ -19,21 +19,21 @@ import javax.xml.transform.stream.StreamSource; import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.xmlgraphics.util.MimeConstants; -import org.dbdoclet.trafo.html.docbook.DocBookTransformer; +import org.dbdoclet.trafo.html.docbook.HtmlDocBookTrafo; import org.dbdoclet.trafo.script.Script; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.tidy.Tidy; public class ApacheFOPConvertHTMLIntegrationTest { - private String inputFile = "src/test/resources/input.html"; - private String style = "src/test/resources/xhtml2fo.xsl"; - private String style1 = "src/test/resources/docbook-xsl/fo/docbook.xsl"; - private String output_jtidy = "src/test/resources/output_jtidy.pdf"; - private String output_html2fo = "src/test/resources/output_html2fo.pdf"; - private String output_herold = "src/test/resources/output_herold.pdf"; - private String foFile = "src/test/resources/input.fo"; - private String xmlFile = "src/test/resources/input.xml"; + private final String inputFile = "src/test/resources/input.html"; + private final String style = "src/test/resources/xhtml2fo.xsl"; + private final String style1 = "src/test/resources/docbook-xsl/fo/docbook.xsl"; + private final String output_jtidy = "src/test/resources/output_jtidy.pdf"; + private final String output_html2fo = "src/test/resources/output_html2fo.pdf"; + private final String output_herold = "src/test/resources/output_herold.pdf"; + private final String foFile = "src/test/resources/input.fo"; + private final String xmlFile = "src/test/resources/input.xml"; @Test public void whenTransformHTMLToPDFUsingJTidy_thenCorrect() throws Exception { @@ -114,8 +114,9 @@ public class ApacheFOPConvertHTMLIntegrationTest { private void fromHTMLTOXMLUsingHerold() throws Exception { final Script script = new Script(); - final DocBookTransformer transformer = new DocBookTransformer(); - transformer.setScript(script); - transformer.convert(new FileInputStream(inputFile), new FileOutputStream(xmlFile)); + final HtmlDocBookTrafo transformer = new HtmlDocBookTrafo(); + transformer.setInputStream(new FileInputStream(inputFile)); + transformer.setOutputStream(new FileOutputStream(xmlFile)); + transformer.transform(script); } } diff --git a/apache-fop/src/test/java/org/baeldung/java/ApacheFOPHeroldLiveTest.java b/apache-fop/src/test/java/org/baeldung/java/ApacheFOPHeroldLiveTest.java index 9e71cd9c16..8496222394 100644 --- a/apache-fop/src/test/java/org/baeldung/java/ApacheFOPHeroldLiveTest.java +++ b/apache-fop/src/test/java/org/baeldung/java/ApacheFOPHeroldLiveTest.java @@ -10,6 +10,7 @@ import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.HttpURLConnection; import java.net.URL; import javax.xml.transform.Result; @@ -25,19 +26,15 @@ import org.apache.fop.apps.Fop; import org.apache.fop.apps.FopFactory; import org.apache.xmlgraphics.util.MimeConstants; import org.dbdoclet.trafo.TrafoScriptManager; -import org.dbdoclet.trafo.html.docbook.DocBookTransformer; +import org.dbdoclet.trafo.html.docbook.HtmlDocBookTrafo; import org.dbdoclet.trafo.script.Script; import org.junit.Test; import org.w3c.dom.Document; public class ApacheFOPHeroldLiveTest { - private String[] inputUrls = {// @formatter:off - "http://www.baeldung.com/2011/10/20/bootstraping-a-web-application-with-spring-3-1-and-java-based-configuration-part-1/", - "http://www.baeldung.com/2011/10/25/building-a-restful-web-service-with-spring-3-1-and-java-based-configuration-part-2/", - "http://www.baeldung.com/2011/10/31/securing-a-restful-web-service-with-spring-security-3-1-part-3/", - "http://www.baeldung.com/spring-security-basic-authentication", - "http://www.baeldung.com/spring-security-digest-authentication", - "http://www.baeldung.com/2011/11/20/basic-and-digest-authentication-for-a-restful-service-with-spring-security-3-1/", + private final String[] inputUrls = {// @formatter:off + // "http://www.baeldung.com/spring-security-basic-authentication", + "http://www.baeldung.com/spring-security-digest-authentication" //"http://www.baeldung.com/spring-httpmessageconverter-rest", //"http://www.baeldung.com/2011/11/06/restful-web-service-discoverability-part-4/", //"http://www.baeldung.com/2011/11/13/rest-service-discoverability-with-spring-part-5/", @@ -49,10 +46,10 @@ public class ApacheFOPHeroldLiveTest { //"http://www.baeldung.com/2013/01/18/testing-rest-with-multiple-mime-types/" }; // @formatter:on - private String style_file = "src/test/resources/docbook-xsl/fo/docbook.xsl"; - private String output_file = "src/test/resources/final_output.pdf"; - private String xmlInput = "src/test/resources/input.xml"; - private String xmlOutput = "src/test/resources/output.xml"; + private final String style_file = "src/test/resources/docbook-xsl/fo/docbook.xsl"; + private final String output_file = "src/test/resources/final_output.pdf"; + private final String xmlInput = "src/test/resources/input.xml"; + private final String xmlOutput = "src/test/resources/output.xml"; // tests @@ -75,10 +72,11 @@ public class ApacheFOPHeroldLiveTest { final TrafoScriptManager mgr = new TrafoScriptManager(); final File profileFile = new File("src/test/resources/default.her"); script = mgr.parseScript(profileFile); - final DocBookTransformer transformer = new DocBookTransformer(); - transformer.setScript(script); + final HtmlDocBookTrafo transformer = new HtmlDocBookTrafo(); + transformer.setInputStream(getInputStream(input)); + transformer.setOutputStream(new FileOutputStream(xmlInput, append)); - transformer.convert(getInputStream(input), new FileOutputStream(xmlInput, append)); + transformer.transform(script); } private Document fromXMLFileToFO() throws Exception { @@ -112,7 +110,9 @@ public class ApacheFOPHeroldLiveTest { private InputStream getInputStream(final String input) throws IOException { final URL url = new URL(input); - return url.openStream(); + final HttpURLConnection httpcon = (HttpURLConnection) url.openConnection(); + httpcon.addRequestProperty("User-Agent", "Mozilla/4.0"); + return httpcon.getInputStream(); } private void fixXML(final String input, final String output) throws IOException { @@ -127,7 +127,7 @@ public class ApacheFOPHeroldLiveTest { if (line.contains("info>")) { writer.write(line.replace("info>", "section>")); - } else if (!((line.startsWith(" 4)) { + } else if (!((line.startsWith(" 4))) { writer.write(line.replaceAll("xml:id=\"", "xml:id=\"" + count)); } writer.write("\n"); diff --git a/apache-fop/src/test/resources/jars/herold.jar b/apache-fop/src/test/resources/jars/herold.jar deleted file mode 100644 index ef5d052f36..0000000000 Binary files a/apache-fop/src/test/resources/jars/herold.jar and /dev/null differ diff --git a/apache-poi/temp.xlsx b/apache-poi/temp.xlsx index 12a9b2656c..431a8a662c 100644 Binary files a/apache-poi/temp.xlsx and b/apache-poi/temp.xlsx differ diff --git a/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImpl.java b/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImpl.java new file mode 100644 index 0000000000..46eee4883a --- /dev/null +++ b/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImpl.java @@ -0,0 +1,82 @@ +package com.baeldung.java9.reactive; + +import java.util.ArrayList; +import java.util.concurrent.Flow.Subscriber; +import java.util.concurrent.Flow.Subscription; + +public class BaeldungBatchSubscriberImpl implements Subscriber { + private Subscription subscription; + private boolean completed = false; + private int counter; + private ArrayList buffer; + public static final int BUFFER_SIZE = 5; + + public BaeldungBatchSubscriberImpl() { + buffer = new ArrayList(); + } + + public boolean isCompleted() { + return completed; + } + + public void setCompleted(boolean completed) { + this.completed = completed; + } + + public int getCounter() { + return counter; + } + + public void setCounter(int counter) { + this.counter = counter; + } + + @Override + public void onSubscribe(Subscription subscription) { + this.subscription = subscription; + subscription.request(BUFFER_SIZE); + } + + @Override + public void onNext(String item) { + buffer.add(item); + // if buffer is full, process the items. + if (buffer.size() >= BUFFER_SIZE) { + processBuffer(); + } + //request more items. + subscription.request(1); + } + + private void processBuffer() { + if (buffer.isEmpty()) + return; + // Process all items in the buffer. Here, we just print it and sleep for 1 second. + System.out.print("Processed items: "); + buffer.stream() + .forEach(item -> { + System.out.print(" " + item); + }); + System.out.println(); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + counter = counter + buffer.size(); + buffer.clear(); + } + + @Override + public void onError(Throwable t) { + t.printStackTrace(); + } + + @Override + public void onComplete() { + completed = true; + // process any remaining items in buffer before + processBuffer(); + subscription.cancel(); + } +} diff --git a/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungSubscriberImpl.java b/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungSubscriberImpl.java new file mode 100644 index 0000000000..bacd777255 --- /dev/null +++ b/core-java-9/src/main/java/com/baeldung/java9/reactive/BaeldungSubscriberImpl.java @@ -0,0 +1,55 @@ +package com.baeldung.java9.reactive; + +import java.util.concurrent.Flow.Subscriber; +import java.util.concurrent.Flow.Subscription; + +public class BaeldungSubscriberImpl implements Subscriber { + private Subscription subscription; + private boolean completed = false; + private int counter; + + public boolean isCompleted() { + return completed; + } + + public void setCompleted(boolean completed) { + this.completed = completed; + } + + public int getCounter() { + return counter; + } + + public void setCounter(int counter) { + this.counter = counter; + } + + @Override + public void onSubscribe(Subscription subscription) { + this.subscription = subscription; + subscription.request(1); + } + + @Override + public void onNext(String item) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + counter++; + System.out.println("Processed item : " + item); + subscription.request(1); + } + + @Override + public void onError(Throwable t) { + t.printStackTrace(); + } + + @Override + public void onComplete() { + completed = true; + subscription.cancel(); + } +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImplTest.java b/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImplTest.java new file mode 100644 index 0000000000..388d3efdd8 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungBatchSubscriberImplTest.java @@ -0,0 +1,75 @@ +package com.baeldung.java9.reactive; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.SubmissionPublisher; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.Stopwatch; + +public class BaeldungBatchSubscriberImplTest { + + private static final int ITEM_SIZE = 10; + private SubmissionPublisher publisher; + private BaeldungBatchSubscriberImpl subscriber; + + @Before + public void initialize() { + this.publisher = new SubmissionPublisher(ForkJoinPool.commonPool(), 6); + this.subscriber = new BaeldungBatchSubscriberImpl(); + publisher.subscribe(subscriber); + } + + @Rule + public Stopwatch stopwatch = new Stopwatch() { + + }; + + @Test + public void testReactiveStreamCount() { + IntStream.range(0, ITEM_SIZE) + .forEach(item -> publisher.submit(item + "")); + publisher.close(); + + do { + // wait for subscribers to complete all processing. + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } while (!subscriber.isCompleted()); + + int count = subscriber.getCounter(); + + assertEquals(ITEM_SIZE, count); + } + + @Test + public void testReactiveStreamTime() { + IntStream.range(0, ITEM_SIZE) + .forEach(item -> publisher.submit(item + "")); + publisher.close(); + + do { + // wait for subscribers to complete all processing. + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } while (!subscriber.isCompleted()); + + // The runtime in seconds should be equal to the number of items in each batch. + assertTrue(stopwatch.runtime(TimeUnit.SECONDS) >= (ITEM_SIZE / subscriber.BUFFER_SIZE)); + } + +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungSubscriberImplTest.java b/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungSubscriberImplTest.java new file mode 100644 index 0000000000..5638c0a431 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/reactive/BaeldungSubscriberImplTest.java @@ -0,0 +1,100 @@ +package com.baeldung.java9.reactive; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.SubmissionPublisher; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.Stopwatch; + +public class BaeldungSubscriberImplTest { + + private static final int ITEM_SIZE = 10; + private SubmissionPublisher publisher; + private BaeldungSubscriberImpl subscriber; + + @Before + public void initialize() { + // create Publisher with max buffer capacity 3. + this.publisher = new SubmissionPublisher(ForkJoinPool.commonPool(), 3); + this.subscriber = new BaeldungSubscriberImpl(); + publisher.subscribe(subscriber); + } + + @Rule + public Stopwatch stopwatch = new Stopwatch() { + + }; + + @Test + public void testReactiveStreamCount() { + IntStream.range(0, ITEM_SIZE) + .forEach(item -> publisher.submit(item + "")); + publisher.close(); + + do { + // wait for subscribers to complete all processing. + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } while (!subscriber.isCompleted()); + + int count = subscriber.getCounter(); + + assertEquals(ITEM_SIZE, count); + } + + @Test + public void testReactiveStreamTime() { + IntStream.range(0, ITEM_SIZE) + .forEach(item -> publisher.submit(item + "")); + publisher.close(); + + do { + // wait for subscribers to complete all processing. + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } while (!subscriber.isCompleted()); + + // The runtime in seconds should be equal to the number of items. + assertTrue(stopwatch.runtime(TimeUnit.SECONDS) >= ITEM_SIZE); + } + + @Test + public void testReactiveStreamOffer() { + IntStream.range(0, ITEM_SIZE) + .forEach(item -> publisher.offer(item + "", (subscriber, string) -> { + // Returning false means this item will be dropped (no retry), if blocked. + return false; + })); + publisher.close(); + + do { + // wait for subscribers to complete all processing. + try { + Thread.sleep(100); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } while (!subscriber.isCompleted()); + + int count = subscriber.getCounter(); + // Because 10 items were offered and the buffer capacity was 3, few items will not be processed. + assertTrue(ITEM_SIZE > count); + } + +} diff --git a/core-java/README.md b/core-java/README.md index 0861ee7c5e..a7c8b0e855 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -11,6 +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 – 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) @@ -85,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/pom.xml b/core-java/pom.xml index 1212465280..d2fa1cdd2e 100644 --- a/core-java/pom.xml +++ b/core-java/pom.xml @@ -170,7 +170,13 @@ org.javamoney moneta 1.1 - + + + + org.owasp.esapi + esapi + 2.1.0.1 + @@ -391,4 +397,4 @@ - \ No newline at end of file + diff --git a/core-java/src/main/java/com/baeldung/logforging/LogForgingDemo.java b/core-java/src/main/java/com/baeldung/logforging/LogForgingDemo.java new file mode 100644 index 0000000000..84c069a746 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/logforging/LogForgingDemo.java @@ -0,0 +1,28 @@ +package com.baeldung.logforging; + +import org.owasp.esapi.ESAPI; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LogForgingDemo { + + private final Logger logger = LoggerFactory.getLogger(LogForgingDemo.class); + + public void addLog(String amount) { + logger.info("Amount credited = {}", amount); + } + + public static void main(String[] args) { + LogForgingDemo demo = new LogForgingDemo(); + demo.addLog(String.valueOf(300)); + demo.addLog(String.valueOf(300 + "\n\nweb - 2017-04-12 17:47:08,957 [main] INFO Amount reversed successfully")); + demo.addLog(String.valueOf(encode(300 + "\n\nweb - 2017-04-12 17:47:08,957 [main] INFO Amount reversed successfully"))); + } + + public static String encode(String message) { + message = message.replace('\n', '_').replace('\r', '_').replace('\t', '_'); + message = ESAPI.encoder().encodeForHTML(message); + return message; + } + +} diff --git a/core-java/src/main/java/com/baeldung/stringtokenizer/Application.java b/core-java/src/main/java/com/baeldung/stringtokenizer/Application.java deleted file mode 100644 index caa7ef06da..0000000000 --- a/core-java/src/main/java/com/baeldung/stringtokenizer/Application.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.baeldung.stringtokenizer; - -import java.util.ArrayList; -import java.util.List; -import java.util.StringTokenizer; - -public class Application { - - public List getTokens(String str) { - List tokens = new ArrayList(); -// StringTokenizer tokenizer = new StringTokenizer( str ); - StringTokenizer tokenizer = new StringTokenizer( str , "," ); -// StringTokenizer tokenizer = new StringTokenizer( str , "," , true ); - while (tokenizer.hasMoreElements()) { - tokens.add( tokenizer.nextToken() ); -// tokens.add( tokenizer.nextToken( "," ) ); - } - return tokens; - } - -} diff --git a/core-java/src/main/java/com/baeldung/stringtokenizer/MyTokenizer.java b/core-java/src/main/java/com/baeldung/stringtokenizer/MyTokenizer.java new file mode 100644 index 0000000000..130218acc2 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/stringtokenizer/MyTokenizer.java @@ -0,0 +1,52 @@ +package com.baeldung.stringtokenizer; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.StringTokenizer; +import java.util.stream.Collectors; + +public class MyTokenizer { + + public List getTokens(String str) { + List tokens = new ArrayList<>(); + // StringTokenizer tokenizer = new StringTokenizer( str ); + StringTokenizer tokenizer = new StringTokenizer(str, ","); + // StringTokenizer tokenizer = new StringTokenizer( str , "," , true ); + while (tokenizer.hasMoreElements()) { + tokens.add(tokenizer.nextToken()); + // tokens.add( tokenizer.nextToken("e") ); + } + int tokenLength = tokens.size(); + return tokens; + } + + public List getTokensWithCollection(String str) { + 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; + StringTokenizer tokenizer; + try (BufferedReader br = new BufferedReader(new InputStreamReader(MyTokenizer.class.getResourceAsStream("/" + path)))) { + while ((currLine = br.readLine()) != null) { + tokenizer = new StringTokenizer(currLine, delim); + while (tokenizer.hasMoreElements()) { + tokens.add(tokenizer.nextToken()); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + return tokens; + } + +} diff --git a/core-java/src/main/java/com/baeldung/threadlocal/Context.java b/core-java/src/main/java/com/baeldung/threadlocal/Context.java new file mode 100644 index 0000000000..241fb2f1e0 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/threadlocal/Context.java @@ -0,0 +1,17 @@ +package com.baeldung.threadlocal; + + +public class Context { + private final String userName; + + public Context(String userName) { + this.userName = userName; + } + + @Override + public String toString() { + return "Context{" + + "userNameSecret='" + userName + '\'' + + '}'; + } +} diff --git a/core-java/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java b/core-java/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java new file mode 100644 index 0000000000..e5854e218a --- /dev/null +++ b/core-java/src/main/java/com/baeldung/threadlocal/SharedMapWithUserContext.java @@ -0,0 +1,21 @@ +package com.baeldung.threadlocal; + + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class SharedMapWithUserContext implements Runnable { + public final static Map userContextPerUserId = new ConcurrentHashMap<>(); + private final Integer userId; + private UserRepository userRepository = new UserRepository(); + + public SharedMapWithUserContext(Integer userId) { + this.userId = userId; + } + + @Override + public void run() { + String userName = userRepository.getUserNameForUserId(userId); + userContextPerUserId.put(userId, new Context(userName)); + } +} diff --git a/core-java/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java b/core-java/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java new file mode 100644 index 0000000000..0d6a7e5572 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/threadlocal/ThreadLocalWithUserContext.java @@ -0,0 +1,20 @@ +package com.baeldung.threadlocal; + + +public class ThreadLocalWithUserContext implements Runnable { + private static final ThreadLocal userContext = new ThreadLocal<>(); + private final Integer userId; + private UserRepository userRepository = new UserRepository(); + + public ThreadLocalWithUserContext(Integer userId) { + this.userId = userId; + } + + + @Override + public void run() { + String userName = userRepository.getUserNameForUserId(userId); + userContext.set(new Context(userName)); + System.out.println("thread context for given userId: " + userId + " is: " + userContext.get()); + } +} diff --git a/core-java/src/main/java/com/baeldung/threadlocal/UserRepository.java b/core-java/src/main/java/com/baeldung/threadlocal/UserRepository.java new file mode 100644 index 0000000000..3fe76f75c0 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/threadlocal/UserRepository.java @@ -0,0 +1,10 @@ +package com.baeldung.threadlocal; + +import java.util.UUID; + + +public class UserRepository { + public String getUserNameForUserId(Integer userId) { + return UUID.randomUUID().toString(); + } +} diff --git a/core-java/src/main/resources/ESAPI.properties b/core-java/src/main/resources/ESAPI.properties new file mode 100644 index 0000000000..24dcaa9dfa --- /dev/null +++ b/core-java/src/main/resources/ESAPI.properties @@ -0,0 +1,453 @@ +# +# OWASP Enterprise Security API (ESAPI) Properties file -- PRODUCTION Version +# +# This file is part of the Open Web Application Security Project (OWASP) +# Enterprise Security API (ESAPI) project. For details, please see +# http://www.owasp.org/index.php/ESAPI. +# +# Copyright (c) 2008,2009 - The OWASP Foundation +# +# DISCUSS: This may cause a major backwards compatibility issue, etc. but +# from a name space perspective, we probably should have prefaced +# all the property names with ESAPI or at least OWASP. Otherwise +# there could be problems is someone loads this properties file into +# the System properties. We could also put this file into the +# esapi.jar file (perhaps as a ResourceBundle) and then allow an external +# ESAPI properties be defined that would overwrite these defaults. +# That keeps the application's properties relatively simple as usually +# they will only want to override a few properties. If looks like we +# already support multiple override levels of this in the +# DefaultSecurityConfiguration class, but I'm suggesting placing the +# defaults in the esapi.jar itself. That way, if the jar is signed, +# we could detect if those properties had been tampered with. (The +# code to check the jar signatures is pretty simple... maybe 70-90 LOC, +# but off course there is an execution penalty (similar to the way +# that the separate sunjce.jar used to be when a class from it was +# first loaded). Thoughts? +############################################################################### +# +# WARNING: Operating system protection should be used to lock down the .esapi +# resources directory and all the files inside and all the directories all the +# way up to the root directory of the file system. Note that if you are using +# file-based implementations, that some files may need to be read-write as they +# get updated dynamically. +# +# Before using, be sure to update the MasterKey and MasterSalt as described below. +# N.B.: If you had stored data that you have previously encrypted with ESAPI 1.4, +# you *must* FIRST decrypt it using ESAPI 1.4 and then (if so desired) +# re-encrypt it with ESAPI 2.0. If you fail to do this, you will NOT be +# able to decrypt your data with ESAPI 2.0. +# +# YOU HAVE BEEN WARNED!!! More details are in the ESAPI 2.0 Release Notes. +# +#=========================================================================== +# ESAPI Configuration +# +# If true, then print all the ESAPI properties set here when they are loaded. +# If false, they are not printed. Useful to reduce output when running JUnit tests. +# If you need to troubleshoot a properties related problem, turning this on may help. +# This is 'false' in the src/test/resources/.esapi version. It is 'true' by +# default for reasons of backward compatibility with earlier ESAPI versions. +ESAPI.printProperties=true + +# ESAPI is designed to be easily extensible. You can use the reference implementation +# or implement your own providers to take advantage of your enterprise's security +# infrastructure. The functions in ESAPI are referenced using the ESAPI locator, like: +# +# String ciphertext = +# ESAPI.encryptor().encrypt("Secret message"); // Deprecated in 2.0 +# CipherText cipherText = +# ESAPI.encryptor().encrypt(new PlainText("Secret message")); // Preferred +# +# Below you can specify the classname for the provider that you wish to use in your +# application. The only requirement is that it implement the appropriate ESAPI interface. +# This allows you to switch security implementations in the future without rewriting the +# entire application. +# +# ExperimentalAccessController requires ESAPI-AccessControlPolicy.xml in .esapi directory +ESAPI.AccessControl=org.owasp.esapi.reference.DefaultAccessController +# FileBasedAuthenticator requires users.txt file in .esapi directory +ESAPI.Authenticator=org.owasp.esapi.reference.FileBasedAuthenticator +ESAPI.Encoder=org.owasp.esapi.reference.DefaultEncoder +ESAPI.Encryptor=org.owasp.esapi.reference.crypto.JavaEncryptor + +ESAPI.Executor=org.owasp.esapi.reference.DefaultExecutor +ESAPI.HTTPUtilities=org.owasp.esapi.reference.DefaultHTTPUtilities +ESAPI.IntrusionDetector=org.owasp.esapi.reference.DefaultIntrusionDetector +# Log4JFactory Requires log4j.xml or log4j.properties in classpath - http://www.laliluna.de/log4j-tutorial.html +ESAPI.Logger=org.owasp.esapi.reference.Log4JLogFactory +#ESAPI.Logger=org.owasp.esapi.reference.JavaLogFactory +ESAPI.Randomizer=org.owasp.esapi.reference.DefaultRandomizer +ESAPI.Validator=org.owasp.esapi.reference.DefaultValidator + +#=========================================================================== +# ESAPI Authenticator +# +Authenticator.AllowedLoginAttempts=3 +Authenticator.MaxOldPasswordHashes=13 +Authenticator.UsernameParameterName=username +Authenticator.PasswordParameterName=password +# RememberTokenDuration (in days) +Authenticator.RememberTokenDuration=14 +# Session Timeouts (in minutes) +Authenticator.IdleTimeoutDuration=20 +Authenticator.AbsoluteTimeoutDuration=120 + +#=========================================================================== +# ESAPI Encoder +# +# ESAPI canonicalizes input before validation to prevent bypassing filters with encoded attacks. +# Failure to canonicalize input is a very common mistake when implementing validation schemes. +# Canonicalization is automatic when using the ESAPI Validator, but you can also use the +# following code to canonicalize data. +# +# ESAPI.Encoder().canonicalize( "%22hello world"" ); +# +# Multiple encoding is when a single encoding format is applied multiple times. Allowing +# multiple encoding is strongly discouraged. +Encoder.AllowMultipleEncoding=false + +# Mixed encoding is when multiple different encoding formats are applied, or when +# multiple formats are nested. Allowing multiple encoding is strongly discouraged. +Encoder.AllowMixedEncoding=false + +# The default list of codecs to apply when canonicalizing untrusted data. The list should include the codecs +# for all downstream interpreters or decoders. For example, if the data is likely to end up in a URL, HTML, or +# inside JavaScript, then the list of codecs below is appropriate. The order of the list is not terribly important. +Encoder.DefaultCodecList=HTMLEntityCodec,PercentCodec,JavaScriptCodec + + +#=========================================================================== +# ESAPI Encryption +# +# The ESAPI Encryptor provides basic cryptographic functions with a simplified API. +# To get started, generate a new key using java -classpath esapi.jar org.owasp.esapi.reference.crypto.JavaEncryptor +# There is not currently any support for key rotation, so be careful when changing your key and salt as it +# will invalidate all signed, encrypted, and hashed data. +# +# WARNING: Not all combinations of algorithms and key lengths are supported. +# If you choose to use a key length greater than 128, you MUST download the +# unlimited strength policy files and install in the lib directory of your JRE/JDK. +# See http://java.sun.com/javase/downloads/index.jsp for more information. +# +# Backward compatibility with ESAPI Java 1.4 is supported by the two deprecated API +# methods, Encryptor.encrypt(String) and Encryptor.decrypt(String). However, whenever +# possible, these methods should be avoided as they use ECB cipher mode, which in almost +# all circumstances a poor choice because of it's weakness. CBC cipher mode is the default +# for the new Encryptor encrypt / decrypt methods for ESAPI Java 2.0. In general, you +# should only use this compatibility setting if you have persistent data encrypted with +# version 1.4 and even then, you should ONLY set this compatibility mode UNTIL +# you have decrypted all of your old encrypted data and then re-encrypted it with +# ESAPI 2.0 using CBC mode. If you have some reason to mix the deprecated 1.4 mode +# with the new 2.0 methods, make sure that you use the same cipher algorithm for both +# (256-bit AES was the default for 1.4; 128-bit is the default for 2.0; see below for +# more details.) Otherwise, you will have to use the new 2.0 encrypt / decrypt methods +# where you can specify a SecretKey. (Note that if you are using the 256-bit AES, +# that requires downloading the special jurisdiction policy files mentioned above.) +# +# ***** IMPORTANT: Do NOT forget to replace these with your own values! ***** +# To calculate these values, you can run: +# java -classpath esapi.jar org.owasp.esapi.reference.crypto.JavaEncryptor +# +Encryptor.MasterKey=tzfztf56ftv +Encryptor.MasterSalt=123456ztrewq + +# Provides the default JCE provider that ESAPI will "prefer" for its symmetric +# encryption and hashing. (That is it will look to this provider first, but it +# will defer to other providers if the requested algorithm is not implemented +# by this provider.) If left unset, ESAPI will just use your Java VM's current +# preferred JCE provider, which is generally set in the file +# "$JAVA_HOME/jre/lib/security/java.security". +# +# The main intent of this is to allow ESAPI symmetric encryption to be +# used with a FIPS 140-2 compliant crypto-module. For details, see the section +# "Using ESAPI Symmetric Encryption with FIPS 140-2 Cryptographic Modules" in +# the ESAPI 2.0 Symmetric Encryption User Guide, at: +# http://owasp-esapi-java.googlecode.com/svn/trunk/documentation/esapi4java-core-2.0-symmetric-crypto-user-guide.html +# However, this property also allows you to easily use an alternate JCE provider +# such as "Bouncy Castle" without having to make changes to "java.security". +# See Javadoc for SecurityProviderLoader for further details. If you wish to use +# a provider that is not known to SecurityProviderLoader, you may specify the +# fully-qualified class name of the JCE provider class that implements +# java.security.Provider. If the name contains a '.', this is interpreted as +# a fully-qualified class name that implements java.security.Provider. +# +# NOTE: Setting this property has the side-effect of changing it in your application +# as well, so if you are using JCE in your application directly rather than +# through ESAPI (you wouldn't do that, would you? ;-), it will change the +# preferred JCE provider there as well. +# +# Default: Keeps the JCE provider set to whatever JVM sets it to. +Encryptor.PreferredJCEProvider= + +# AES is the most widely used and strongest encryption algorithm. This +# should agree with your Encryptor.CipherTransformation property. +# By default, ESAPI Java 1.4 uses "PBEWithMD5AndDES" and which is +# very weak. It is essentially a password-based encryption key, hashed +# with MD5 around 1K times and then encrypted with the weak DES algorithm +# (56-bits) using ECB mode and an unspecified padding (it is +# JCE provider specific, but most likely "NoPadding"). However, 2.0 uses +# "AES/CBC/PKCSPadding". If you want to change these, change them here. +# Warning: This property does not control the default reference implementation for +# ESAPI 2.0 using JavaEncryptor. Also, this property will be dropped +# in the future. +# @deprecated +Encryptor.EncryptionAlgorithm=AES +# For ESAPI Java 2.0 - New encrypt / decrypt methods use this. +Encryptor.CipherTransformation=AES/CBC/PKCS5Padding + +# Applies to ESAPI 2.0 and later only! +# Comma-separated list of cipher modes that provide *BOTH* +# confidentiality *AND* message authenticity. (NIST refers to such cipher +# modes as "combined modes" so that's what we shall call them.) If any of these +# cipher modes are used then no MAC is calculated and stored +# in the CipherText upon encryption. Likewise, if one of these +# cipher modes is used with decryption, no attempt will be made +# to validate the MAC contained in the CipherText object regardless +# of whether it contains one or not. Since the expectation is that +# these cipher modes support support message authenticity already, +# injecting a MAC in the CipherText object would be at best redundant. +# +# Note that as of JDK 1.5, the SunJCE provider does not support *any* +# of these cipher modes. Of these listed, only GCM and CCM are currently +# NIST approved. YMMV for other JCE providers. E.g., Bouncy Castle supports +# GCM and CCM with "NoPadding" mode, but not with "PKCS5Padding" or other +# padding modes. +Encryptor.cipher_modes.combined_modes=GCM,CCM,IAPM,EAX,OCB,CWC + +# Applies to ESAPI 2.0 and later only! +# Additional cipher modes allowed for ESAPI 2.0 encryption. These +# cipher modes are in _addition_ to those specified by the property +# 'Encryptor.cipher_modes.combined_modes'. +# Note: We will add support for streaming modes like CFB & OFB once +# we add support for 'specified' to the property 'Encryptor.ChooseIVMethod' +# (probably in ESAPI 2.1). +# DISCUSS: Better name? +Encryptor.cipher_modes.additional_allowed=CBC + +# 128-bit is almost always sufficient and appears to be more resistant to +# related key attacks than is 256-bit AES. Use '_' to use default key size +# for cipher algorithms (where it makes sense because the algorithm supports +# a variable key size). Key length must agree to what's provided as the +# cipher transformation, otherwise this will be ignored after logging a +# warning. +# +# NOTE: This is what applies BOTH ESAPI 1.4 and 2.0. See warning above about mixing! +Encryptor.EncryptionKeyLength=128 + +# Because 2.0 uses CBC mode by default, it requires an initialization vector (IV). +# (All cipher modes except ECB require an IV.) There are two choices: we can either +# use a fixed IV known to both parties or allow ESAPI to choose a random IV. While +# the IV does not need to be hidden from adversaries, it is important that the +# adversary not be allowed to choose it. Also, random IVs are generally much more +# secure than fixed IVs. (In fact, it is essential that feed-back cipher modes +# such as CFB and OFB use a different IV for each encryption with a given key so +# in such cases, random IVs are much preferred. By default, ESAPI 2.0 uses random +# IVs. If you wish to use 'fixed' IVs, set 'Encryptor.ChooseIVMethod=fixed' and +# uncomment the Encryptor.fixedIV. +# +# Valid values: random|fixed|specified 'specified' not yet implemented; planned for 2.1 +Encryptor.ChooseIVMethod=random +# If you choose to use a fixed IV, then you must place a fixed IV here that +# is known to all others who are sharing your secret key. The format should +# be a hex string that is the same length as the cipher block size for the +# cipher algorithm that you are using. The following is an *example* for AES +# from an AES test vector for AES-128/CBC as described in: +# NIST Special Publication 800-38A (2001 Edition) +# "Recommendation for Block Cipher Modes of Operation". +# (Note that the block size for AES is 16 bytes == 128 bits.) +# +Encryptor.fixedIV=0x000102030405060708090a0b0c0d0e0f + +# Whether or not CipherText should use a message authentication code (MAC) with it. +# This prevents an adversary from altering the IV as well as allowing a more +# fool-proof way of determining the decryption failed because of an incorrect +# key being supplied. This refers to the "separate" MAC calculated and stored +# in CipherText, not part of any MAC that is calculated as a result of a +# "combined mode" cipher mode. +# +# If you are using ESAPI with a FIPS 140-2 cryptographic module, you *must* also +# set this property to false. +Encryptor.CipherText.useMAC=true + +# Whether or not the PlainText object may be overwritten and then marked +# eligible for garbage collection. If not set, this is still treated as 'true'. +Encryptor.PlainText.overwrite=true + +# Do not use DES except in a legacy situations. 56-bit is way too small key size. +#Encryptor.EncryptionKeyLength=56 +#Encryptor.EncryptionAlgorithm=DES + +# TripleDES is considered strong enough for most purposes. +# Note: There is also a 112-bit version of DESede. Using the 168-bit version +# requires downloading the special jurisdiction policy from Sun. +#Encryptor.EncryptionKeyLength=168 +#Encryptor.EncryptionAlgorithm=DESede + +Encryptor.HashAlgorithm=SHA-512 +Encryptor.HashIterations=1024 +Encryptor.DigitalSignatureAlgorithm=SHA1withDSA +Encryptor.DigitalSignatureKeyLength=1024 +Encryptor.RandomAlgorithm=SHA1PRNG +Encryptor.CharacterEncoding=UTF-8 + +# This is the Pseudo Random Function (PRF) that ESAPI's Key Derivation Function +# (KDF) normally uses. Note this is *only* the PRF used for ESAPI's KDF and +# *not* what is used for ESAPI's MAC. (Currently, HmacSHA1 is always used for +# the MAC, mostly to keep the overall size at a minimum.) +# +# Currently supported choices for JDK 1.5 and 1.6 are: +# HmacSHA1 (160 bits), HmacSHA256 (256 bits), HmacSHA384 (384 bits), and +# HmacSHA512 (512 bits). +# Note that HmacMD5 is *not* supported for the PRF used by the KDF even though +# the JDKs support it. See the ESAPI 2.0 Symmetric Encryption User Guide +# further details. +Encryptor.KDF.PRF=HmacSHA256 +#=========================================================================== +# ESAPI HttpUtilties +# +# The HttpUtilities provide basic protections to HTTP requests and responses. Primarily these methods +# protect against malicious data from attackers, such as unprintable characters, escaped characters, +# and other simple attacks. The HttpUtilities also provides utility methods for dealing with cookies, +# headers, and CSRF tokens. +# +# Default file upload location (remember to escape backslashes with \\) +HttpUtilities.UploadDir=C:\\ESAPI\\testUpload +HttpUtilities.UploadTempDir=C:\\temp +# Force flags on cookies, if you use HttpUtilities to set cookies +HttpUtilities.ForceHttpOnlySession=false +HttpUtilities.ForceSecureSession=false +HttpUtilities.ForceHttpOnlyCookies=true +HttpUtilities.ForceSecureCookies=true +# Maximum size of HTTP headers +HttpUtilities.MaxHeaderSize=4096 +# File upload configuration +HttpUtilities.ApprovedUploadExtensions=.zip,.pdf,.doc,.docx,.ppt,.pptx,.tar,.gz,.tgz,.rar,.war,.jar,.ear,.xls,.rtf,.properties,.java,.class,.txt,.xml,.jsp,.jsf,.exe,.dll +HttpUtilities.MaxUploadFileBytes=500000000 +# Using UTF-8 throughout your stack is highly recommended. That includes your database driver, +# container, and any other technologies you may be using. Failure to do this may expose you +# to Unicode transcoding injection attacks. Use of UTF-8 does not hinder internationalization. +HttpUtilities.ResponseContentType=text/html; charset=UTF-8 +# This is the name of the cookie used to represent the HTTP session +# Typically this will be the default "JSESSIONID" +HttpUtilities.HttpSessionIdName=JSESSIONID + + + +#=========================================================================== +# ESAPI Executor +# CHECKME - Not sure what this is used for, but surely it should be made OS independent. +Executor.WorkingDirectory=C:\\Windows\\Temp +Executor.ApprovedExecutables=C:\\Windows\\System32\\cmd.exe,C:\\Windows\\System32\\runas.exe + + +#=========================================================================== +# ESAPI Logging +# Set the application name if these logs are combined with other applications +Logger.ApplicationName=ExampleApplication +# If you use an HTML log viewer that does not properly HTML escape log data, you can set LogEncodingRequired to true +Logger.LogEncodingRequired=false +# Determines whether ESAPI should log the application name. This might be clutter in some single-server/single-app environments. +Logger.LogApplicationName=true +# Determines whether ESAPI should log the server IP and port. This might be clutter in some single-server environments. +Logger.LogServerIP=true +# LogFileName, the name of the logging file. Provide a full directory path (e.g., C:\\ESAPI\\ESAPI_logging_file) if you +# want to place it in a specific directory. +Logger.LogFileName=ESAPI_logging_file +# MaxLogFileSize, the max size (in bytes) of a single log file before it cuts over to a new one (default is 10,000,000) +Logger.MaxLogFileSize=10000000 + + +#=========================================================================== +# ESAPI Intrusion Detection +# +# Each event has a base to which .count, .interval, and .action are added +# The IntrusionException will fire if we receive "count" events within "interval" seconds +# The IntrusionDetector is configurable to take the following actions: log, logout, and disable +# (multiple actions separated by commas are allowed e.g. event.test.actions=log,disable +# +# Custom Events +# Names must start with "event." as the base +# Use IntrusionDetector.addEvent( "test" ) in your code to trigger "event.test" here +# You can also disable intrusion detection completely by changing +# the following parameter to true +# +IntrusionDetector.Disable=false +# +IntrusionDetector.event.test.count=2 +IntrusionDetector.event.test.interval=10 +IntrusionDetector.event.test.actions=disable,log + +# Exception Events +# All EnterpriseSecurityExceptions are registered automatically +# Call IntrusionDetector.getInstance().addException(e) for Exceptions that do not extend EnterpriseSecurityException +# Use the fully qualified classname of the exception as the base + +# any intrusion is an attack +IntrusionDetector.org.owasp.esapi.errors.IntrusionException.count=1 +IntrusionDetector.org.owasp.esapi.errors.IntrusionException.interval=1 +IntrusionDetector.org.owasp.esapi.errors.IntrusionException.actions=log,disable,logout + +# for test purposes +# CHECKME: Shouldn't there be something in the property name itself that designates +# that these are for testing??? +IntrusionDetector.org.owasp.esapi.errors.IntegrityException.count=10 +IntrusionDetector.org.owasp.esapi.errors.IntegrityException.interval=5 +IntrusionDetector.org.owasp.esapi.errors.IntegrityException.actions=log,disable,logout + +# rapid validation errors indicate scans or attacks in progress +# org.owasp.esapi.errors.ValidationException.count=10 +# org.owasp.esapi.errors.ValidationException.interval=10 +# org.owasp.esapi.errors.ValidationException.actions=log,logout + +# sessions jumping between hosts indicates session hijacking +IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.count=2 +IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.interval=10 +IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.actions=log,logout + + +#=========================================================================== +# ESAPI Validation +# +# The ESAPI Validator works on regular expressions with defined names. You can define names +# either here, or you may define application specific patterns in a separate file defined below. +# This allows enterprises to specify both organizational standards as well as application specific +# validation rules. +# +Validator.ConfigurationFile=validation.properties + +# Validators used by ESAPI +Validator.AccountName=^[a-zA-Z0-9]{3,20}$ +Validator.SystemCommand=^[a-zA-Z\\-\\/]{1,64}$ +Validator.RoleName=^[a-z]{1,20}$ + +#the word TEST below should be changed to your application +#name - only relative URL's are supported +Validator.Redirect=^\\/test.*$ + +# Global HTTP Validation Rules +# Values with Base64 encoded data (e.g. encrypted state) will need at least [a-zA-Z0-9\/+=] +Validator.HTTPScheme=^(http|https)$ +Validator.HTTPServerName=^[a-zA-Z0-9_.\\-]*$ +Validator.HTTPParameterName=^[a-zA-Z0-9_]{1,32}$ +Validator.HTTPParameterValue=^[a-zA-Z0-9.\\-\\/+=@_ ]*$ +Validator.HTTPCookieName=^[a-zA-Z0-9\\-_]{1,32}$ +Validator.HTTPCookieValue=^[a-zA-Z0-9\\-\\/+=_ ]*$ +Validator.HTTPHeaderName=^[a-zA-Z0-9\\-_]{1,32}$ +Validator.HTTPHeaderValue=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ ]*$ +Validator.HTTPContextPath=^\\/?[a-zA-Z0-9.\\-\\/_]*$ +Validator.HTTPServletPath=^[a-zA-Z0-9.\\-\\/_]*$ +Validator.HTTPPath=^[a-zA-Z0-9.\\-_]*$ +Validator.HTTPQueryString=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ %]*$ +Validator.HTTPURI=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ ]*$ +Validator.HTTPURL=^.*$ +Validator.HTTPJSESSIONID=^[A-Z0-9]{10,30}$ + +# Validation of file related input +Validator.FileName=^[a-zA-Z0-9!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$ +Validator.DirectoryName=^[a-zA-Z0-9:/\\\\!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$ + +# Validation of dates. Controls whether or not 'lenient' dates are accepted. +# See DataFormat.setLenient(boolean flag) for further details. +Validator.AcceptLenientDates=false + diff --git a/core-java/src/main/resources/data.csv b/core-java/src/main/resources/data.csv new file mode 100644 index 0000000000..ec4ac10443 --- /dev/null +++ b/core-java/src/main/resources/data.csv @@ -0,0 +1,3 @@ +1|IND|India +2|MY|Malaysia +3|AU|Australia diff --git a/core-java/src/test/java/com/baeldung/java/collections/ConcurrentModificationExceptionTest.java b/core-java/src/test/java/com/baeldung/java/collections/ConcurrentModificationExceptionTest.java new file mode 100644 index 0000000000..100d25ab8d --- /dev/null +++ b/core-java/src/test/java/com/baeldung/java/collections/ConcurrentModificationExceptionTest.java @@ -0,0 +1,82 @@ +package com.baeldung.java.collections; + +import org.junit.Test; + +import java.util.*; +import java.util.concurrent.CopyOnWriteArrayList; + +import static java.util.Arrays.asList; +import static org.testng.Assert.assertEquals; + +public class ConcurrentModificationExceptionTest { + @Test + public void changingContentWithSetDoesNotThrowConcurrentModificationException() throws Exception { + ArrayList array = new ArrayList<>(asList(0, "one", 2, "three")); + + for (Object item : array) { + array.set(3, 3); + } + } + + @Test + public void removingElementUsingIteratorAPI() throws Exception { + List originalList = new ArrayList<>(asList("zero", "one", "two", "three")); + + Iterator iterator = originalList.iterator(); + + while (iterator.hasNext()) { + String next = iterator.next(); + if (Objects.equals(next, "one")) iterator.remove(); + } + + assertEquals(originalList, asList("zero", "two", "three")); + } + + @Test + public void modifyingContentAndIteratingUsingListIteratorAPI() throws Exception { + List originalList = new ArrayList<>(asList("zero", "one", "two", "three")); + + ListIterator iterator = originalList.listIterator(); + + while (iterator.hasNext()) { + String next = iterator.next(); + if (Objects.equals(next, "one")) { + iterator.set("another"); + } + + if (Objects.equals(next, "two")) { + iterator.remove(); + } + + if (Objects.equals(next, "three")) { + iterator.add("four"); + } + } + + assertEquals(originalList, asList("zero", "another", "three", "four")); + } + + @Test + public void removingElementUsingCopyAndListAPI() throws Exception { + List originalList = new ArrayList<>(asList("zero", "one", "two", "three")); + + List listCopy = new ArrayList<>(originalList); + + for (String next : listCopy) { + if (Objects.equals(next, "one")) originalList.remove(originalList.indexOf(next) - 1); + } + + assertEquals(originalList, asList("one", "two", "three")); + } + + @Test + public void copyOnWriteList() throws Exception { + List originalList = new CopyOnWriteArrayList<>(asList("zero", "one", "two", "three")); + + for (String next : originalList) { + if (Objects.equals(next, "one")) originalList.remove(originalList.indexOf(next) - 1); + } + + assertEquals(originalList, asList("one", "two", "three")); + } +} diff --git a/core-java/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListTest.java b/core-java/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListTest.java index 285b217156..93962e7831 100644 --- a/core-java/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListTest.java +++ b/core-java/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListTest.java @@ -17,7 +17,7 @@ public class FlattenNestedListTest { List> lol = asList(asList("one:one"), asList("two:one", "two:two", "two:three"), asList("three:one", "three:two", "three:three", "three:four")); @Test - public void givenNestedList_thenFlattenNestedListImperative() { + public void givenNestedList_thenFlattenImperatively() { List ls = flattenListOfListsImperatively(lol); assertNotNull(ls); @@ -27,7 +27,7 @@ public class FlattenNestedListTest { } @Test - public void givenNestedList_thenFlattenNestedListStream() { + public void givenNestedList_thenFlattenFunctionally() { List ls = flattenListOfListsStream(lol); assertNotNull(ls); diff --git a/core-java/src/test/java/com/baeldung/stringtokenizer/ApplicationTest.java b/core-java/src/test/java/com/baeldung/stringtokenizer/ApplicationTest.java deleted file mode 100644 index 5e3df5b303..0000000000 --- a/core-java/src/test/java/com/baeldung/stringtokenizer/ApplicationTest.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.stringtokenizer; - -import java.util.ArrayList; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class ApplicationTest { - - Application application = new Application(); - List expectedTokens = new ArrayList(); - - @Before - public void init() { - expectedTokens.add( "Welcome" ); - expectedTokens.add( "to" ); - expectedTokens.add( "baeldung.com" ); - } - - @Test - public void givenString_thenGetListOfString() { - String str = "Welcome,to,baeldung.com"; - List actualTokens = application.getTokens(str); - assertEquals(expectedTokens, actualTokens); - } - -} diff --git a/core-java/src/test/java/com/baeldung/stringtokenizer/TokenizerTest.java b/core-java/src/test/java/com/baeldung/stringtokenizer/TokenizerTest.java new file mode 100644 index 0000000000..eed42a2f96 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/stringtokenizer/TokenizerTest.java @@ -0,0 +1,29 @@ +package com.baeldung.stringtokenizer; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class TokenizerTest { + + private final MyTokenizer myTokenizer = new MyTokenizer(); + private final List expectedTokensForString = Arrays.asList("Welcome", "to", "baeldung.com"); + private final List expectedTokensForFile = Arrays.asList("1", "IND", "India", "2", "MY", "Malaysia", "3", "AU", "Australia"); + + @Test + public void givenString_thenGetListOfString() { + String str = "Welcome,to,baeldung.com"; + List actualTokens = myTokenizer.getTokens(str); + assertEquals(expectedTokensForString, actualTokens); + } + + @Test + public void givenFile_thenGetListOfString() { + List actualTokens = myTokenizer.getTokensFromFile("data.csv", "|"); + assertEquals(expectedTokensForFile, actualTokens); + } + +} diff --git a/core-java/src/test/java/com/baeldung/threadlocal/ThreadLocalTest.java b/core-java/src/test/java/com/baeldung/threadlocal/ThreadLocalTest.java new file mode 100644 index 0000000000..ac2e8fbe63 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/threadlocal/ThreadLocalTest.java @@ -0,0 +1,35 @@ +package com.baeldung.threadlocal; + + +import org.junit.Test; + +import java.util.concurrent.ExecutionException; + +import static org.junit.Assert.assertEquals; + +public class ThreadLocalTest { + @Test + public void givenThreadThatStoresContextInAMap_whenStartThread_thenShouldSetContextForBothUsers() throws ExecutionException, InterruptedException { + //when + SharedMapWithUserContext firstUser = new SharedMapWithUserContext(1); + SharedMapWithUserContext secondUser = new SharedMapWithUserContext(2); + new Thread(firstUser).start(); + new Thread(secondUser).start(); + + Thread.sleep(3000); + //then + assertEquals(SharedMapWithUserContext.userContextPerUserId.size(), 2); + } + + @Test + public void givenThreadThatStoresContextInThreadLocal_whenStartThread_thenShouldStoreContextInThreadLocal() throws ExecutionException, InterruptedException { + //when + ThreadLocalWithUserContext firstUser = new ThreadLocalWithUserContext(1); + ThreadLocalWithUserContext secondUser = new ThreadLocalWithUserContext(2); + new Thread(firstUser).start(); + new Thread(secondUser).start(); + + Thread.sleep(3000); + } + +} diff --git a/core-java/src/test/java/com/baeldung/unsafe/CASCounter.java b/core-java/src/test/java/com/baeldung/unsafe/CASCounter.java new file mode 100644 index 0000000000..f7f3b340c2 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/unsafe/CASCounter.java @@ -0,0 +1,33 @@ +package com.baeldung.unsafe; + +import sun.misc.Unsafe; + +import java.lang.reflect.Field; + +class CASCounter { + private final Unsafe unsafe; + private volatile long counter = 0; + private long offset; + + private Unsafe getUnsafe() throws IllegalAccessException, NoSuchFieldException { + Field f = Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + return (Unsafe) f.get(null); + } + + public CASCounter() throws Exception { + unsafe = getUnsafe(); + offset = unsafe.objectFieldOffset(CASCounter.class.getDeclaredField("counter")); + } + + public void increment() { + long before = counter; + while (!unsafe.compareAndSwapLong(this, offset, before, before + 1)) { + before = counter; + } + } + + public long getCounter() { + return counter; + } +} \ No newline at end of file diff --git a/core-java/src/test/java/com/baeldung/unsafe/OffHeapArray.java b/core-java/src/test/java/com/baeldung/unsafe/OffHeapArray.java new file mode 100644 index 0000000000..f5cab88f3d --- /dev/null +++ b/core-java/src/test/java/com/baeldung/unsafe/OffHeapArray.java @@ -0,0 +1,39 @@ +package com.baeldung.unsafe; + +import sun.misc.Unsafe; + +import java.lang.reflect.Field; + +class OffHeapArray { + private final static int BYTE = 1; + private long size; + private long address; + + private Unsafe getUnsafe() throws IllegalAccessException, NoSuchFieldException { + Field f = Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + return (Unsafe) f.get(null); + } + + public OffHeapArray(long size) throws NoSuchFieldException, IllegalAccessException { + this.size = size; + address = getUnsafe().allocateMemory(size * BYTE); + } + + public void set(long i, byte value) throws NoSuchFieldException, IllegalAccessException { + getUnsafe().putByte(address + i * BYTE, value); + } + + public int get(long idx) throws NoSuchFieldException, IllegalAccessException { + return getUnsafe().getByte(address + idx * BYTE); + } + + public long size() { + return size; + } + + public void freeMemory() throws NoSuchFieldException, IllegalAccessException { + getUnsafe().freeMemory(address); + } + +} diff --git a/core-java/src/test/java/com/baeldung/unsafe/UnsafeTest.java b/core-java/src/test/java/com/baeldung/unsafe/UnsafeTest.java new file mode 100644 index 0000000000..9f53e38969 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/unsafe/UnsafeTest.java @@ -0,0 +1,123 @@ +package com.baeldung.unsafe; + +import org.junit.Before; +import org.junit.Test; +import sun.misc.Unsafe; + +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.stream.IntStream; + +import static junit.framework.Assert.assertTrue; +import static junit.framework.TestCase.assertEquals; + +public class UnsafeTest { + + private Unsafe unsafe; + + @Before + public void setup() throws NoSuchFieldException, IllegalAccessException { + Field f = Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + unsafe = (Unsafe) f.get(null); + } + + + @Test + public void givenClass_whenInitializeIt_thenShouldHaveDifferentStateWhenUseUnsafe() throws IllegalAccessException, InstantiationException { + //when + InitializationOrdering o1 = new InitializationOrdering(); + assertEquals(o1.getA(), 1); + + //when + InitializationOrdering o3 = (InitializationOrdering) unsafe.allocateInstance(InitializationOrdering.class); + assertEquals(o3.getA(), 0); + } + + @Test + public void givenPrivateMethod_whenUsingUnsafe_thenCanModifyPrivateField() throws NoSuchFieldException { + //given + SecretHolder secretHolder = new SecretHolder(); + + //when + Field f = secretHolder.getClass().getDeclaredField("SECRET_VALUE"); + unsafe.putInt(secretHolder, unsafe.objectFieldOffset(f), 1); + + //then + assertTrue(secretHolder.secretIsDisclosed()); + } + + @Test(expected = IOException.class) + public void givenUnsafeThrowException_whenThrowCheckedException_thenNotNeedToCatchIt() { + unsafe.throwException(new IOException()); + } + + @Test + public void givenArrayBiggerThatMaxInt_whenAllocateItOffHeapMemory_thenSuccess() throws NoSuchFieldException, IllegalAccessException { + //given + long SUPER_SIZE = (long) Integer.MAX_VALUE * 2; + OffHeapArray array = new OffHeapArray(SUPER_SIZE); + + //when + int sum = 0; + for (int i = 0; i < 100; i++) { + array.set((long) Integer.MAX_VALUE + i, (byte) 3); + sum += array.get((long) Integer.MAX_VALUE + i); + } + + long arraySize = array.size(); + + array.freeMemory(); + + //then + assertEquals(arraySize, SUPER_SIZE); + assertEquals(sum, 300); + + } + + @Test + public void givenUnsafeCompareAndSwap_whenUseIt_thenCounterYildCorrectLockFreeResults() throws Exception { + //given + int NUM_OF_THREADS = 1_000; + int NUM_OF_INCREMENTS = 10_000; + ExecutorService service = Executors.newFixedThreadPool(NUM_OF_THREADS); + CASCounter casCounter = new CASCounter(); + + //when + IntStream.rangeClosed(0, NUM_OF_THREADS - 1) + .forEach(i -> service.submit(() -> IntStream + .rangeClosed(0, NUM_OF_INCREMENTS - 1) + .forEach(j -> casCounter.increment()))); + + service.shutdown(); + service.awaitTermination(1, TimeUnit.MINUTES); + + //then + assertEquals(NUM_OF_INCREMENTS * NUM_OF_THREADS, casCounter.getCounter()); + + } + + class InitializationOrdering { + private long a; + + public InitializationOrdering() { + this.a = 1; + } + + public long getA() { + return this.a; + } + } + + class SecretHolder { + private int SECRET_VALUE = 0; + + public boolean secretIsDisclosed() { + return SECRET_VALUE == 1; + } + } + +} diff --git a/cucumber/pom.xml b/cucumber/pom.xml new file mode 100644 index 0000000000..77d04f96c2 --- /dev/null +++ b/cucumber/pom.xml @@ -0,0 +1,93 @@ + + 4.0.0 + com.baeldung + cucumber + 1.0.0-SNAPSHOT + jar + + + 1.8 + 1.8 + UTF-8 + 3.5.1 + 1.7.21 + 1.1.7 + 4.12 + 1.3 + 1.2.5 + 2.19.1 + + + + + + + + info.cukes + cucumber-junit + ${cucumber.version} + test + + + + info.cukes + cucumber-java + ${cucumber.version} + test + + + + org.hamcrest + hamcrest-library + ${hamcrest.library.version} + test + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + + ch.qos.logback + logback-classic + ${logback.version} + + + + ch.qos.logback + logback-core + ${logback.version} + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler.plugin.version} + + true + true + ${java.source.version} + ${java.target.version} + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.plugin.version} + + + **/CalculatorTest.java + + + + + + + \ No newline at end of file diff --git a/cucumber/src/main/java/com/baeldung/cucumber/calculator/Calculator.java b/cucumber/src/main/java/com/baeldung/cucumber/calculator/Calculator.java new file mode 100644 index 0000000000..fd4a3bad7b --- /dev/null +++ b/cucumber/src/main/java/com/baeldung/cucumber/calculator/Calculator.java @@ -0,0 +1,7 @@ +package com.baeldung.cucumber.calculator; + +public class Calculator { + public int add(int a, int b) { + return a + b; + } +} diff --git a/cucumber/src/test/java/com/baeldung/cucumber/calculator/CalculatorRunSteps.java b/cucumber/src/test/java/com/baeldung/cucumber/calculator/CalculatorRunSteps.java new file mode 100644 index 0000000000..9c0e920a8d --- /dev/null +++ b/cucumber/src/test/java/com/baeldung/cucumber/calculator/CalculatorRunSteps.java @@ -0,0 +1,38 @@ +package com.baeldung.cucumber.calculator; + +import org.hamcrest.Matchers; +import org.junit.Assert; + +import cucumber.api.java.Before; +import cucumber.api.java.en.Given; +import cucumber.api.java.en.Then; +import cucumber.api.java.en.When; + +public class CalculatorRunSteps { + + private int total; + + private Calculator calculator; + + @Before + private void init() { + total = -999; + + } + + @Given("^I have a calculator$") + public void initializeCalculator() throws Throwable { + calculator = new Calculator(); + } + + @When("^I add (-?\\d+) and (-?\\d+)$") + public void testAdd(int num1, int num2) throws Throwable { + total = calculator.add(num1, num2); + } + + @Then("^the result should be (-?\\d+)$") + public void validateResult(int result) throws Throwable { + Assert.assertThat(total, Matchers.equalTo(result)); + } + +} diff --git a/cucumber/src/test/java/com/baeldung/cucumber/calculator/CalculatorTest.java b/cucumber/src/test/java/com/baeldung/cucumber/calculator/CalculatorTest.java new file mode 100644 index 0000000000..6bbbca60d2 --- /dev/null +++ b/cucumber/src/test/java/com/baeldung/cucumber/calculator/CalculatorTest.java @@ -0,0 +1,15 @@ +package com.baeldung.cucumber.calculator; + +import org.junit.runner.RunWith; + +import cucumber.api.CucumberOptions; +import cucumber.api.junit.Cucumber; + +@RunWith(Cucumber.class) +@CucumberOptions( + features={"classpath:features/calculator.feature", "classpath:features/calculator-scenario-outline.feature"} + , plugin = { "pretty", "json:target/reports/json/calculator.json" } + , glue = {"com.baeldung.cucumber.calculator"} +) +public class CalculatorTest { +} diff --git a/cucumber/src/test/resources/features/calculator-scenario-outline.feature b/cucumber/src/test/resources/features/calculator-scenario-outline.feature new file mode 100644 index 0000000000..7437dbf5f9 --- /dev/null +++ b/cucumber/src/test/resources/features/calculator-scenario-outline.feature @@ -0,0 +1,16 @@ +Feature: Calculator + As a user + I want to use a calculator to add numbers + So that I don't need to add myself + + Scenario Outline: Add two numbers & + Given I have a calculator + When I add and + Then the result should be + + Examples: + | num1 | num2 | total | + | -2 | 3 | 1 | + | 10 | 15 | 25 | + | 99 | -99 | 0 | + | -1 | -10 | -11 | \ No newline at end of file diff --git a/cucumber/src/test/resources/features/calculator.feature b/cucumber/src/test/resources/features/calculator.feature new file mode 100644 index 0000000000..eaf05cb6ca --- /dev/null +++ b/cucumber/src/test/resources/features/calculator.feature @@ -0,0 +1,24 @@ +Feature: Calculator + As a user + I want to use a calculator to add numbers + So that I don't need to add myself + + Scenario: Add two numbers -2 & 3 + Given I have a calculator + When I add -2 and 3 + Then the result should be 1 + + Scenario: Add two numbers 10 & 15 + Given I have a calculator + When I add 10 and 15 + Then the result should be 25 + + Scenario: Add two numbers 99 & -99 + Given I have a calculator + When I add 99 and -99 + Then the result should be 0 + + Scenario: Add two numbers -1 & -10 + Given I have a calculator + When I add -1 and -10 + Then the result should be -11 \ No newline at end of file diff --git a/cucumber/src/test/resources/logback-test.xml b/cucumber/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..e980d88693 --- /dev/null +++ b/cucumber/src/test/resources/logback-test.xml @@ -0,0 +1,13 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n%ex + + + + + + + + + \ No newline at end of file diff --git a/guava/src/test/java/org/baeldung/guava/GuavaMathTest.java b/guava/src/test/java/org/baeldung/guava/GuavaMathTest.java index d0c551032c..b8e13f0650 100644 --- a/guava/src/test/java/org/baeldung/guava/GuavaMathTest.java +++ b/guava/src/test/java/org/baeldung/guava/GuavaMathTest.java @@ -1,167 +1,195 @@ package org.baeldung.guava; -import com.google.common.math.DoubleMath; -import com.google.common.math.IntMath; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.junit.Assert.*; import java.math.BigInteger; import java.math.RoundingMode; -import static org.hamcrest.core.IsEqual.equalTo; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; +import org.junit.Test; + +import com.google.common.math.DoubleMath; +import com.google.common.math.IntMath; public class GuavaMathTest { - @Test - public void testIntMathAdd() { - try { - IntMath.checkedAdd(Integer.MAX_VALUE, 1); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } + @Test(expected = ArithmeticException.class) + public void whenSumOverflow_thenThrowException() { + IntMath.checkedAdd(Integer.MAX_VALUE, 1); + } - try { - IntMath.checkedAdd(Integer.MIN_VALUE, -1); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } - - int result1 = IntMath.checkedAdd(2, 1); - assertThat(result1, equalTo(3)); - - int result2 = IntMath.saturatedAdd(Integer.MAX_VALUE, 100); - assertThat(result2, equalTo(Integer.MAX_VALUE)); - - int result3 = IntMath.saturatedAdd(Integer.MIN_VALUE, -100); - assertThat(result3, equalTo(Integer.MIN_VALUE)); + @Test(expected = ArithmeticException.class) + public void whenSumUnderflow_thenThrowException() { + IntMath.checkedAdd(Integer.MIN_VALUE, -1); } @Test - public void testIntMathSubtract() { - try { - IntMath.checkedSubtract(Integer.MIN_VALUE, 1); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } - - try { - IntMath.checkedSubtract(Integer.MAX_VALUE, -1); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - }; - - int result1 = IntMath.checkedSubtract(200, 100); - assertThat(result1, equalTo(100)); - - int result2 = IntMath.saturatedSubtract(Integer.MIN_VALUE, 1); - assertThat(result2, equalTo(Integer.MIN_VALUE)); - - int result3 = IntMath.saturatedSubtract(Integer.MAX_VALUE, -1); - assertThat(result3, equalTo(Integer.MAX_VALUE)); + public void should_calculate_sum() { + int result = IntMath.checkedAdd(2, 1); + assertThat(result, equalTo(3)); } @Test - public void testIntMathMultiply() { - try { - IntMath.checkedMultiply(Integer.MAX_VALUE, 2); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } - - try { - IntMath.checkedMultiply(Integer.MIN_VALUE, 2); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } - - int result1 = IntMath.checkedMultiply(21, 3); - assertThat(result1, equalTo(63)); - - int result2 = IntMath.saturatedMultiply(Integer.MAX_VALUE, 2); - assertThat(result2, equalTo(Integer.MAX_VALUE)); - - int result3 = IntMath.saturatedMultiply(Integer.MIN_VALUE, 2); - assertThat(result3, equalTo(Integer.MIN_VALUE)); + public void whenSumOverflow_thenReturnMaxInteger() { + int result = IntMath.saturatedAdd(Integer.MAX_VALUE, 100); + assertThat(result, equalTo(Integer.MAX_VALUE)); } @Test - public void testIntMathPow() { - try { - IntMath.checkedPow(Integer.MAX_VALUE, 2); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } + public void whenSumUnderflow_thenReturnMinInteger() { + int result = IntMath.saturatedAdd(Integer.MIN_VALUE, -100); + assertThat(result, equalTo(Integer.MIN_VALUE)); + } - try { - IntMath.checkedPow(Integer.MIN_VALUE, 3); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } + @Test(expected = ArithmeticException.class) + public void whenDifferenceOverflow_thenThrowException() { + IntMath.checkedSubtract(Integer.MAX_VALUE, -1); + } - int result1 = IntMath.saturatedPow(3, 3); - assertThat(result1, equalTo(27)); - - int result2 = IntMath.saturatedPow(Integer.MAX_VALUE, 2); - assertThat(result2, equalTo(Integer.MAX_VALUE)); - - int result3 = IntMath.saturatedPow(Integer.MIN_VALUE, 3); - assertThat(result3, equalTo(Integer.MIN_VALUE)); + @Test(expected = ArithmeticException.class) + public void whenDifferenceUnderflow_thenThrowException() { + IntMath.checkedSubtract(Integer.MIN_VALUE, 1); } @Test - public void testIntMathRound() { + public void should_calculate_difference() { + int result = IntMath.checkedSubtract(200, 100); + assertThat(result, equalTo(100)); + } + + @Test + public void whenDifferenceOverflow_thenReturnMaxInteger() { + int result = IntMath.saturatedSubtract(Integer.MAX_VALUE, -1); + assertThat(result, equalTo(Integer.MAX_VALUE)); + } + + @Test + public void whenDifferenceUnderflow_thenReturnMinInteger() { + int result = IntMath.saturatedSubtract(Integer.MIN_VALUE, 1); + assertThat(result, equalTo(Integer.MIN_VALUE)); + } + + @Test(expected = ArithmeticException.class) + public void whenProductOverflow_thenThrowException() { + IntMath.checkedMultiply(Integer.MAX_VALUE, 2); + } + + @Test(expected = ArithmeticException.class) + public void whenProductUnderflow_thenThrowException() { + IntMath.checkedMultiply(Integer.MIN_VALUE, 2); + } + + @Test + public void should_calculate_product() { + int result = IntMath.checkedMultiply(21, 3); + assertThat(result, equalTo(63)); + } + + @Test + public void whenProductOverflow_thenReturnMaxInteger() { + int result = IntMath.saturatedMultiply(Integer.MAX_VALUE, 2); + assertThat(result, equalTo(Integer.MAX_VALUE)); + } + + @Test + public void whenProductUnderflow_thenReturnMinInteger() { + int result = IntMath.saturatedMultiply(Integer.MIN_VALUE, 2); + assertThat(result, equalTo(Integer.MIN_VALUE)); + } + + @Test(expected = ArithmeticException.class) + public void whenPowerOverflow_thenThrowException() { + IntMath.checkedPow(Integer.MAX_VALUE, 2); + } + + @Test(expected = ArithmeticException.class) + public void whenPowerUnderflow_thenThrowException() { + IntMath.checkedPow(Integer.MIN_VALUE, 3); + } + + @Test + public void should_calculate_power() { + int result = IntMath.saturatedPow(3, 3); + assertThat(result, equalTo(27)); + } + + @Test + public void whenPowerOverflow_thenReturnMaxInteger() { + int result = IntMath.saturatedPow(Integer.MAX_VALUE, 2); + assertThat(result, equalTo(Integer.MAX_VALUE)); + } + + @Test + public void whenPowerUnderflow_thenReturnMinInteger() { + int result = IntMath.saturatedPow(Integer.MIN_VALUE, 3); + assertThat(result, equalTo(Integer.MIN_VALUE)); + } + + @Test + public void should_round_divide_result() { int result1 = IntMath.divide(3, 2, RoundingMode.DOWN); assertThat(result1, equalTo(1)); + int result2 = IntMath.divide(3, 2, RoundingMode.UP); assertThat(result2, equalTo(2)); - - int result3 = IntMath.log2(5, RoundingMode.FLOOR); - assertThat(result3, equalTo(2)); - int result4 = IntMath.log2(5, RoundingMode.CEILING); - assertThat(result4, equalTo(3)); - - int result5 = IntMath.log10(11, RoundingMode.HALF_UP); - assertThat(result5, equalTo(1)); - - int result6 = IntMath.sqrt(4, RoundingMode.UNNECESSARY); - assertThat(result6, equalTo(2)); - try { - IntMath.sqrt(5, RoundingMode.UNNECESSARY); - assertTrue(false); - } catch (ArithmeticException e) { - assertTrue(true); - } } @Test - public void testIntMathAdditionalFunctions() { - int result1 = IntMath.gcd(15, 20); - assertThat(result1, equalTo(5)); + public void should_round_log2_result() { + int result1 = IntMath.log2(5, RoundingMode.FLOOR); + assertThat(result1, equalTo(2)); - int result2 = IntMath.mod(8, 3); - assertThat(result2, equalTo(2)); + int result2 = IntMath.log2(5, RoundingMode.CEILING); + assertThat(result2, equalTo(3)); + } - boolean result3 = IntMath.isPowerOfTwo(8); - assertTrue(result3); - boolean result4 = IntMath.isPowerOfTwo(9); - assertFalse(result4); + @Test + public void should_round_log10_result() { + int result = IntMath.log10(11, RoundingMode.HALF_UP); + assertThat(result, equalTo(1)); + } - int result5 = IntMath.factorial(4); - assertThat(result5, equalTo(24)); + @Test + public void should_round_sqrt_result() { + int result = IntMath.sqrt(4, RoundingMode.UNNECESSARY); + assertThat(result, equalTo(2)); + } - int result6 = IntMath.binomial(7, 3); - assertThat(result6, equalTo(35)); + @Test(expected = ArithmeticException.class) + public void whenNeedRounding_thenThrowException() { + IntMath.sqrt(5, RoundingMode.UNNECESSARY); + } + + @Test + public void should_calculate_gcd() { + int result = IntMath.gcd(15, 20); + assertThat(result, equalTo(5)); + } + + @Test + public void should_calculate_mod() { + int result = IntMath.mod(8, 3); + assertThat(result, equalTo(2)); + } + + @Test + public void should_test_if_is_power_of_two() { + boolean result1 = IntMath.isPowerOfTwo(8); + assertTrue(result1); + + boolean result2 = IntMath.isPowerOfTwo(9); + assertFalse(result2); + } + + @Test + public void should_calculate_factorial() { + int result = IntMath.factorial(4); + assertThat(result, equalTo(24)); + } + + @Test + public void should_calculate_binomial() { + int result = IntMath.binomial(7, 3); + assertThat(result, equalTo(35)); } @Test diff --git a/jee7/pom.xml b/jee7/pom.xml index 26d433df78..e398651055 100644 --- a/jee7/pom.xml +++ b/jee7/pom.xml @@ -7,7 +7,6 @@ jee7 1.0-SNAPSHOT JavaEE 7 Arquillian Archetype Sample - war 1.8 @@ -28,6 +27,7 @@ 3.6.0 2.6 + 2.19.1 @@ -43,6 +43,13 @@ import pom + + org.jboss.arquillian.extension + arquillian-drone-bom + 2.0.1.Final + pom + import + @@ -65,6 +72,13 @@ arquillian-junit-container test + + org.jboss.arquillian.graphene + graphene-webdriver + 2.1.0.Final + pom + test + com.jayway.awaitility awaitility @@ -84,7 +98,47 @@ shrinkwrap-resolver-impl-maven-archive test - + + org.apache.httpcomponents + httpclient + 4.5 + + + commons-io + commons-io + 2.4 + + + com.sun.faces + jsf-api + 2.2.14 + + + com.sun.faces + jsf-impl + 2.2.14 + + + javax.servlet + jstl + 1.2 + + + javax.servlet + javax.servlet-api + 3.1.0 + + + javax.servlet.jsp + jsp-api + 2.2 + provided + + + taglibs + standard + 1.1.2 + @@ -167,6 +221,7 @@ + maven-dependency-plugin @@ -206,6 +261,7 @@ + @@ -331,5 +387,21 @@ + + webdriver-chrome + + true + + + chrome + + + + + webdriver-firefox + + firefox + + diff --git a/jee7/src/main/java/com/baeldung/convListVal/ConvListVal.java b/jee7/src/main/java/com/baeldung/convListVal/ConvListVal.java new file mode 100644 index 0000000000..245c69f2bb --- /dev/null +++ b/jee7/src/main/java/com/baeldung/convListVal/ConvListVal.java @@ -0,0 +1,56 @@ +package com.baeldung.convListVal; + +import java.util.Date; + +import javax.faces.bean.ManagedBean; + +@ManagedBean +public class ConvListVal { + + private Integer age; + private Double average; + private Date myDate; + private String name; + private String surname; + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public Double getAverage() { + return average; + } + + public void setAverage(Double average) { + this.average = average; + } + + public Date getMyDate() { + return myDate; + } + + public void setMyDate(Date myDate) { + this.myDate = myDate; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSurname() { + return surname; + } + + public void setSurname(String surname) { + this.surname = surname; + } + +} diff --git a/jee7/src/main/java/com/baeldung/convListVal/MyListener.java b/jee7/src/main/java/com/baeldung/convListVal/MyListener.java new file mode 100644 index 0000000000..784bddd59a --- /dev/null +++ b/jee7/src/main/java/com/baeldung/convListVal/MyListener.java @@ -0,0 +1,21 @@ +package com.baeldung.convListVal; + +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.faces.event.AbortProcessingException; +import javax.faces.event.ValueChangeEvent; +import javax.faces.event.ValueChangeListener; + +public class MyListener implements ValueChangeListener { + + private static final Logger LOG = Logger.getLogger(MyListener.class.getName()); + @Override + public void processValueChange(ValueChangeEvent event) throws AbortProcessingException { + if (event.getNewValue() != null) { + LOG.log(Level.INFO, "\tNew Value:{0}", event.getNewValue()); + } + + } + +} diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/README.txt b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/README.txt index 063856b2be..0f95e588b8 100644 --- a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/README.txt +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/README.txt @@ -12,8 +12,17 @@ NOTES: @WebServlet annotation designates the AccountServlet class as a Servlet c An initialization parameter 'type' is being set to denote the type of the bank account. @ServletSecurity annotation imposes security constraints on the AccountServlet based on - the tomcat-users.xml (this code assumes there is a role 'admin' in your tomcat-users.xml) - + the tomcat-users.xml. +   + This code assumes that your tomcat-users.xml looks as follows: + + + + + + + +   N.B : To see @ServletSecurity annotation in action, please uncomment the annotation code for @ServletSecurity. diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/AccountServlet.java b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/AccountServlet.java index a8ed74984b..a487d4c3b1 100644 --- a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/AccountServlet.java +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/AccountServlet.java @@ -1,4 +1,4 @@ -package com.baeldung.javaeeannotations; +package com.baeldung.javaeeannotations.JavaEEAnnotationsSample.src.main.java.com.baeldung.javaeeannotations; import java.io.IOException; import java.io.PrintWriter; @@ -17,8 +17,8 @@ import javax.servlet.http.HttpServletResponse; initParams = { @WebInitParam(name = "type", value = "savings") } ) /*@ServletSecurity( - value = @HttpConstraint(rolesAllowed = {"admin"}), - httpMethodConstraints = {@HttpMethodConstraint(value = "POST", rolesAllowed = {"admin"})} + value = @HttpConstraint(rolesAllowed = {"Member"}), + httpMethodConstraints = {@HttpMethodConstraint(value = "POST", rolesAllowed = {"Admin"})} )*/ public class AccountServlet extends javax.servlet.http.HttpServlet { diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/BankAppServletContextListener.java b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/BankAppServletContextListener.java index ee1b624cd1..dc9a91d059 100644 --- a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/BankAppServletContextListener.java +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/BankAppServletContextListener.java @@ -1,4 +1,4 @@ -package com.baeldung.javaeeannotations; +package com.baeldung.javaeeannotations.JavaEEAnnotationsSample.src.main.java.com.baeldung.javaeeannotations; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/LogInFilter.java b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/LogInFilter.java index 5ee420f6a2..bfe1a39377 100644 --- a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/LogInFilter.java +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/LogInFilter.java @@ -1,4 +1,4 @@ -package com.baeldung.javaeeannotations; +package com.baeldung.javaeeannotations.JavaEEAnnotationsSample.src.main.java.com.baeldung.javaeeannotations; import java.io.IOException; diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/UploadCustomerDocumentsServlet.java b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/UploadCustomerDocumentsServlet.java index 28922dba46..6945f663bb 100644 --- a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/UploadCustomerDocumentsServlet.java +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/java/com/baeldung/javaeeannotations/UploadCustomerDocumentsServlet.java @@ -1,4 +1,4 @@ -package com.baeldung.javaeeannotations; +package com.baeldung.javaeeannotations.JavaEEAnnotationsSample.src.main.java.com.baeldung.javaeeannotations; import java.io.IOException; import java.io.PrintWriter; diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/webapp/web.xml b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/webapp/WEB-INF/web.xml similarity index 97% rename from jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/webapp/web.xml rename to jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/webapp/WEB-INF/web.xml index f01eb341e4..a92885ec11 100644 --- a/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/webapp/web.xml +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/JavaEEAnnotationsSample/src/main/webapp/WEB-INF/web.xml @@ -7,5 +7,4 @@ BASIC default - - \ No newline at end of file + diff --git a/jee7/src/main/java/com/baeldung/jaxws/exception/EmployeeAlreadyExists.java b/jee7/src/main/java/com/baeldung/jaxws/exception/EmployeeAlreadyExists.java index 4842fbf84c..8a96f8aec0 100644 --- a/jee7/src/main/java/com/baeldung/jaxws/exception/EmployeeAlreadyExists.java +++ b/jee7/src/main/java/com/baeldung/jaxws/exception/EmployeeAlreadyExists.java @@ -1,13 +1,9 @@ package com.baeldung.jaxws.exception; -import java.io.Serializable; - import javax.xml.ws.WebFault; @WebFault -public class EmployeeAlreadyExists extends Exception implements Serializable { - - private static final long serialVersionUID = 1L; +public class EmployeeAlreadyExists extends Exception { public EmployeeAlreadyExists() { super("This employee already exists"); diff --git a/jee7/src/main/java/com/baeldung/jaxws/exception/EmployeeNotFound.java b/jee7/src/main/java/com/baeldung/jaxws/exception/EmployeeNotFound.java index 667e3e0c72..3de2ca8db6 100644 --- a/jee7/src/main/java/com/baeldung/jaxws/exception/EmployeeNotFound.java +++ b/jee7/src/main/java/com/baeldung/jaxws/exception/EmployeeNotFound.java @@ -1,10 +1,9 @@ package com.baeldung.jaxws.exception; import javax.xml.ws.WebFault; -import java.io.Serializable; @WebFault -public class EmployeeNotFound extends Exception implements Serializable { +public class EmployeeNotFound extends Exception { public EmployeeNotFound() { super("The specified employee does not exist"); diff --git a/jee7/src/main/java/com/baeldung/jaxws/model/Employee.java b/jee7/src/main/java/com/baeldung/jaxws/model/Employee.java index 5b1673c1e4..dbbdc234cf 100644 --- a/jee7/src/main/java/com/baeldung/jaxws/model/Employee.java +++ b/jee7/src/main/java/com/baeldung/jaxws/model/Employee.java @@ -1,9 +1,6 @@ package com.baeldung.jaxws.model; -import java.io.Serializable; - -public class Employee implements Serializable { - private static final long serialVersionUID = 1L; +public class Employee { private int id; private String firstName; diff --git a/jee7/src/main/webapp/ConvListVal.xhtml b/jee7/src/main/webapp/ConvListVal.xhtml new file mode 100644 index 0000000000..8c5213764c --- /dev/null +++ b/jee7/src/main/webapp/ConvListVal.xhtml @@ -0,0 +1,50 @@ + + + + + Converters, Listeners and Validators + + +

Testing converters

+ + + + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + + + + +
+ +
+
+ diff --git a/jee7/src/main/webapp/WEB-INF/faces-config.xml b/jee7/src/main/webapp/WEB-INF/faces-config.xml new file mode 100644 index 0000000000..d5b2cd6612 --- /dev/null +++ b/jee7/src/main/webapp/WEB-INF/faces-config.xml @@ -0,0 +1,13 @@ + + + + convListVal + com.baeldung.convListVal.ConvListVal + session + + \ No newline at end of file diff --git a/jee7/src/main/webapp/WEB-INF/web.xml b/jee7/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..11bd87cf99 --- /dev/null +++ b/jee7/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,41 @@ + + + + + Faces Servlet + javax.faces.webapp.FacesServlet + + + Faces Servlet + *.jsf + + + javax.faces.PROJECT_STAGE + Development + + + State saving method: 'client' or 'server' (default). See JSF Specification section 2.5.2 + javax.faces.STATE_SAVING_METHOD + client + + + + index.jsf + welcome.jsf + index.html + index.jsp + + \ No newline at end of file diff --git a/jee7/src/test/java/com/baeldung/convListVal/ConvListValTest.java b/jee7/src/test/java/com/baeldung/convListVal/ConvListValTest.java new file mode 100644 index 0000000000..4450a26f43 --- /dev/null +++ b/jee7/src/test/java/com/baeldung/convListVal/ConvListValTest.java @@ -0,0 +1,101 @@ +package com.baeldung.convListVal; + +import static org.jboss.arquillian.graphene.Graphene.guardHttp; + +import java.io.File; +import java.net.URL; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.drone.api.annotation.Drone; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.openqa.selenium.By; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.FindBy; + +@RunWith(Arquillian.class) +public class ConvListValTest { + + @ArquillianResource + private URL deploymentUrl; + + private static final String WEBAPP_SRC = "src/main/webapp"; + + @Deployment(testable = false) + public static WebArchive createDeployment() { + return ( ShrinkWrap.create( + WebArchive.class, "jee7.war"). + addClasses(ConvListVal.class, MyListener.class)). + addAsWebResource(new File(WEBAPP_SRC, "ConvListVal.xhtml")). + addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); + } + + @Drone + WebDriver browser; + + @ArquillianResource + URL contextPath; + + @FindBy(id="myForm:age") + private WebElement ageInput; + + @FindBy(id="myForm:average") + private WebElement averageInput; + + @FindBy(id="myForm:send") + private WebElement sendButton; + + @Test + @RunAsClient + public void givenAge_whenAgeInvalid_thenErrorMessage() throws Exception { + browser.get(deploymentUrl.toExternalForm() + "ConvListVal.jsf"); + ageInput.sendKeys("stringage"); + guardHttp(sendButton).click(); + Assert.assertTrue("Show Age error message", browser.findElements(By.id("myForm:ageError")).size() > 0); + } + + @Test + @RunAsClient + public void givenAverage_whenAverageInvalid_thenErrorMessage() throws Exception { + browser.get(deploymentUrl.toExternalForm() + "ConvListVal.jsf"); + averageInput.sendKeys("stringaverage"); + guardHttp(sendButton).click(); + Assert.assertTrue("Show Average error message", browser.findElements(By.id("myForm:averageError")).size() > 0); + } + + @Test + @RunAsClient + public void givenDate_whenDateInvalid_thenErrorMessage() throws Exception { + browser.get(deploymentUrl.toExternalForm() + "ConvListVal.jsf"); + averageInput.sendKeys("123"); + guardHttp(sendButton).click(); + Assert.assertTrue("Show Date error message", browser.findElements(By.id("myForm:myDateError")).size() > 0); + } + + @Test + @RunAsClient + public void givenSurname_whenSurnameMinLenghtInvalid_thenErrorMessage() throws Exception { + browser.get(deploymentUrl.toExternalForm() + "ConvListVal.jsf"); + averageInput.sendKeys("aaa"); + guardHttp(sendButton).click(); + Assert.assertTrue("Show Surname error message", browser.findElements(By.id("myForm:surnameError")).size() > 0); + } + + @Test + @RunAsClient + public void givenSurname_whenSurnameMaxLenghtInvalid_thenErrorMessage() throws Exception { + browser.get(deploymentUrl.toExternalForm() + "ConvListVal.jsf"); + averageInput.sendKeys("aaaaabbbbbc"); + guardHttp(sendButton).click(); + Assert.assertTrue("Show Surname error message", browser.findElements(By.id("myForm:surnameError")).size() > 0); + } + +} diff --git a/jee7/src/test/java/com/baeldung/jaxws/EmployeeServiceLiveTest.java b/jee7/src/test/java/com/baeldung/jaxws/EmployeeServiceLiveTest.java index 5311b3c5fe..4429703468 100644 --- a/jee7/src/test/java/com/baeldung/jaxws/EmployeeServiceLiveTest.java +++ b/jee7/src/test/java/com/baeldung/jaxws/EmployeeServiceLiveTest.java @@ -1,4 +1,4 @@ -package com.baeldung.jaxws; +/*package com.baeldung.jaxws; import static org.junit.Assert.assertEquals; @@ -108,3 +108,4 @@ public class EmployeeServiceLiveTest { } } +*/ \ No newline at end of file diff --git a/libraries/README.md b/libraries/README.md index a8ecf56cc2..7d95caa6b1 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -5,6 +5,7 @@ - [String Processing with Apache Commons Lang 3](http://www.baeldung.com/string-processing-commons-lang) - [Introduction to Javatuples](http://www.baeldung.com/java-tuples) - [Introduction to Javassist](http://www.baeldung.com/javassist) +- [Embedded Jetty Server in Java](http://www.baeldung.com/jetty-embedded) The libraries module contains examples related to small libraries that are relatively easy to use and does not require any separate module of its own. diff --git a/libraries/pom.xml b/libraries/pom.xml index 11295230b4..939d674d97 100644 --- a/libraries/pom.xml +++ b/libraries/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"> parent-modules com.baeldung @@ -20,6 +20,31 @@ 1.8 + + org.apache.maven.plugins + maven-dependency-plugin + + + org.apache.felix + maven-bundle-plugin + 3.3.0 + maven-plugin + + + + true + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + **/*IntegrationTest.java + **/*LiveTest.java + + +
@@ -72,6 +97,62 @@ javers-core ${javers.version} + + org.eclipse.jetty + jetty-server + ${jetty.version} + + + org.eclipse.jetty + jetty-servlet + ${jetty.version} + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + commons-io + commons-io + ${commons.io.version} + + + org.eclipse.jetty + jetty-server + ${jetty.version} + + + org.eclipse.jetty + jetty-servlet + ${jetty.version} + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + commons-io + commons-io + ${commons.io.version} + + + org.apache.flink + flink-core + ${flink.version} + + + org.apache.flink + flink-java + ${flink.version} + + + org.apache.flink + flink-test-utils_2.10 + ${flink.version} + test + @@ -84,6 +165,14 @@ 3.6.2 1.5.0 3.1.0 + 9.4.3.v20170317 + 4.5.3 + 2.5 + 9.4.2.v20170220 + 4.5.3 + 2.5 + 1.2.0 + 2.19.1 \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/flink/LineSplitter.java b/libraries/src/main/java/com/baeldung/flink/LineSplitter.java new file mode 100644 index 0000000000..8deeeb01c4 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/flink/LineSplitter.java @@ -0,0 +1,20 @@ +package com.baeldung.flink; + +import org.apache.flink.api.common.functions.FlatMapFunction; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.util.Collector; + +import java.util.stream.Stream; + +@SuppressWarnings("serial") +public class LineSplitter implements FlatMapFunction> { + + @Override + public void flatMap(String value, Collector> out) { + + String[] tokens = value.toLowerCase().split("\\W+"); + Stream.of(tokens) + .filter(t -> t.length() > 0) + .forEach(token -> out.collect(new Tuple2<>(token, 1))); + } +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/flink/WordCount.java b/libraries/src/main/java/com/baeldung/flink/WordCount.java new file mode 100644 index 0000000000..ab109bdbce --- /dev/null +++ b/libraries/src/main/java/com/baeldung/flink/WordCount.java @@ -0,0 +1,20 @@ +package com.baeldung.flink; + +import org.apache.flink.api.java.DataSet; +import org.apache.flink.api.java.ExecutionEnvironment; +import org.apache.flink.api.java.aggregation.Aggregations; +import org.apache.flink.api.java.tuple.Tuple2; + +import java.util.List; + +public class WordCount { + + public static DataSet> startWordCount(ExecutionEnvironment env, List lines) throws Exception { + DataSet text = env.fromCollection(lines); + + return text.flatMap(new LineSplitter()) + .groupBy(0) + .aggregate(Aggregations.SUM, 1); + + } +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/jetty/AsyncServlet.java b/libraries/src/main/java/com/baeldung/jetty/AsyncServlet.java new file mode 100644 index 0000000000..d1bddd097f --- /dev/null +++ b/libraries/src/main/java/com/baeldung/jetty/AsyncServlet.java @@ -0,0 +1,42 @@ +package com.baeldung.jetty; + +import javax.servlet.AsyncContext; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.WriteListener; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +public class AsyncServlet extends HttpServlet { + private static final String HEAVY_RESOURCE = "This is some heavy resource that will be served in an async way"; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + ByteBuffer content = ByteBuffer.wrap(HEAVY_RESOURCE.getBytes(StandardCharsets.UTF_8)); + + AsyncContext async = request.startAsync(); + ServletOutputStream out = response.getOutputStream(); + out.setWriteListener(new WriteListener() { + @Override + public void onWritePossible() throws IOException { + while (out.isReady()) { + if (!content.hasRemaining()) { + response.setStatus(200); + async.complete(); + return; + } + out.write(content.get()); + } + } + + @Override + public void onError(Throwable t) { + getServletContext().log("Async Error", t); + async.complete(); + } + }); + } +} \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/jetty/BlockingServlet.java b/libraries/src/main/java/com/baeldung/jetty/BlockingServlet.java new file mode 100644 index 0000000000..f1de71beeb --- /dev/null +++ b/libraries/src/main/java/com/baeldung/jetty/BlockingServlet.java @@ -0,0 +1,17 @@ +package com.baeldung.jetty; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class BlockingServlet extends HttpServlet { + + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.setContentType("application/json"); + response.setStatus(HttpServletResponse.SC_OK); + response.getWriter().println("{ \"status\": \"ok\"}"); + } +} + diff --git a/libraries/src/main/java/com/baeldung/jetty/JettyServer.java b/libraries/src/main/java/com/baeldung/jetty/JettyServer.java new file mode 100644 index 0000000000..1033a7266d --- /dev/null +++ b/libraries/src/main/java/com/baeldung/jetty/JettyServer.java @@ -0,0 +1,39 @@ +package com.baeldung.jetty; + +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.servlet.ServletHandler; +import org.eclipse.jetty.util.thread.QueuedThreadPool; + +public class JettyServer { + + private Server server; + + public void start() throws Exception { + + int maxThreads = 100; + int minThreads = 10; + int idleTimeout = 120; + + QueuedThreadPool threadPool = new QueuedThreadPool(maxThreads, minThreads, idleTimeout); + + server = new Server(threadPool); + ServerConnector connector = new ServerConnector(server); + connector.setPort(8090); + server.setConnectors(new Connector[]{connector}); + + ServletHandler servletHandler = new ServletHandler(); + server.setHandler(servletHandler); + + servletHandler.addServletWithMapping(BlockingServlet.class, "/status"); + servletHandler.addServletWithMapping(AsyncServlet.class, "/heavy/async"); + + server.start(); + + } + + public void stop() throws Exception { + server.stop(); + } +} diff --git a/libraries/src/test/java/com/baeldung/flink/WordCountIntegrationTest.java b/libraries/src/test/java/com/baeldung/flink/WordCountIntegrationTest.java new file mode 100644 index 0000000000..a5613e2406 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/flink/WordCountIntegrationTest.java @@ -0,0 +1,186 @@ +package com.baeldung.flink; + +import org.apache.flink.api.common.operators.Order; +import org.apache.flink.api.java.DataSet; +import org.apache.flink.api.java.ExecutionEnvironment; +import org.apache.flink.api.java.functions.KeySelector; +import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.api.java.tuple.Tuple3; +import org.apache.flink.streaming.api.datastream.DataStream; +import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator; +import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; +import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; +import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows; +import org.apache.flink.streaming.api.windowing.time.Time; +import org.junit.Test; + +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + + +public class WordCountIntegrationTest { + private final ExecutionEnvironment env = ExecutionEnvironment.getExecutionEnvironment(); + + @Test + public void givenDataSet_whenExecuteWordCount_thenReturnWordCount() throws Exception { + //given + List lines = Arrays.asList("This is a first sentence", "This is a second sentence with a one word"); + + //when + DataSet> result = WordCount.startWordCount(env, lines); + + //then + List> collect = result.collect(); + assertThat(collect).containsExactlyInAnyOrder( + new Tuple2<>("a", 3), new Tuple2<>("sentence", 2), new Tuple2<>("word", 1), + new Tuple2<>("is", 2), new Tuple2<>("this", 2), new Tuple2<>("second", 1), + new Tuple2<>("first", 1), new Tuple2<>("with", 1), new Tuple2<>("one", 1)); + } + + @Test + public void givenListOfAmounts_whenUseMapReduce_thenSumAmountsThatAreOnlyAboveThreshold() throws Exception { + //given + DataSet amounts = env.fromElements(1, 29, 40, 50); + int threshold = 30; + + //when + List collect = amounts + .filter(a -> a > threshold) + .reduce((integer, t1) -> integer + t1) + .collect(); + + //then + assertThat(collect.get(0)).isEqualTo(90); + } + + @Test + public void givenDataSetOfComplexObjects_whenMapToGetOneField_thenReturnedListHaveProperElements() throws Exception { + //given + DataSet personDataSource = env.fromCollection(Arrays.asList(new Person(23, "Tom"), new Person(75, "Michael"))); + + //when + List ages = personDataSource.map(p -> p.age).collect(); + + //then + assertThat(ages).hasSize(2); + assertThat(ages).contains(23, 75); + + } + + @Test + public void givenDataSet_whenSortItByOneField_thenShouldReturnSortedDataSet() throws Exception { + //given + Tuple2 secondPerson = new Tuple2<>(4, "Tom"); + Tuple2 thirdPerson = new Tuple2<>(5, "Scott"); + Tuple2 fourthPerson = new Tuple2<>(200, "Michael"); + Tuple2 firstPerson = new Tuple2<>(1, "Jack"); + DataSet> transactions = env.fromElements(fourthPerson, secondPerson, + thirdPerson, firstPerson); + + + //when + List> sorted = transactions + .sortPartition(new IdKeySelectorTransaction(), Order.ASCENDING) + .collect(); + + //then + assertThat(sorted).containsExactly(firstPerson, secondPerson, thirdPerson, fourthPerson); + } + + + @Test + public void giveTwoDataSets_whenJoinUsingId_thenProduceJoinedData() throws Exception { + //given + Tuple3 address = new Tuple3<>(1, "5th Avenue", "London"); + DataSet> addresses = env.fromElements(address); + + Tuple2 firstTransaction = new Tuple2<>(1, "Transaction_1"); + DataSet> transactions = + env.fromElements(firstTransaction, new Tuple2<>(12, "Transaction_2")); + + + //when + List, Tuple3>> joined = + transactions.join(addresses) + .where(new IdKeySelectorTransaction()) + .equalTo(new IdKeySelectorAddress()) + .collect(); + + //then + assertThat(joined).hasSize(1); + assertThat(joined).contains(new Tuple2<>(firstTransaction, address)); + + } + + @Test + public void givenStreamOfEvents_whenProcessEvents_thenShouldPrintResultsOnSinkOperation() throws Exception { + //given + final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + DataStream text + = env.fromElements("This is a first sentence", "This is a second sentence with a one word"); + + + SingleOutputStreamOperator upperCase = text.map(String::toUpperCase); + + upperCase.print(); + + //when + env.execute(); + } + + + @Test + public void givenStreamOfEvents_whenProcessEvents_thenShouldApplyWindowingOnTransformation() throws Exception { + //given + final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); + + SingleOutputStreamOperator> windowed = env.fromElements( + new Tuple2<>(16, ZonedDateTime.now().plusMinutes(25).toInstant().getEpochSecond()), + new Tuple2<>(15, ZonedDateTime.now().plusMinutes(2).toInstant().getEpochSecond()) + ).assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor>(Time.seconds(20)) { + @Override + public long extractTimestamp(Tuple2 element) { + return element.f1 * 1000; + } + }); + + SingleOutputStreamOperator> reduced = windowed + .windowAll(TumblingEventTimeWindows.of(Time.seconds(5))) + .maxBy(0, true); + + reduced.print(); + + //when + env.execute(); + } + + + private static class IdKeySelectorTransaction implements KeySelector, Integer> { + @Override + public Integer getKey(Tuple2 value) { + return value.f0; + } + } + + private static class IdKeySelectorAddress implements KeySelector, Integer> { + @Override + public Integer getKey(Tuple3 value) { + return value.f0; + } + } + + private static class Person { + private final int age; + private final String name; + + private Person(int age, String name) { + this.age = age; + this.name = name; + } + } + +} \ No newline at end of file diff --git a/libraries/src/test/java/com/baeldung/jetty/JettyTest.java b/libraries/src/test/java/com/baeldung/jetty/JettyTest.java new file mode 100644 index 0000000000..caf70f9af3 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/jetty/JettyTest.java @@ -0,0 +1,58 @@ +package com.baeldung.jetty; + + +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.HttpClientBuilder; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.nio.charset.StandardCharsets; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; + +public class JettyTest { + private JettyServer jettyServer; + + @Before + public void setup() throws Exception { + jettyServer = new JettyServer(); + jettyServer.start(); + } + + @After + public void cleanup() throws Exception { + Thread.sleep(2000); + jettyServer.stop(); + } + + @Test + public void givenServer_whenSendRequestToBlockingServlet_thenReturnStatusOK() throws Exception { + //given + String url = "http://localhost:8090/status"; + HttpClient client = HttpClientBuilder.create().build(); + HttpGet request = new HttpGet(url); + HttpResponse response = client.execute(request); + + //then + assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); + + } + + @Test + public void givenServer_whenSendRequestToNonBlockingServlet_thenReturnStatusOK() throws Exception { + //when + String url = "http://localhost:8090/heavy/async"; + HttpClient client = HttpClientBuilder.create().build(); + HttpGet request = new HttpGet(url); + HttpResponse response = client.execute(request); + + //then + assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); + String responseContent = IOUtils.toString(response.getEntity().getContent(), StandardCharsets.UTF_8); + assertThat(responseContent).isEqualTo("This is some heavy resource that will be served in an async way"); + } +} diff --git a/mesos-marathon/pom.xml b/mesos-marathon/pom.xml index ca17a5c4c4..92b56e721b 100644 --- a/mesos-marathon/pom.xml +++ b/mesos-marathon/pom.xml @@ -40,6 +40,16 @@ + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*IntegrationTest.java + **/*LiveTest.java + + + diff --git a/mesos-marathon/src/main/java/com/mogronalol/DemoApplication.java b/mesos-marathon/src/main/java/com/baeldung/DemoApplication.java similarity index 81% rename from mesos-marathon/src/main/java/com/mogronalol/DemoApplication.java rename to mesos-marathon/src/main/java/com/baeldung/DemoApplication.java index f757178026..b2c5302277 100644 --- a/mesos-marathon/src/main/java/com/mogronalol/DemoApplication.java +++ b/mesos-marathon/src/main/java/com/baeldung/DemoApplication.java @@ -1,10 +1,8 @@ -package com.mogronalol; +package com.baeldung; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import javax.annotation.PostConstruct; - @SpringBootApplication public class DemoApplication { diff --git a/mesos-marathon/src/main/java/com/mogronalol/HelloController.java b/mesos-marathon/src/main/java/com/baeldung/HelloController.java similarity index 82% rename from mesos-marathon/src/main/java/com/mogronalol/HelloController.java rename to mesos-marathon/src/main/java/com/baeldung/HelloController.java index 2059280ba0..83eca1f501 100644 --- a/mesos-marathon/src/main/java/com/mogronalol/HelloController.java +++ b/mesos-marathon/src/main/java/com/baeldung/HelloController.java @@ -1,6 +1,5 @@ -package com.mogronalol; +package com.baeldung; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; diff --git a/mesos-marathon/src/test/java/com/mogronalol/DemoApplicationTests.java b/mesos-marathon/src/test/java/com/baeldung/DemoApplicationIntegrationTest.java similarity index 88% rename from mesos-marathon/src/test/java/com/mogronalol/DemoApplicationTests.java rename to mesos-marathon/src/test/java/com/baeldung/DemoApplicationIntegrationTest.java index 5e88f9a70f..85331516f9 100644 --- a/mesos-marathon/src/test/java/com/mogronalol/DemoApplicationTests.java +++ b/mesos-marathon/src/test/java/com/baeldung/DemoApplicationIntegrationTest.java @@ -1,11 +1,10 @@ -package com.mogronalol; +package com.baeldung; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.context.embedded.LocalServerPort; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.web.client.RestTemplate; @@ -13,7 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = {DemoApplication.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public class DemoApplicationTests { +public class DemoApplicationIntegrationTest { private RestTemplate restTemplate; diff --git a/mockito/src/test/java/org/baeldung/mockito/MockitoConfigExamplesTest.java b/mockito/src/test/java/org/baeldung/mockito/MockitoConfigExamplesTest.java index de6e7fca72..5050a2d6bc 100644 --- a/mockito/src/test/java/org/baeldung/mockito/MockitoConfigExamplesTest.java +++ b/mockito/src/test/java/org/baeldung/mockito/MockitoConfigExamplesTest.java @@ -2,8 +2,6 @@ package org.baeldung.mockito; import org.junit.Test; import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; import static org.hamcrest.Matchers.equalTo; @@ -69,7 +67,7 @@ public class MockitoConfigExamplesTest { } @Test - public final void whenMockMethodCallIsConfiguredToCallTheRealMethod_thenRealMetehodIsCalled() { + public final void whenMockMethodCallIsConfiguredToCallTheRealMethod_thenRealMethodIsCalled() { final MyList listMock = Mockito.mock(MyList.class); when(listMock.size()).thenCallRealMethod(); @@ -77,14 +75,9 @@ public class MockitoConfigExamplesTest { } @Test - public final void whenMockMethodCallIsConfiguredWithCustomAnswer_thenRealMetehodIsCalled() { + public final void whenMockMethodCallIsConfiguredWithCustomAnswer_thenRealMethodIsCalled() { final MyList listMock = Mockito.mock(MyList.class); - doAnswer(new Answer() { - @Override - public final String answer(final InvocationOnMock invocation) { - return "Always the same"; - } - }).when(listMock).get(anyInt()); + doAnswer(invocation -> "Always the same").when(listMock).get(anyInt()); final String element = listMock.get(1); assertThat(element, is(equalTo("Always the same"))); diff --git a/mybatis/pom.xml b/mybatis/pom.xml new file mode 100644 index 0000000000..56de727b21 --- /dev/null +++ b/mybatis/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + com.baeldung + mybatis + 1.0.0-SNAPSHOT + + 4.12 + 10.13.1.1 + 3.2.2 + + + + org.apache.derby + derby + ${derby.version} + + + org.mybatis + mybatis + ${mybatis.version} + + + junit + junit + ${junit.version} + test + + + + \ No newline at end of file diff --git a/mybatis/src/main/java/com/baeldung/mybatis/mapper/AddressMapper.java b/mybatis/src/main/java/com/baeldung/mybatis/mapper/AddressMapper.java new file mode 100644 index 0000000000..588707383b --- /dev/null +++ b/mybatis/src/main/java/com/baeldung/mybatis/mapper/AddressMapper.java @@ -0,0 +1,24 @@ +package com.baeldung.mybatis.mapper; + +import com.baeldung.mybatis.model.Address; +import com.baeldung.mybatis.model.Person; +import org.apache.ibatis.annotations.*; + + +public interface AddressMapper { + + @Insert("Insert into address (streetAddress,personId) values(#{streetAddress},#{personId})") + @Options(useGeneratedKeys = true,flushCache=true ) + public Integer saveAddress(Address address); + + @Select("SELECT addressId, streetAddress FROM Address WHERE addressId = #{addressId}") + @Results(value = { + @Result(property = "addressId", column = "addressId"), + @Result(property = "streetAddress", column = "streetAddress"), + @Result(property = "person", column = "personId",javaType =Person.class,one=@One(select = "getPerson")) + }) + Address getAddresses(Integer addressID); + + @Select("SELECT personId FROM address WHERE addressId = #{addressId})") + Person getPerson(Integer personId); +} diff --git a/mybatis/src/main/java/com/baeldung/mybatis/mapper/PersonMapper.java b/mybatis/src/main/java/com/baeldung/mybatis/mapper/PersonMapper.java new file mode 100644 index 0000000000..ab207325ad --- /dev/null +++ b/mybatis/src/main/java/com/baeldung/mybatis/mapper/PersonMapper.java @@ -0,0 +1,52 @@ +package com.baeldung.mybatis.mapper; + +import com.baeldung.mybatis.model.Address; +import com.baeldung.mybatis.model.Person; +import com.baeldung.mybatis.utils.MyBatisUtil; +import org.apache.ibatis.annotations.*; +import org.apache.ibatis.mapping.StatementType; + +import java.util.List; +import java.util.Map; + + +public interface PersonMapper { + + @Insert("Insert into person(name) values (#{name})") + public Integer save(Person person); + + @Update("Update Person set name= #{name} where personId=#{personId}") + public void updatePerson(Person person); + + @Delete("Delete from Person where personId=#{personId}") + public void deletePersonById(Integer personId); + + @Select("SELECT person.personId, person.name FROM person WHERE person.personId = #{personId}") + Person getPerson(Integer personId); + + @Select("Select personId,name from Person where personId=#{personId}") + @Results(value ={ + @Result(property = "personId", column = "personId"), + @Result(property="name", column = "name"), + @Result(property = "addresses",javaType = List.class,column = "personId", + many=@Many(select = "getAddresses")) + + }) + public Person getPersonById(Integer personId); + + @Select("select addressId,streetAddress,personId from address where personId=#{personId}") + public Address getAddresses(Integer personId); + + @Select("select * from Person ") + @MapKey("personId") + Map getAllPerson(); + + @SelectProvider(type=MyBatisUtil.class,method="getPersonByName") + public Person getPersonByName(String name); + + + @Select(value= "{ CALL getPersonByProc( #{personId, mode=IN, jdbcType=INTEGER})}") + @Options(statementType = StatementType.CALLABLE) + public Person getPersonByProc(Integer personId); + +} diff --git a/mybatis/src/main/java/com/baeldung/mybatis/model/Address.java b/mybatis/src/main/java/com/baeldung/mybatis/model/Address.java new file mode 100644 index 0000000000..f32e47aef2 --- /dev/null +++ b/mybatis/src/main/java/com/baeldung/mybatis/model/Address.java @@ -0,0 +1,49 @@ +package com.baeldung.mybatis.model; + + +public class Address { + + private Integer addressId; + private String streetAddress; + private Integer personId; + + public Address() { + } + + public Integer getPersonId() { + return personId; + } + + public void setPersonId(Integer personId) { + this.personId = personId; + } + + + + public Address(String streetAddress) { + this.streetAddress =streetAddress; + } + + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } + + private Person person; + + public Address(int i, String name) { + this.streetAddress = name; + } + + public Integer getAddressId() { + return addressId; + } + + public String getStreetAddress() { + return streetAddress; + } + +} diff --git a/mybatis/src/main/java/com/baeldung/mybatis/model/Person.java b/mybatis/src/main/java/com/baeldung/mybatis/model/Person.java new file mode 100644 index 0000000000..248e3ca7a1 --- /dev/null +++ b/mybatis/src/main/java/com/baeldung/mybatis/model/Person.java @@ -0,0 +1,40 @@ +package com.baeldung.mybatis.model; + +import java.util.ArrayList; +import java.util.List; + + +public class Person { + + private Integer personId; + private String name; + private List
addresses; + + public Person() { + } + + public Person(Integer personId, String name) { + this.personId=personId; + this.name = name; + addresses = new ArrayList
(); + } + + public Person(String name) { + this.name=name; + } + + public Integer getPersonId() { + return personId; + } + + public String getName() { + return name; + } + public void addAddress(Address address){ + addresses.add(address); + } + + public List
getAddresses() { + return addresses; + } +} diff --git a/mybatis/src/main/java/com/baeldung/mybatis/utils/MyBatisUtil.java b/mybatis/src/main/java/com/baeldung/mybatis/utils/MyBatisUtil.java new file mode 100644 index 0000000000..a045e70333 --- /dev/null +++ b/mybatis/src/main/java/com/baeldung/mybatis/utils/MyBatisUtil.java @@ -0,0 +1,33 @@ +package com.baeldung.mybatis.utils; +import org.apache.ibatis.io.Resources; +import org.apache.ibatis.jdbc.SQL; +import org.apache.ibatis.session.SqlSessionFactory; +import org.apache.ibatis.session.SqlSessionFactoryBuilder; + +import java.io.IOException; +import java.io.InputStream; + +public class MyBatisUtil { + private static SqlSessionFactory sqlSessionFactory; + static { + String resource = "mybatis-config.xml"; + InputStream inputStream; + try { + inputStream = Resources.getResourceAsStream(resource); + sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); + } catch (IOException e) { + e.printStackTrace(); + } + } + public static SqlSessionFactory getSqlSessionFactory(){ + return sqlSessionFactory; + } + + public String getPersonByName(String name){ + return new SQL(){{ + SELECT("*"); + FROM("person"); + WHERE("name like #{name} || '%'"); + }}.toString(); + } +} diff --git a/mybatis/src/main/resources/mybatis-config.xml b/mybatis/src/main/resources/mybatis-config.xml new file mode 100644 index 0000000000..6987797068 --- /dev/null +++ b/mybatis/src/main/resources/mybatis-config.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mybatis/src/test/java/com/baeldung/mybatis/mapper/PersonMapperTest.java b/mybatis/src/test/java/com/baeldung/mybatis/mapper/PersonMapperTest.java new file mode 100644 index 0000000000..8724aaa545 --- /dev/null +++ b/mybatis/src/test/java/com/baeldung/mybatis/mapper/PersonMapperTest.java @@ -0,0 +1,149 @@ +package com.baeldung.mybatis.mapper; + +import com.baeldung.mybatis.model.Address; +import com.baeldung.mybatis.model.Person; +import com.baeldung.mybatis.utils.MyBatisUtil; +import org.apache.ibatis.session.SqlSession; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Map; + +import static junit.framework.TestCase.assertEquals; + +public class PersonMapperTest { + + SqlSession session; + + @Before + public void setup() throws SQLException { + + session = MyBatisUtil.getSqlSessionFactory().openSession(); + createTables(session); + + } + + private void createTables(SqlSession session) throws SQLException { + + String createPersonTable = "create table person (" + + "personId integer not null generated always as" + + " identity (start with 1, increment by 1), " + + "name varchar(30) not null, " + + "constraint primary_key_person primary key (personId))"; + + String createAddressTable = "create table address (" + + "addressId integer not null generated always as" + + " identity (start with 1, increment by 1), " + + "streetAddress varchar(300), personId integer, " + + "constraint primary_key_address primary key (addressId))"; + + String alterTable="ALTER TABLE " + + " address ADD CONSTRAINT fk_person FOREIGN KEY (personId) REFERENCES person (personId)"; + + + session.getConnection().createStatement().execute(createPersonTable); + session.getConnection().createStatement().execute(createAddressTable); + session.getConnection().createStatement().execute(alterTable); + + } + + @Test + public void whenPersonAdressSaved_ThenPersonAddressCanBeQueried(){ + Person person=new Person("Baljeet S"); + Address address = new Address("Pune"); + PersonMapper personMapper=session.getMapper(PersonMapper.class); + Integer id =personMapper.save(person); + address.setPersonId(id); + AddressMapper addressMapper=session.getMapper(AddressMapper.class); + addressMapper.saveAddress(address); + + Person returnedPerson= personMapper.getPersonById(id); + assertEquals("Baljeet S", returnedPerson.getName()); + assertEquals("Pune", returnedPerson.getAddresses().get(0).getStreetAddress()); + } + + @Test + public void whenPersonSaved_ThenPersonCanBeQueried(){ + Person person=new Person("Baljeet S"); + Address address = new Address("Pune"); + PersonMapper personMapper=session.getMapper(PersonMapper.class); + Integer id =personMapper.save(person); + address.setPersonId(id); + AddressMapper addressMapper=session.getMapper(AddressMapper.class); + addressMapper.saveAddress(address); + + Person returnedPerson= personMapper.getPerson(id); + assertEquals("Baljeet S", returnedPerson.getName()); + } + + @Test + public void whenPersonUpdated_ThenPersonIsChanged(){ + Person person=new Person("Baljeet S"); + Address address = new Address("Pune"); + PersonMapper personMapper=session.getMapper(PersonMapper.class); + Integer id =personMapper.save(person); + address.setPersonId(id); + AddressMapper addressMapper=session.getMapper(AddressMapper.class); + addressMapper.saveAddress(address); + + personMapper.updatePerson(new Person(id,"Baljeet1")); + Person returnedPerson= personMapper.getPerson(id); + assertEquals("Baljeet1", returnedPerson.getName()); + } + @Test + public void whenPersoSaved_ThenMapIsReturned(){ + Person person=new Person("Baljeet S"); + Address address = new Address("Pune"); + PersonMapper personMapper=session.getMapper(PersonMapper.class); + Integer id =personMapper.save(person); + address.setPersonId(id); + AddressMapper addressMapper=session.getMapper(AddressMapper.class); + addressMapper.saveAddress(address); + + Map returnedPerson= personMapper.getAllPerson(); + assertEquals(1, returnedPerson.size()); + } + + @Test + public void whenPersonSearched_ThenResultIsReturned(){ + Person person=new Person("Baljeet S"); + Address address = new Address("Pune"); + PersonMapper personMapper=session.getMapper(PersonMapper.class); + Integer id =personMapper.save(person); + address.setPersonId(id); + AddressMapper addressMapper=session.getMapper(AddressMapper.class); + addressMapper.saveAddress(address); + + Person returnedPerson= personMapper.getPersonByName("Baljeet S"); + assertEquals("Baljeet S", returnedPerson.getName()); + } + + @Test + public void whenAddressSearched_ThenResultIsReturned(){ + Person person=new Person("Baljeet S"); + Address address = new Address("Pune"); + PersonMapper personMapper=session.getMapper(PersonMapper.class); + Integer id =personMapper.save(person); + address.setPersonId(id); + AddressMapper addressMapper=session.getMapper(AddressMapper.class); + Integer addressId=addressMapper.saveAddress(address); + Address returnedAddress=addressMapper.getAddresses(addressId); + + assertEquals("Pune", returnedAddress.getStreetAddress()); + } + + @After + public void cleanup() throws SQLException { + session.getConnection().createStatement().execute("drop table address"); + session.getConnection().createStatement().execute("drop table person"); + + session.close(); + + } + +} diff --git a/pom.xml b/pom.xml index a6b46a0e39..a705ac7cb1 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ deltaspike dozer - ejb + feign flyway @@ -66,7 +66,7 @@ javax-servlets javaxval jaxb - jee7 + jjwt jooq @@ -153,7 +153,6 @@ spring-mvc-email spring-mvc-forms spring-mvc-java - spring-mvc-no-xml spring-mvc-tiles spring-mvc-velocity spring-mvc-web-vs-initializer @@ -215,6 +214,8 @@ rabbitmq vertx spring-data-gemfire + cucumber + mybatis @@ -233,6 +234,8 @@ org.apache.maven.plugins maven-surefire-plugin + 3 + true **/*IntegrationTest.java **/*LongRunningUnitTest.java diff --git a/querydsl/pom.xml b/querydsl/pom.xml index b0a07fb3ff..1335d0f1fd 100644 --- a/querydsl/pom.xml +++ b/querydsl/pom.xml @@ -181,6 +181,8 @@ org.apache.maven.plugins maven-surefire-plugin + 3 + true **/*IntegrationTest.java **/*LiveTest.java diff --git a/rest-testing/pom.xml b/rest-testing/pom.xml index f7f94a49a6..746752133c 100644 --- a/rest-testing/pom.xml +++ b/rest-testing/pom.xml @@ -1,164 +1,171 @@ - 4.0.0 - com.baeldung - rest-testing - 0.1-SNAPSHOT + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + com.baeldung + rest-testing + 0.1-SNAPSHOT - rest-testing + rest-testing - + - + - - com.google.guava - guava - ${guava.version} - + + com.google.guava + guava + ${guava.version} + - - commons-io - commons-io - ${commons-io.version} - + + commons-io + commons-io + ${commons-io.version} + - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + - + - - org.apache.httpcomponents - httpclient - ${httpclient.version} - - - org.apache.httpcomponents - httpcore - ${httpcore.version} - + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + org.apache.httpcomponents + httpcore + ${httpcore.version} + - + - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + - + - - org.slf4j - slf4j-api - ${org.slf4j.version} - - - ch.qos.logback - logback-classic - ${logback.version} - - - - org.slf4j - jcl-over-slf4j - ${org.slf4j.version} - runtime - - - org.slf4j - log4j-over-slf4j - ${org.slf4j.version} - + + org.slf4j + slf4j-api + ${org.slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + + org.slf4j + jcl-over-slf4j + ${org.slf4j.version} + runtime + + + org.slf4j + log4j-over-slf4j + ${org.slf4j.version} + - + - - junit - junit - ${junit.version} - test - + + junit + junit + ${junit.version} + test + - - org.hamcrest - hamcrest-core - ${org.hamcrest.version} - test - - - org.hamcrest - hamcrest-library - ${org.hamcrest.version} - test - + + org.hamcrest + hamcrest-core + ${org.hamcrest.version} + test + + + org.hamcrest + hamcrest-library + ${org.hamcrest.version} + test + - - org.mockito - mockito-core - ${mockito.version} - test - - - com.github.tomakehurst - wiremock - ${wiremock.version} - test - + + org.mockito + mockito-core + ${mockito.version} + test + + + com.github.tomakehurst + wiremock + ${wiremock.version} + test + - - info.cukes - cucumber-java - ${cucumber.version} - test - - - info.cukes - cucumber-junit - ${cucumber.version} - - + + info.cukes + cucumber-java + ${cucumber.version} + test + + + info.cukes + cucumber-junit + ${cucumber.version} + - - rest-testing - - - src/main/resources - true - - + + org.jbehave + jbehave-core + ${jbehave.version} + test + + - + + rest-testing + + + src/main/resources + true + + - - org.apache.maven.plugins - maven-compiler-plugin - ${maven-compiler-plugin.version} - - 1.8 - 1.8 - - + - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + 1.8 + 1.8 + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + **/*IntegrationTest.java **/*LiveTest.java - + - + - + @@ -177,10 +184,10 @@ **/*UnitTest.java + **/*LiveTest.java **/*IntegrationTest.java - **/*LiveTest.java @@ -195,37 +202,38 @@ - - - - 2.8.5 - - 1.7.21 - 1.1.7 + + + 2.8.5 - - 19.0 - 3.5 - 2.5 + + 1.7.21 + 1.1.7 - - 1.3 - 4.12 - 1.10.19 + + 19.0 + 3.5 + 2.5 + + + 1.3 + 4.12 + 1.10.19 2.9.0 1.2.5 2.4.1 - 4.4.5 - 4.5.2 + 4.4.5 + 4.5.2 + 4.1 - - 3.6.0 - 2.6 - 2.19.1 + + 3.6.0 + 2.6 + 2.19.1 - + \ No newline at end of file diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/AbstractStory.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/AbstractStory.java new file mode 100644 index 0000000000..ce3c98d07e --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/AbstractStory.java @@ -0,0 +1,45 @@ +package com.baeldung.rest.jbehave; + +import org.jbehave.core.configuration.Configuration; +import org.jbehave.core.configuration.MostUsefulConfiguration; +import org.jbehave.core.io.LoadFromClasspath; +import org.jbehave.core.junit.JUnitStories; +import org.jbehave.core.reporters.StoryReporterBuilder; +import org.jbehave.core.steps.InjectableStepsFactory; +import org.jbehave.core.steps.InstanceStepsFactory; + +import java.util.Arrays; +import java.util.List; + +import static org.jbehave.core.io.CodeLocations.codeLocationFromClass; +import static org.jbehave.core.reporters.Format.CONSOLE; + +/** + * @author aiet + */ +public abstract class AbstractStory extends JUnitStories { + + abstract String storyName(); + + @Override + public Configuration configuration() { + return new MostUsefulConfiguration() + .useStoryLoader(new LoadFromClasspath(this.getClass())) + .useStoryReporterBuilder(new StoryReporterBuilder() + .withCodeLocation(codeLocationFromClass(this.getClass())) + .withFormats(CONSOLE)); + } + + abstract Object stepInstance(); + + @Override + public InjectableStepsFactory stepsFactory() { + return new InstanceStepsFactory(configuration(), stepInstance()); + } + + @Override + protected List storyPaths() { + return Arrays.asList(storyName()); + } + +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserNotFoundSteps.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserNotFoundSteps.java new file mode 100644 index 0000000000..54d3b0b155 --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserNotFoundSteps.java @@ -0,0 +1,59 @@ +package com.baeldung.rest.jbehave; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.HttpClientBuilder; +import org.jbehave.core.annotations.Given; +import org.jbehave.core.annotations.Then; +import org.jbehave.core.annotations.When; + +import java.io.IOException; + +import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic; +import static org.apache.http.HttpStatus.SC_NOT_FOUND; +import static org.junit.Assert.assertTrue; + +public class GithubUserNotFoundSteps { + + private String api; + private String nonExistentUser; + private int githubResponseCode; + + @Given("github user profile api") + public void givenGithubUserProfileApi() { + api = "https://api.github.com/users/%s"; + } + + @Given("a random non-existent username") + public void givenANonexistentUsername() { + nonExistentUser = randomAlphabetic(8); + } + + @When("I look for the random user via the api") + public void whenILookForTheUserViaTheApi() throws IOException { + githubResponseCode = getGithubUserProfile(api, nonExistentUser) + .getStatusLine() + .getStatusCode(); + } + + @When("I look for $user via the api") + public void whenILookForSomeNonExistentUserViaTheApi(String user) throws IOException { + githubResponseCode = getGithubUserProfile(api, user) + .getStatusLine() + .getStatusCode(); + } + + static HttpResponse getGithubUserProfile(String api, String username) throws IOException { + HttpUriRequest request = new HttpGet(String.format(api, username)); + return HttpClientBuilder + .create() + .build() + .execute(request); + } + + @Then("github respond: 404 not found") + public void thenGithubRespond404NotFound() { + assertTrue(SC_NOT_FOUND == githubResponseCode); + } +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserNotFoundStoryLiveTest.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserNotFoundStoryLiveTest.java new file mode 100644 index 0000000000..f681fb085a --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserNotFoundStoryLiveTest.java @@ -0,0 +1,18 @@ +package com.baeldung.rest.jbehave; + +/** + * @author aiet + */ +public class GithubUserNotFoundStoryLiveTest extends AbstractStory { + + @Override + String storyName() { + return "github_user_not_found.story"; + } + + @Override + Object stepInstance() { + return new GithubUserNotFoundSteps(); + } + +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponseMediaTypeSteps.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponseMediaTypeSteps.java new file mode 100644 index 0000000000..a1a9aceee5 --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponseMediaTypeSteps.java @@ -0,0 +1,40 @@ +package com.baeldung.rest.jbehave; + +import org.apache.http.entity.ContentType; +import org.jbehave.core.annotations.Given; +import org.jbehave.core.annotations.Then; +import org.jbehave.core.annotations.When; + +import java.io.IOException; + +import static com.baeldung.rest.jbehave.GithubUserNotFoundSteps.getGithubUserProfile; +import static org.junit.Assert.assertEquals; + +public class GithubUserResponseMediaTypeSteps { + + private String api; + private String validUser; + private String mediaType; + + @Given("github user profile api") + public void givenGithubUserProfileApi() { + api = "https://api.github.com/users/%s"; + } + + @Given("a valid username") + public void givenAValidUsername() { + validUser = "eugenp"; + } + + @When("I look for the user via the api") + public void whenILookForTheUserViaTheApi() throws IOException { + mediaType = ContentType + .getOrDefault(getGithubUserProfile(api, validUser).getEntity()) + .getMimeType(); + } + + @Then("github respond data of type json") + public void thenGithubRespondDataOfTypeJson() { + assertEquals("application/json", mediaType); + } +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponseMediaTypeStoryLiveTest.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponseMediaTypeStoryLiveTest.java new file mode 100644 index 0000000000..c14f7aad75 --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponseMediaTypeStoryLiveTest.java @@ -0,0 +1,18 @@ +package com.baeldung.rest.jbehave; + +/** + * @author aiet + */ +public class GithubUserResponseMediaTypeStoryLiveTest extends AbstractStory { + + @Override + String storyName() { + return "github_user_response_mediatype.story"; + } + + @Override + Object stepInstance() { + return new GithubUserResponseMediaTypeSteps(); + } + +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponsePayloadSteps.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponsePayloadSteps.java new file mode 100644 index 0000000000..d9401a5d00 --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponsePayloadSteps.java @@ -0,0 +1,40 @@ +package com.baeldung.rest.jbehave; + +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.HttpClientBuilder; +import org.baeldung.rest.GitHubUser; +import org.baeldung.rest.RetrieveUtil; +import org.hamcrest.Matchers; +import org.jbehave.core.annotations.Given; +import org.jbehave.core.annotations.Then; +import org.jbehave.core.annotations.When; + +import java.io.IOException; + +import static com.baeldung.rest.jbehave.GithubUserNotFoundSteps.getGithubUserProfile; +import static org.hamcrest.MatcherAssert.assertThat; + +public class GithubUserResponsePayloadSteps { + + private String api; + private GitHubUser resource; + + @Given("github user profile api") + public void givenGithubUserProfileApi() { + api = "https://api.github.com/users/%s"; + } + + @When("I look for $user via the api") + public void whenILookForEugenpViaTheApi(String user) throws IOException { + HttpResponse httpResponse = getGithubUserProfile(api, user); + resource = RetrieveUtil.retrieveResourceFromResponse(httpResponse, GitHubUser.class); + } + + @Then("github's response contains a 'login' payload same as $username") + public void thenGithubsResponseContainsAloginPayloadSameAsEugenp(String username) { + assertThat(username, Matchers.is(resource.getLogin())); + } + +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponsePayloadStoryLiveTest.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponsePayloadStoryLiveTest.java new file mode 100644 index 0000000000..cd7974869a --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/GithubUserResponsePayloadStoryLiveTest.java @@ -0,0 +1,18 @@ +package com.baeldung.rest.jbehave; + +/** + * @author aiet + */ +public class GithubUserResponsePayloadStoryLiveTest extends AbstractStory { + + @Override + String storyName() { + return "github_user_response_payload.story"; + } + + @Override + Object stepInstance() { + return new GithubUserResponsePayloadSteps(); + } + +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/IncreaseSteps.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/IncreaseSteps.java new file mode 100644 index 0000000000..3bc6fb2aa2 --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/IncreaseSteps.java @@ -0,0 +1,34 @@ +package com.baeldung.rest.jbehave; + +import org.jbehave.core.annotations.Given; +import org.jbehave.core.annotations.Then; +import org.jbehave.core.annotations.When; + +import java.util.Random; + +import static org.junit.Assert.assertTrue; + +public class IncreaseSteps { + private int counter; + private int previousValue; + + @Given("a counter") + public void aCounter() { + } + + @Given("the counter has any integral value") + public void counterHasAnyIntegralValue() { + counter = new Random().nextInt(); + previousValue = counter; + } + + @When("the user increases the counter") + public void increasesTheCounter() { + counter++; + } + + @Then("the value of the counter must be 1 greater than previous value") + public void theValueOfTheCounterMustBe1Greater() { + assertTrue(1 == counter - previousValue); + } +} diff --git a/rest-testing/src/test/java/com/baeldung/rest/jbehave/IncreaseStoryLiveTest.java b/rest-testing/src/test/java/com/baeldung/rest/jbehave/IncreaseStoryLiveTest.java new file mode 100644 index 0000000000..9033dbfbdc --- /dev/null +++ b/rest-testing/src/test/java/com/baeldung/rest/jbehave/IncreaseStoryLiveTest.java @@ -0,0 +1,38 @@ +package com.baeldung.rest.jbehave; + +import org.jbehave.core.configuration.Configuration; +import org.jbehave.core.configuration.MostUsefulConfiguration; +import org.jbehave.core.io.LoadFromClasspath; +import org.jbehave.core.junit.JUnitStories; +import org.jbehave.core.reporters.StoryReporterBuilder; +import org.jbehave.core.steps.InjectableStepsFactory; +import org.jbehave.core.steps.InstanceStepsFactory; + +import java.util.Arrays; +import java.util.List; + +import static org.jbehave.core.io.CodeLocations.codeLocationFromClass; +import static org.jbehave.core.reporters.Format.CONSOLE; + +public class IncreaseStoryLiveTest extends JUnitStories { + + @Override + public Configuration configuration() { + return new MostUsefulConfiguration() + .useStoryLoader(new LoadFromClasspath(this.getClass())) + .useStoryReporterBuilder(new StoryReporterBuilder() + .withCodeLocation(codeLocationFromClass(this.getClass())) + .withFormats(CONSOLE)); + } + + @Override + public InjectableStepsFactory stepsFactory() { + return new InstanceStepsFactory(configuration(), new IncreaseSteps()); + } + + @Override + protected List storyPaths() { + return Arrays.asList("increase.story"); + } + +} diff --git a/rest-testing/src/test/resources/github_user_not_found.story b/rest-testing/src/test/resources/github_user_not_found.story new file mode 100644 index 0000000000..1ab6920eee --- /dev/null +++ b/rest-testing/src/test/resources/github_user_not_found.story @@ -0,0 +1,19 @@ +Meta: + +Narrative: +As a user +I want to look up a non-existent user's profile on github +So that I can be sure that the username can not be found on github + +Scenario: when a user checks a non-existent user on github, github would respond 'not found' + +Given github user profile api +And a random non-existent username +When I look for the random user via the api +Then github respond: 404 not found + +When I look for eugenp1 via the api +Then github respond: 404 not found + +When I look for eugenp2 via the api +Then github respond: 404 not found diff --git a/rest-testing/src/test/resources/github_user_response_mediatype.story b/rest-testing/src/test/resources/github_user_response_mediatype.story new file mode 100644 index 0000000000..7c4a0b9e2d --- /dev/null +++ b/rest-testing/src/test/resources/github_user_response_mediatype.story @@ -0,0 +1,13 @@ +Meta: + +Narrative: +As a user +I want to look up a valid user's profile on github +So that I can know that github responds data of type json + +Scenario: when a user checks a valid user's profile on github, github would respond json data + +Given github user profile api +And a valid username +When I look for the user via the api +Then github respond data of type json \ No newline at end of file diff --git a/rest-testing/src/test/resources/github_user_response_payload.story b/rest-testing/src/test/resources/github_user_response_payload.story new file mode 100644 index 0000000000..788b43eba6 --- /dev/null +++ b/rest-testing/src/test/resources/github_user_response_payload.story @@ -0,0 +1,12 @@ +Meta: + +Narrative: +As a user +I want to look up a valid user's profile on github +So that I can know the login payload should be the same as username + +Scenario: when a user checks a valid user's profile on github, github's response json should include a login payload with the same username + +Given github user profile api +When I look for eugenp via the api +Then github's response contains a 'login' payload same as eugenp diff --git a/rest-testing/src/test/resources/increase.story b/rest-testing/src/test/resources/increase.story new file mode 100644 index 0000000000..fef91298bc --- /dev/null +++ b/rest-testing/src/test/resources/increase.story @@ -0,0 +1,15 @@ +JBehave Story - An increase test + +Meta: + +Narrative: +As a user +I want to increase a counter +So that I can have the counter's value increase by 1 + +Scenario: when a user increases a counter, its value is increased by 1 + +Given a counter +And the counter has any integral value +When the user increases the counter +Then the value of the counter must be 1 greater than previous value \ No newline at end of file diff --git a/resteasy/bin/pom.xml b/resteasy/bin/pom.xml index f0bd8298f5..1116c0f01a 100644 --- a/resteasy/bin/pom.xml +++ b/resteasy/bin/pom.xml @@ -32,6 +32,8 @@ maven-surefire-plugin ${maven-surefire-plugin.version} + 3 + true **/*IntegrationTest.java **/*LiveTest.java diff --git a/resteasy/src/main/java/com/baeldung/filter/CorsFilter.java b/resteasy/src/main/java/com/baeldung/filter/CorsFilter.java deleted file mode 100644 index 266707fb9f..0000000000 --- a/resteasy/src/main/java/com/baeldung/filter/CorsFilter.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.filter; - -import java.io.IOException; - -import javax.ws.rs.container.ContainerRequestContext; -import javax.ws.rs.container.ContainerResponseContext; -import javax.ws.rs.container.ContainerResponseFilter; -import javax.ws.rs.ext.Provider; - -@Provider -public class CorsFilter implements ContainerResponseFilter { - - @Override - public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) - throws IOException { - responseContext.getHeaders().add("Access-Control-Allow-Origin", "*"); - responseContext.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization"); - responseContext.getHeaders().add("Access-Control-Allow-Credentials", "true"); - responseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD"); - } - -} diff --git a/rxjava/pom.xml b/rxjava/pom.xml index 4172187b03..3313713b9b 100644 --- a/rxjava/pom.xml +++ b/rxjava/pom.xml @@ -21,6 +21,8 @@ org.apache.maven.plugins maven-surefire-plugin + 3 + true **/*IntegrationTest.java **/*LongRunningUnitTest.java diff --git a/spring-5/pom.xml b/spring-5/pom.xml index f116ed73c0..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 + @@ -80,6 +108,8 @@ org.apache.maven.plugins maven-surefire-plugin + 3 + true **/*IntegrationTest.java **/*LiveTest.java @@ -90,7 +120,7 @@ org.apache.maven.plugins maven-surefire-plugin - 2.19.1 + ${maven-surefire-plugin.version} methods true @@ -141,6 +171,10 @@ UTF-8 UTF-8 1.8 + 1.0.0-M3 + 5.0.0-M3 + 4.3.7.RELEASE + 2.19.1 diff --git a/spring-5/src/main/java/com/baeldung/jupiter/MethodParameterFactory.java b/spring-5/src/main/java/com/baeldung/jupiter/MethodParameterFactory.java new file mode 100644 index 0000000000..85bd505d11 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/jupiter/MethodParameterFactory.java @@ -0,0 +1,46 @@ +package com.baeldung.jupiter; + +import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.SynthesizingMethodParameter; +import org.springframework.util.Assert; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; + +abstract class MethodParameterFactory { + + private MethodParameterFactory() { + } + + public static MethodParameter createMethodParameter(Parameter parameter) { + Assert.notNull(parameter, "Parameter must not be null"); + Executable executable = parameter.getDeclaringExecutable(); + if (executable instanceof Method) { + return new MethodParameter((Method) executable, getIndex(parameter)); + } + return new MethodParameter((Constructor) executable, getIndex(parameter)); + } + + public static SynthesizingMethodParameter createSynthesizingMethodParameter(Parameter parameter) { + Assert.notNull(parameter, "Parameter must not be null"); + Executable executable = parameter.getDeclaringExecutable(); + if (executable instanceof Method) { + return new SynthesizingMethodParameter((Method) executable, getIndex(parameter)); + } + throw new UnsupportedOperationException("Cannot create a SynthesizingMethodParameter for a constructor parameter: " + parameter); + } + + private static int getIndex(Parameter parameter) { + Assert.notNull(parameter, "Parameter must not be null"); + Executable executable = parameter.getDeclaringExecutable(); + Parameter[] parameters = executable.getParameters(); + for (int i = 0; i < parameters.length; i++) { + if (parameters[i] == parameter) { + return i; + } + } + throw new IllegalStateException(String.format("Failed to resolve index of parameter [%s] in executable [%s]", parameter, executable.toGenericString())); + } +} diff --git a/spring-5/src/main/java/com/baeldung/jupiter/ParameterAutowireUtils.java b/spring-5/src/main/java/com/baeldung/jupiter/ParameterAutowireUtils.java new file mode 100644 index 0000000000..068c6af381 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/jupiter/ParameterAutowireUtils.java @@ -0,0 +1,46 @@ +package com.baeldung.jupiter; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.config.DependencyDescriptor; +import org.springframework.context.ApplicationContext; +import org.springframework.core.MethodParameter; +import org.springframework.core.annotation.AnnotatedElementUtils; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.util.Optional; + +import static org.springframework.core.annotation.AnnotatedElementUtils.hasAnnotation; + +abstract class ParameterAutowireUtils { + + private ParameterAutowireUtils() { + } + + public static boolean isAutowirable(Parameter parameter) { + return ApplicationContext.class.isAssignableFrom(parameter.getType()) || hasAnnotation(parameter, Autowired.class) || hasAnnotation(parameter, Qualifier.class) || hasAnnotation(parameter, Value.class); + } + + public static Object resolveDependency(Parameter parameter, Class containingClass, ApplicationContext applicationContext) { + + boolean required = findMergedAnnotation(parameter, Autowired.class) + .map(Autowired::required) + .orElse(true); + MethodParameter methodParameter = (parameter.getDeclaringExecutable() instanceof Method ? MethodParameterFactory.createSynthesizingMethodParameter(parameter) : MethodParameterFactory.createMethodParameter(parameter)); + DependencyDescriptor descriptor = new DependencyDescriptor(methodParameter, required); + descriptor.setContainingClass(containingClass); + + return applicationContext + .getAutowireCapableBeanFactory() + .resolveDependency(descriptor, null); + } + + private static Optional findMergedAnnotation(AnnotatedElement element, Class annotationType) { + + return Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(element, annotationType)); + } +} diff --git a/spring-5/src/main/java/com/baeldung/jupiter/SpringExtension.java b/spring-5/src/main/java/com/baeldung/jupiter/SpringExtension.java new file mode 100644 index 0000000000..08fa0c4768 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/jupiter/SpringExtension.java @@ -0,0 +1,94 @@ +package com.baeldung.jupiter; + +import org.junit.jupiter.api.extension.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.test.context.TestContextManager; +import org.springframework.util.Assert; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Executable; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; + +public class SpringExtension implements BeforeAllCallback, AfterAllCallback, TestInstancePostProcessor, BeforeEachCallback, AfterEachCallback, ParameterResolver { + + private static final ExtensionContext.Namespace namespace = ExtensionContext.Namespace.create(SpringExtension.class); + + @Override + public void beforeAll(ContainerExtensionContext context) throws Exception { + getTestContextManager(context).beforeTestClass(); + } + + @Override + public void afterAll(ContainerExtensionContext context) throws Exception { + try { + getTestContextManager(context).afterTestClass(); + } finally { + context + .getStore(namespace) + .remove(context + .getTestClass() + .get()); + } + } + + @Override + public void postProcessTestInstance(Object testInstance, ExtensionContext context) throws Exception { + getTestContextManager(context).prepareTestInstance(testInstance); + } + + @Override + public void beforeEach(TestExtensionContext context) throws Exception { + Object testInstance = context.getTestInstance(); + Method testMethod = context + .getTestMethod() + .get(); + getTestContextManager(context).beforeTestMethod(testInstance, testMethod); + } + + @Override + public void afterEach(TestExtensionContext context) throws Exception { + Object testInstance = context.getTestInstance(); + Method testMethod = context + .getTestMethod() + .get(); + Throwable testException = context + .getTestException() + .orElse(null); + getTestContextManager(context).afterTestMethod(testInstance, testMethod, testException); + } + + @Override + public boolean supports(ParameterContext parameterContext, ExtensionContext extensionContext) { + Parameter parameter = parameterContext.getParameter(); + Executable executable = parameter.getDeclaringExecutable(); + return (executable instanceof Constructor && AnnotatedElementUtils.hasAnnotation(executable, Autowired.class)) || ParameterAutowireUtils.isAutowirable(parameter); + } + + @Override + public Object resolve(ParameterContext parameterContext, ExtensionContext extensionContext) { + Parameter parameter = parameterContext.getParameter(); + Class testClass = extensionContext + .getTestClass() + .get(); + ApplicationContext applicationContext = getApplicationContext(extensionContext); + return ParameterAutowireUtils.resolveDependency(parameter, testClass, applicationContext); + } + + private ApplicationContext getApplicationContext(ExtensionContext context) { + return getTestContextManager(context) + .getTestContext() + .getApplicationContext(); + } + + private TestContextManager getTestContextManager(ExtensionContext context) { + Assert.notNull(context, "ExtensionContext must not be null"); + Class testClass = context + .getTestClass() + .get(); + ExtensionContext.Store store = context.getStore(namespace); + return store.getOrComputeIfAbsent(testClass, TestContextManager::new, TestContextManager.class); + } +} diff --git a/spring-5/src/main/java/com/baeldung/jupiter/SpringJUnit5Config.java b/spring-5/src/main/java/com/baeldung/jupiter/SpringJUnit5Config.java new file mode 100644 index 0000000000..e8b9cc500f --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/jupiter/SpringJUnit5Config.java @@ -0,0 +1,40 @@ +package com.baeldung.jupiter; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.annotation.AliasFor; +import org.springframework.test.context.ContextConfiguration; + +import java.lang.annotation.*; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration +@Documented +@Inherited +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface SpringJUnit5Config { + + @AliasFor(annotation = ContextConfiguration.class, attribute = "classes") + Class[] value() default {}; + + @AliasFor(annotation = ContextConfiguration.class) + Class[] classes() default {}; + + @AliasFor(annotation = ContextConfiguration.class) + String[] locations() default {}; + + @AliasFor(annotation = ContextConfiguration.class) + Class>[] initializers() default {}; + + @AliasFor(annotation = ContextConfiguration.class) + boolean inheritLocations() default true; + + @AliasFor(annotation = ContextConfiguration.class) + boolean inheritInitializers() default true; + + @AliasFor(annotation = ContextConfiguration.class) + String name() default ""; +} diff --git a/spring-5/src/main/java/com/baeldung/jupiter/TestConfig.java b/spring-5/src/main/java/com/baeldung/jupiter/TestConfig.java new file mode 100644 index 0000000000..a29f77c5df --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/jupiter/TestConfig.java @@ -0,0 +1,20 @@ +package com.baeldung.jupiter; + +import com.baeldung.web.reactive.Task; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; + +@Configuration +public class TestConfig { + + @Bean + static PropertySourcesPlaceholderConfigurer placeholderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + @Bean + Task taskName() { + return new Task("taskName", 1); + } +} diff --git a/spring-5/src/main/java/com/baeldung/web/reactive/Task.java b/spring-5/src/main/java/com/baeldung/web/reactive/Task.java new file mode 100644 index 0000000000..84193d9354 --- /dev/null +++ b/spring-5/src/main/java/com/baeldung/web/reactive/Task.java @@ -0,0 +1,31 @@ +package com.baeldung.web.reactive; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Task { + + private final String name; + + private final int id; + + public Task(@JsonProperty("name") String name, @JsonProperty("id") int id) { + this.name = name; + this.id = id; + } + + public String getName() { + return this.name; + } + + public int getId() { + return this.id; + } + + @Override + public String toString() { + return "Task{" + + "name='" + name + '\'' + + ", id=" + id + + '}'; + } +} diff --git a/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java b/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java index bf28ed1e7d..dda25f46f7 100644 --- a/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java +++ b/spring-5/src/test/java/com/baeldung/functional/FunctionalWebApplicationIntegrationTest.java @@ -7,7 +7,7 @@ import org.springframework.boot.web.server.WebServer; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.http.MediaType; -import org.springframework.test.web.reactive.server.WebTestClient; +//import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.reactive.function.BodyInserters; @@ -15,140 +15,141 @@ import org.springframework.web.reactive.function.BodyInserters; import static org.springframework.web.reactive.function.BodyInserters.fromObject; import static org.springframework.web.reactive.function.BodyInserters.fromResource; +// TODO The class does not compile, WebTestClient cannot be resolved. Missing dependency? public class FunctionalWebApplicationIntegrationTest { - private static WebTestClient client; - private static WebServer server; - - @BeforeClass - public static void setup() throws Exception { - server = new FunctionalWebApplication().start(); - client = WebTestClient - .bindToServer() - .baseUrl("http://localhost:" + server.getPort()) - .build(); - } - - @AfterClass - public static void destroy() { - server.stop(); - } - - @Test - public void givenRouter_whenGetTest_thenGotHelloWorld() throws Exception { - client - .get() - .uri("/test") - .exchange() - .expectStatus() - .isOk() - .expectBody(String.class) - .value() - .isEqualTo("helloworld"); - } - - @Test - public void givenIndexFilter_whenRequestRoot_thenRewrittenToTest() throws Exception { - client - .get() - .uri("/") - .exchange() - .expectStatus() - .isOk() - .expectBody(String.class) - .value() - .isEqualTo("helloworld"); - } - - @Test - public void givenLoginForm_whenPostValidToken_thenSuccess() throws Exception { - MultiValueMap formData = new LinkedMultiValueMap<>(1); - formData.add("user", "baeldung"); - formData.add("token", "you_know_what_to_do"); - - client - .post() - .uri("/login") - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .exchange(BodyInserters.fromFormData(formData)) - .expectStatus() - .isOk() - .expectBody(String.class) - .value() - .isEqualTo("welcome back!"); - } - - @Test - public void givenLoginForm_whenRequestWithInvalidToken_thenFail() throws Exception { - MultiValueMap formData = new LinkedMultiValueMap<>(2); - formData.add("user", "baeldung"); - formData.add("token", "try_again"); - - client - .post() - .uri("/login") - .contentType(MediaType.APPLICATION_FORM_URLENCODED) - .exchange(BodyInserters.fromFormData(formData)) - .expectStatus() - .isBadRequest(); - } - - @Test - public void givenUploadForm_whenRequestWithMultipartData_thenSuccess() throws Exception { - Resource resource = new ClassPathResource("/baeldung-weekly.png"); - client - .post() - .uri("/upload") - .contentType(MediaType.MULTIPART_FORM_DATA) - .exchange(fromResource(resource)) - .expectStatus() - .isOk() - .expectBody(String.class) - .value() - .isEqualTo(String.valueOf(resource.contentLength())); - } - - @Test - public void givenActors_whenAddActor_thenAdded() throws Exception { - client - .get() - .uri("/actor") - .exchange() - .expectStatus() - .isOk() - .expectBody(Actor.class) - .list() - .hasSize(2); - - client - .post() - .uri("/actor") - .exchange(fromObject(new Actor("Clint", "Eastwood"))) - .expectStatus() - .isOk(); - - client - .get() - .uri("/actor") - .exchange() - .expectStatus() - .isOk() - .expectBody(Actor.class) - .list() - .hasSize(3); - } - - @Test - public void givenResources_whenAccess_thenGot() throws Exception { - client - .get() - .uri("/files/hello.txt") - .exchange() - .expectStatus() - .isOk() - .expectBody(String.class) - .value() - .isEqualTo("hello"); - } +// private static WebTestClient client; +// private static WebServer server; +// +// @BeforeClass +// public static void setup() throws Exception { +// server = new FunctionalWebApplication().start(); +// client = WebTestClient +// .bindToServer() +// .baseUrl("http://localhost:" + server.getPort()) +// .build(); +// } +// +// @AfterClass +// public static void destroy() { +// server.stop(); +// } +// +// @Test +// public void givenRouter_whenGetTest_thenGotHelloWorld() throws Exception { +// client +// .get() +// .uri("/test") +// .exchange() +// .expectStatus() +// .isOk() +// .expectBody(String.class) +// .value() +// .isEqualTo("helloworld"); +// } +// +// @Test +// public void givenIndexFilter_whenRequestRoot_thenRewrittenToTest() throws Exception { +// client +// .get() +// .uri("/") +// .exchange() +// .expectStatus() +// .isOk() +// .expectBody(String.class) +// .value() +// .isEqualTo("helloworld"); +// } +// +// @Test +// public void givenLoginForm_whenPostValidToken_thenSuccess() throws Exception { +// MultiValueMap formData = new LinkedMultiValueMap<>(1); +// formData.add("user", "baeldung"); +// formData.add("token", "you_know_what_to_do"); +// +// client +// .post() +// .uri("/login") +// .contentType(MediaType.APPLICATION_FORM_URLENCODED) +// .exchange(BodyInserters.fromFormData(formData)) +// .expectStatus() +// .isOk() +// .expectBody(String.class) +// .value() +// .isEqualTo("welcome back!"); +// } +// +// @Test +// public void givenLoginForm_whenRequestWithInvalidToken_thenFail() throws Exception { +// MultiValueMap formData = new LinkedMultiValueMap<>(2); +// formData.add("user", "baeldung"); +// formData.add("token", "try_again"); +// +// client +// .post() +// .uri("/login") +// .contentType(MediaType.APPLICATION_FORM_URLENCODED) +// .exchange(BodyInserters.fromFormData(formData)) +// .expectStatus() +// .isBadRequest(); +// } +// +// @Test +// public void givenUploadForm_whenRequestWithMultipartData_thenSuccess() throws Exception { +// Resource resource = new ClassPathResource("/baeldung-weekly.png"); +// client +// .post() +// .uri("/upload") +// .contentType(MediaType.MULTIPART_FORM_DATA) +// .exchange(fromResource(resource)) +// .expectStatus() +// .isOk() +// .expectBody(String.class) +// .value() +// .isEqualTo(String.valueOf(resource.contentLength())); +// } +// +// @Test +// public void givenActors_whenAddActor_thenAdded() throws Exception { +// client +// .get() +// .uri("/actor") +// .exchange() +// .expectStatus() +// .isOk() +// .expectBody(Actor.class) +// .list() +// .hasSize(2); +// +// client +// .post() +// .uri("/actor") +// .exchange(fromObject(new Actor("Clint", "Eastwood"))) +// .expectStatus() +// .isOk(); +// +// client +// .get() +// .uri("/actor") +// .exchange() +// .expectStatus() +// .isOk() +// .expectBody(Actor.class) +// .list() +// .hasSize(3); +// } +// +// @Test +// public void givenResources_whenAccess_thenGot() throws Exception { +// client +// .get() +// .uri("/files/hello.txt") +// .exchange() +// .expectStatus() +// .isOk() +// .expectBody(String.class) +// .value() +// .isEqualTo("hello"); +// } } diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ComposedAnnotationTests.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ComposedAnnotationTests.java new file mode 100644 index 0000000000..d15857e0a5 --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ComposedAnnotationTests.java @@ -0,0 +1,38 @@ +package com.baeldung.jupiter; + +import com.baeldung.web.reactive.Task; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@SpringJUnit5Config(TestConfig.class) +@DisplayName("@SpringJUnit5Config Tests") +class Spring5JUnit5ComposedAnnotationTests { + + @Autowired + Task task; + + @Autowired + List tasks; + + @Test + @DisplayName("ApplicationContext injected into method") + void givenAMethodName_whenInjecting_thenApplicationContextInjectedIntoMethod(ApplicationContext applicationContext) { + assertNotNull(applicationContext, "ApplicationContext should have been injected into method by Spring"); + assertEquals(this.task, applicationContext.getBean("taskName", Task.class)); + } + + @Test + @DisplayName("Spring @Beans injected into fields") + void givenAnObject_whenInjecting_thenSpringBeansInjected() { + assertNotNull(task, "Task should have been @Autowired by Spring"); + assertEquals("taskName", task.getName(), "Task's name"); + assertEquals(1, tasks.size(), "Number of Tasks in context"); + } +} diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ParallelTest.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ParallelTest.java new file mode 100644 index 0000000000..a060b78c93 --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5ParallelTest.java @@ -0,0 +1,29 @@ +package com.baeldung.jupiter; + +import com.baeldung.IntegrationTestExample1; +import com.baeldung.IntegrationTestExample2; +import org.junit.experimental.ParallelComputer; +import org.junit.jupiter.api.Test; +import org.junit.runner.Computer; +import org.junit.runner.JUnitCore; + +public class Spring5JUnit5ParallelTest { + + @Test + public void givenTwoTestClasses_whenJUnitRunParallel_thenTheTestsExecutingParallel() { + final Class[] classes = { + IntegrationTestExample1.class, IntegrationTestExample2.class + }; + + JUnitCore.runClasses(new ParallelComputer(true, true), classes); + } + + @Test + public void givenTwoTestClasses_whenJUnitRunParallel_thenTheTestsExecutingLinear() { + final Class[] classes = { + IntegrationTestExample1.class, IntegrationTestExample2.class + }; + + JUnitCore.runClasses(new Computer(), classes); + } +} \ No newline at end of file diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5Tests.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5Tests.java new file mode 100644 index 0000000000..c4c3148b1e --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5JUnit5Tests.java @@ -0,0 +1,27 @@ +package com.baeldung.jupiter; + +import com.baeldung.web.reactive.Task; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.ContextConfiguration; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.Test; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = TestConfig.class) +class Spring5JUnit5Tests { + + @Autowired + Task task; + + @Test + void givenAMethodName_whenInjecting_thenApplicationContextInjectedIntoMetho(ApplicationContext applicationContext) { + assertNotNull(applicationContext, "ApplicationContext should have been injected by Spring"); + assertEquals(this.task, applicationContext.getBean("taskName", Task.class)); + } +} diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5Java8NewFeaturesTest.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5Java8NewFeaturesTest.java new file mode 100644 index 0000000000..36adf1f7ff --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5Java8NewFeaturesTest.java @@ -0,0 +1,33 @@ +package com.baeldung.jupiter; + +import org.junit.jupiter.api.Test; +import java.util.function.Supplier; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class Spring5Java8NewFeaturesTest { + + @FunctionalInterface + public interface FunctionalInterfaceExample { + Result reverseString(Input input); + } + + public class StringUtils{ + public FunctionalInterfaceExample + functionLambdaString = s -> { + return Pattern.compile(" +").splitAsStream(s) + .map(word->new StringBuilder(word).reverse()) + .collect(Collectors.joining(" ")); + }; + } + + @Test + void givenStringUtil_whenSupplierCall_thenFunctionalInterfaceReverseString() + throws Exception { + Supplier stringUtilsSupplier = StringUtils::new; + + assertEquals(stringUtilsSupplier.get().functionLambdaString + .reverseString("hello"), "olleh"); + } +} diff --git a/spring-5/src/test/java/com/baeldung/jupiter/Spring5ReactiveServerClientTest.java b/spring-5/src/test/java/com/baeldung/jupiter/Spring5ReactiveServerClientTest.java new file mode 100644 index 0000000000..2252c255ee --- /dev/null +++ b/spring-5/src/test/java/com/baeldung/jupiter/Spring5ReactiveServerClientTest.java @@ -0,0 +1,110 @@ +package com.baeldung.jupiter; + +import com.baeldung.web.reactive.Task; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.http.HttpMethod; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.http.server.reactive.HttpHandler; +import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.ClientRequest; +import org.springframework.web.reactive.function.client.ExchangeFunction; +import org.springframework.web.reactive.function.client.ExchangeFunctions; +import org.springframework.web.reactive.function.client.WebClient; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.ipc.netty.NettyContext; +import reactor.ipc.netty.http.server.HttpServer; + +import java.net.URI; +import java.time.Duration; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.web.reactive.function.server.RequestPredicates.GET; +import static org.springframework.web.reactive.function.server.RequestPredicates.POST; + +public class Spring5ReactiveServerClientTest { + + private static NettyContext nettyContext; + + @BeforeAll + public static void setUp() throws Exception { + HttpServer server = HttpServer.create("localhost", 8080); + RouterFunction route = RouterFunctions + .route(POST("/task/process"), request -> ServerResponse + .ok() + .body(request + .bodyToFlux(Task.class) + .map(ll -> new Task("TaskName", 1)), Task.class)) + .and(RouterFunctions.route(GET("/task"), request -> ServerResponse + .ok() + .body(Mono.just("server is alive"), String.class))); + HttpHandler httpHandler = RouterFunctions.toHttpHandler(route); + ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler); + nettyContext = server + .newHandler(adapter) + .block(); + } + + @AfterAll + public static void shutDown() { + nettyContext.dispose(); + } + + @Test + public void givenCheckTask_whenServerHandle_thenServerResponseALiveString() throws Exception { + WebClient client = WebClient.create("http://localhost:8080"); + Mono result = client + .get() + .uri("/task") + .exchange() + .then(response -> response.bodyToMono(String.class)); + + assertThat(result.block()).isInstanceOf(String.class); + } + + @Test + public void givenThreeTasks_whenServerHandleTheTasks_thenServerResponseATask() throws Exception { + URI uri = URI.create("http://localhost:8080/task/process"); + ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector()); + ClientRequest request = ClientRequest + .method(HttpMethod.POST, uri) + .body(BodyInserters.fromPublisher(getLatLngs(), Task.class)) + .build(); + + Flux taskResponse = exchange + .exchange(request) + .flatMap(response -> response.bodyToFlux(Task.class)); + + assertThat(taskResponse.blockFirst()).isInstanceOf(Task.class); + } + + @Test + public void givenCheckTask_whenServerHandle_thenOragicServerResponseALiveString() throws Exception { + URI uri = URI.create("http://localhost:8080/task"); + ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector()); + ClientRequest request = ClientRequest + .method(HttpMethod.GET, uri) + .body(BodyInserters.fromPublisher(getLatLngs(), Task.class)) + .build(); + + Flux taskResponse = exchange + .exchange(request) + .flatMap(response -> response.bodyToFlux(String.class)); + + assertThat(taskResponse.blockFirst()).isInstanceOf(String.class); + } + + private static Flux getLatLngs() { + return Flux + .range(0, 3) + .zipWith(Flux.interval(Duration.ofSeconds(1))) + .map(x -> new Task("taskname", 1)) + .doOnNext(ll -> System.out.println("Produced: {}" + ll)); + } +} diff --git a/spring-akka/pom.xml b/spring-akka/pom.xml index 1a273b0fed..5965213e65 100644 --- a/spring-akka/pom.xml +++ b/spring-akka/pom.xml @@ -70,6 +70,8 @@ maven-surefire-plugin ${maven-surefire-plugin.version} + 3 + true **/*IntegrationTest.java **/*LiveTest.java diff --git a/spring-all/README.md b/spring-all/README.md index 047f1bd5f6..3493871c78 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -19,3 +19,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Introduction To Ehcache](http://www.baeldung.com/ehcache) - [A Guide to the Spring Task Scheduler](http://www.baeldung.com/spring-task-scheduler) - [Guide to Spring Retry](http://www.baeldung.com/spring-retry) +- [Custom Scope in Spring](http://www.baeldung.com/spring-custom-scope) 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/customscope/TenantBean.java b/spring-all/src/main/java/org/baeldung/customscope/TenantBean.java new file mode 100644 index 0000000000..2d3049ebb9 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/customscope/TenantBean.java @@ -0,0 +1,16 @@ +package org.baeldung.customscope; + +public class TenantBean { + + private final String name; + + public TenantBean(String name) { + this.name = name; + } + + public void sayHello() { + System.out.println(String.format("Hello from %s of type %s", + this.name, + this.getClass().getName())); + } +} diff --git a/spring-all/src/main/java/org/baeldung/customscope/TenantBeanFactoryPostProcessor.java b/spring-all/src/main/java/org/baeldung/customscope/TenantBeanFactoryPostProcessor.java new file mode 100644 index 0000000000..2757399fa6 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/customscope/TenantBeanFactoryPostProcessor.java @@ -0,0 +1,13 @@ +package org.baeldung.customscope; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; + +public class TenantBeanFactoryPostProcessor implements BeanFactoryPostProcessor { + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException { + factory.registerScope("tenant", new TenantScope()); + } +} diff --git a/spring-all/src/main/java/org/baeldung/customscope/TenantBeansConfig.java b/spring-all/src/main/java/org/baeldung/customscope/TenantBeansConfig.java new file mode 100644 index 0000000000..0e21ad9344 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/customscope/TenantBeansConfig.java @@ -0,0 +1,21 @@ +package org.baeldung.customscope; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Scope; + +@Configuration +public class TenantBeansConfig { + + @Scope(scopeName = "tenant") + @Bean + public TenantBean foo() { + return new TenantBean("foo"); + } + + @Scope(scopeName = "tenant") + @Bean + public TenantBean bar() { + return new TenantBean("bar"); + } +} diff --git a/spring-all/src/main/java/org/baeldung/customscope/TenantScope.java b/spring-all/src/main/java/org/baeldung/customscope/TenantScope.java new file mode 100644 index 0000000000..062d7ee890 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/customscope/TenantScope.java @@ -0,0 +1,43 @@ +package org.baeldung.customscope; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.config.Scope; + +public class TenantScope implements Scope { + + private Map scopedObjects = Collections.synchronizedMap(new HashMap()); + private Map destructionCallbacks = Collections.synchronizedMap(new HashMap()); + + @Override + public Object get(String name, ObjectFactory objectFactory) { + if(!scopedObjects.containsKey(name)) { + scopedObjects.put(name, objectFactory.getObject()); + } + return scopedObjects.get(name); + } + + @Override + public Object remove(String name) { + destructionCallbacks.remove(name); + return scopedObjects.remove(name); + } + + @Override + public void registerDestructionCallback(String name, Runnable callback) { + destructionCallbacks.put(name, callback); + } + + @Override + public Object resolveContextualObject(String key) { + return null; + } + + @Override + public String getConversationId() { + return "tenant"; + } +} diff --git a/spring-all/src/main/java/org/baeldung/customscope/TenantScopeConfig.java b/spring-all/src/main/java/org/baeldung/customscope/TenantScopeConfig.java new file mode 100644 index 0000000000..d1159b0f60 --- /dev/null +++ b/spring-all/src/main/java/org/baeldung/customscope/TenantScopeConfig.java @@ -0,0 +1,14 @@ +package org.baeldung.customscope; + +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class TenantScopeConfig { + + @Bean + public static BeanFactoryPostProcessor beanFactoryPostProcessor() { + return new TenantBeanFactoryPostProcessor(); + } +} 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/java/org/baeldung/sample/AppConfig.java b/spring-all/src/main/java/org/baeldung/sample/AppConfig.java index ffc792d9df..8a177d2611 100644 --- a/spring-all/src/main/java/org/baeldung/sample/AppConfig.java +++ b/spring-all/src/main/java/org/baeldung/sample/AppConfig.java @@ -4,7 +4,7 @@ import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration -@ComponentScan("com.baeldung.autowire.sample") +@ComponentScan("org.baeldung.sample") public class AppConfig { } diff --git a/spring-all/src/main/resources/employee-schema.sql b/spring-all/src/main/resources/employee-schema.sql new file mode 100644 index 0000000000..011ff162e1 --- /dev/null +++ b/spring-all/src/main/resources/employee-schema.sql @@ -0,0 +1,27 @@ +CREATE TABLE EMPLOYEE( + ID INT NOT NULL PRIMARY KEY, + FIRST_NAME VARCHAR(255), + LAST_NAME VARCHAR(255), + SALARY DOUBLE, +); + +CREATE TABLE EMAIL( + ID INT NOT NULL PRIMARY KEY, + ID_EMPLOYEE VARCHAR(255), + ADDRESS VARCHAR(255) +); + +INSERT INTO EMPLOYEE VALUES (1, 'John', 'Doe', 10000.10); +INSERT INTO EMPLOYEE VALUES (2, 'Kevin', 'Smith', 20000.20); +INSERT INTO EMPLOYEE VALUES (3, 'Kim', 'Smith', 30000.30); +INSERT INTO EMPLOYEE VALUES (4, 'Stephen', 'Torvalds', 40000.40); +INSERT INTO EMPLOYEE VALUES (5, 'Christian', 'Reynolds', 50000.50); + +INSERT INTO EMAIL VALUES (1, 1, 'john@baeldung.com'); +INSERT INTO EMAIL VALUES (2, 1, 'john@gmail.com'); +INSERT INTO EMAIL VALUES (3, 2, 'kevin@baeldung.com'); +INSERT INTO EMAIL VALUES (4, 3, 'kim@baeldung.com'); +INSERT INTO EMAIL VALUES (5, 3, 'kim@gmail.com'); +INSERT INTO EMAIL VALUES (6, 3, 'kim@outlook.com'); +INSERT INTO EMAIL VALUES (7, 4, 'stephen@baeldung.com'); +INSERT INTO EMAIL VALUES (8, 5, 'christian@gmail.com'); diff --git a/spring-all/src/main/resources/employeeEmailReport.jrxml b/spring-all/src/main/resources/employeeEmailReport.jrxml new file mode 100644 index 0000000000..ad4aaaac90 --- /dev/null +++ b/spring-all/src/main/resources/employeeEmailReport.jrxml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/spring-all/src/main/resources/employeeReport.jrxml b/spring-all/src/main/resources/employeeReport.jrxml new file mode 100644 index 0000000000..3d2be226fb --- /dev/null +++ b/spring-all/src/main/resources/employeeReport.jrxml @@ -0,0 +1,51 @@ + + + + + + + + + = $P{minSalary} AND $P!{condition}]]> + + + + + + + <band height="20" splitType="Stretch"> + <textField> + <reportElement x="238" y="0" width="100" height="20"/> + <textElement/> + <textFieldExpression class="java.lang.String"><![CDATA[$P{title}]]></textFieldExpression> + </textField> + </band> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-all/src/test/java/org/baeldung/customscope/TenantScopeTest.java b/spring-all/src/test/java/org/baeldung/customscope/TenantScopeTest.java new file mode 100644 index 0000000000..641e57bffd --- /dev/null +++ b/spring-all/src/test/java/org/baeldung/customscope/TenantScopeTest.java @@ -0,0 +1,74 @@ +package org.baeldung.customscope; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.not; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import org.junit.Test; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +public class TenantScopeTest { + + @Test + public final void whenRegisterScopeAndBeans_thenContextContainsFooAndBar() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + try{ + ctx.register(TenantScopeConfig.class); + ctx.register(TenantBeansConfig.class); + ctx.refresh(); + + TenantBean foo = (TenantBean) ctx.getBean("foo", TenantBean.class); + foo.sayHello(); + TenantBean bar = (TenantBean) ctx.getBean("bar", TenantBean.class); + bar.sayHello(); + Map foos = ctx.getBeansOfType(TenantBean.class); + + assertThat(foo, not(equalTo(bar))); + assertThat(foos.size(), equalTo(2)); + assertTrue(foos.containsValue(foo)); + assertTrue(foos.containsValue(bar)); + + BeanDefinition fooDefinition = ctx.getBeanDefinition("foo"); + BeanDefinition barDefinition = ctx.getBeanDefinition("bar"); + + assertThat(fooDefinition.getScope(), equalTo("tenant")); + assertThat(barDefinition.getScope(), equalTo("tenant")); + } + finally { + ctx.close(); + } + } + + @Test + public final void whenComponentScan_thenContextContainsFooAndBar() { + AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); + try{ + ctx.scan("org.baeldung.customscope"); + ctx.refresh(); + + TenantBean foo = (TenantBean) ctx.getBean("foo", TenantBean.class); + foo.sayHello(); + TenantBean bar = (TenantBean) ctx.getBean("bar", TenantBean.class); + bar.sayHello(); + Map foos = ctx.getBeansOfType(TenantBean.class); + + assertThat(foo, not(equalTo(bar))); + assertThat(foos.size(), equalTo(2)); + assertTrue(foos.containsValue(foo)); + assertTrue(foos.containsValue(bar)); + + BeanDefinition fooDefinition = ctx.getBeanDefinition("foo"); + BeanDefinition barDefinition = ctx.getBeanDefinition("bar"); + + assertThat(fooDefinition.getScope(), equalTo("tenant")); + assertThat(barDefinition.getScope(), equalTo("tenant")); + } + finally { + ctx.close(); + } + } +} diff --git a/spring-amqp-simple/pom.xml b/spring-amqp-simple/pom.xml index 38738d875f..7ff26376e4 100644 --- a/spring-amqp-simple/pom.xml +++ b/spring-amqp-simple/pom.xml @@ -41,6 +41,16 @@ org.springframework.boot spring-boot-maven-plugin + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*IntegrationTest.java + **/*LiveTest.java + + + \ No newline at end of file diff --git a/spring-aop/pom.xml b/spring-aop/pom.xml index bd86839742..90e892b311 100644 --- a/spring-aop/pom.xml +++ b/spring-aop/pom.xml @@ -2,10 +2,10 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.baeldung - spring-custom-aop + spring-aop 0.0.1-SNAPSHOT war - spring-custom-aop + spring-aop org.springframework.boot @@ -42,6 +42,18 @@ 1.8 + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*IntegrationTest.java + **/*LiveTest.java + + + + diff --git a/spring-aop/src/test/java/org/baeldung/CustomAnnotationTest.java b/spring-aop/src/test/java/org/baeldung/CustomAnnotationIntegrationTest.java similarity index 91% rename from spring-aop/src/test/java/org/baeldung/CustomAnnotationTest.java rename to spring-aop/src/test/java/org/baeldung/CustomAnnotationIntegrationTest.java index d4712cc063..b109e3a39e 100644 --- a/spring-aop/src/test/java/org/baeldung/CustomAnnotationTest.java +++ b/spring-aop/src/test/java/org/baeldung/CustomAnnotationIntegrationTest.java @@ -8,7 +8,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest -public class CustomAnnotationTest { +public class CustomAnnotationIntegrationTest { @Autowired private Service service; diff --git a/spring-boot/README.MD b/spring-boot/README.MD index 8aa5957bad..bb15ffc8cc 100644 --- a/spring-boot/README.MD +++ b/spring-boot/README.MD @@ -15,4 +15,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Guide to Spring WebUtils and ServletRequestUtils](http://www.baeldung.com/spring-webutils-servletrequestutils) - [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) +- [Dynamic DTO Validation Config Retrieved from DB](http://www.baeldung.com/spring-dynamic-dto-validation) diff --git a/spring-boot/pom.xml b/spring-boot/pom.xml index f087617709..5f77be43e3 100644 --- a/spring-boot/pom.xml +++ b/spring-boot/pom.xml @@ -67,6 +67,7 @@ com.h2database h2 + ${h2.version} @@ -219,6 +220,7 @@ 3.3.7-1 3.1.7 8.5.11 + 1.4.194 diff --git a/spring-boot/src/main/java/com/baeldung/dynamicvalidation/ContactInfo.java b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/ContactInfo.java new file mode 100644 index 0000000000..41f873b42a --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/ContactInfo.java @@ -0,0 +1,26 @@ +package com.baeldung.dynamicvalidation; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import javax.validation.Constraint; +import javax.validation.Payload; + +@Constraint(validatedBy = { ContactInfoValidator.class }) +@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +public @interface ContactInfo { + String message() default "Invalid value"; + + Class[] groups() default {}; + + Class[] payload() default {}; + +} diff --git a/spring-boot/src/main/java/com/baeldung/dynamicvalidation/ContactInfoValidator.java b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/ContactInfoValidator.java new file mode 100644 index 0000000000..81345eac83 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/ContactInfoValidator.java @@ -0,0 +1,38 @@ +package com.baeldung.dynamicvalidation; + +import com.baeldung.dynamicvalidation.dao.ContactInfoExpressionRepository; +import com.baeldung.dynamicvalidation.model.ContactInfoExpression; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.thymeleaf.util.StringUtils; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; +import java.util.regex.Pattern; + +public class ContactInfoValidator implements ConstraintValidator { + + @Autowired + private ContactInfoExpressionRepository expressionRepository; + + @Value("${contactInfoType}") + String expressionType; + + @Override + public void initialize(final ContactInfo contactInfo) { + } + + @Override + public boolean isValid(final String value, final ConstraintValidatorContext context) { + if (StringUtils.isEmptyOrWhitespace(expressionType)) { + return false; + } + + return expressionRepository + .findOne(expressionType) + .map(ContactInfoExpression::getPattern) + .map(p -> Pattern.matches(p, value)) + .orElse(false); + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/dynamicvalidation/DynamicValidationApp.java b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/DynamicValidationApp.java new file mode 100644 index 0000000000..361a7b1c03 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/DynamicValidationApp.java @@ -0,0 +1,15 @@ +package com.baeldung.dynamicvalidation; + +import javax.annotation.security.RolesAllowed; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DynamicValidationApp { + @RolesAllowed("*") + public static void main(String[] args) { + System.setProperty("security.basic.enabled", "false"); + SpringApplication.run(DynamicValidationApp.class, args); + } +} diff --git a/spring-boot/src/main/java/com/baeldung/dynamicvalidation/config/CustomerController.java b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/config/CustomerController.java new file mode 100644 index 0000000000..d1e6b845d7 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/config/CustomerController.java @@ -0,0 +1,32 @@ +package com.baeldung.dynamicvalidation.config; + +import java.util.List; + +import javax.validation.Valid; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import com.baeldung.dynamicvalidation.model.Customer; + +@Controller +public class CustomerController { + + @GetMapping("/customer") + public String getCustomerPage(Model model) { + return "customer"; + } + + @PostMapping("/customer") + public String validateCustomer(@Valid final Customer customer, final BindingResult result, final Model model) { + if (result.hasErrors()) { + model.addAttribute("message", "The information is invalid!"); + } else { + model.addAttribute("message", "The information is valid!"); + } + return "customer"; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/dynamicvalidation/config/PersistenceConfig.java b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/config/PersistenceConfig.java new file mode 100644 index 0000000000..0eeac2a8dc --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/config/PersistenceConfig.java @@ -0,0 +1,30 @@ +package com.baeldung.dynamicvalidation.config; + +import javax.sql.DataSource; + +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; + +@EnableJpaRepositories("com.baeldung.dynamicvalidation.dao") +@EntityScan("com.baeldung.dynamicvalidation.model") +@Configuration +public class PersistenceConfig { + + @Bean + public JdbcTemplate getJdbcTemplate() { + return new JdbcTemplate(dataSource()); + } + + @Bean + public DataSource dataSource() { + EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); + EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.H2).addScript("schema-expressions.sql").addScript("data-expressions.sql").build(); + return db; + } +} diff --git a/spring-boot/src/main/java/com/baeldung/dynamicvalidation/dao/ContactInfoExpressionRepository.java b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/dao/ContactInfoExpressionRepository.java new file mode 100644 index 0000000000..0d7797b996 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/dao/ContactInfoExpressionRepository.java @@ -0,0 +1,11 @@ +package com.baeldung.dynamicvalidation.dao; + +import java.util.Optional; + +import org.springframework.data.repository.Repository; + +import com.baeldung.dynamicvalidation.model.ContactInfoExpression; + +public interface ContactInfoExpressionRepository extends Repository { + Optional findOne(String id); +} diff --git a/spring-boot/src/main/java/com/baeldung/dynamicvalidation/model/ContactInfoExpression.java b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/model/ContactInfoExpression.java new file mode 100644 index 0000000000..9c202b07c8 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/model/ContactInfoExpression.java @@ -0,0 +1,40 @@ +package com.baeldung.dynamicvalidation.model; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; + +@Entity +public class ContactInfoExpression { + + @Id + @Column(name = "expression_type") + private String type; + private String pattern; + + public ContactInfoExpression() { + + } + + public ContactInfoExpression(final String type, final String pattern) { + this.type = type; + this.pattern = pattern; + } + + public String getType() { + return type; + } + + public void setType(final String type) { + this.type = type; + } + + public String getPattern() { + return pattern; + } + + public void setPattern(final String pattern) { + this.pattern = pattern; + } + +} diff --git a/spring-boot/src/main/java/com/baeldung/dynamicvalidation/model/Customer.java b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/model/Customer.java new file mode 100644 index 0000000000..f043458fce --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/dynamicvalidation/model/Customer.java @@ -0,0 +1,44 @@ +package com.baeldung.dynamicvalidation.model; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import com.baeldung.dynamicvalidation.ContactInfo; + +@Entity +public class Customer { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private long id; + + @ContactInfo + private String contactInfo; + + public Customer() { + } + + public Customer(final long id, final String contactInfo) { + this.id = id; + this.contactInfo = contactInfo; + } + + public String getContactInfo() { + return contactInfo; + } + + public void setContactInfo(final String contactInfo) { + this.contactInfo = contactInfo; + } + + public long getId() { + return id; + } + + public void setId(final long id) { + this.id = id; + } + +} diff --git a/spring-boot/src/main/java/org/baeldung/boot/boottest/Employee.java b/spring-boot/src/main/java/org/baeldung/boot/boottest/Employee.java new file mode 100644 index 0000000000..a805e8f5fe --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/boottest/Employee.java @@ -0,0 +1,43 @@ +package org.baeldung.boot.boottest; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.validation.constraints.Size; + +@Entity +@Table(name = "person") +public class Employee { + + public Employee() { + } + + public Employee(String name) { + this.name = name; + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @Size(min = 3, max = 20) + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} \ No newline at end of file diff --git a/spring-boot/src/main/java/org/baeldung/boot/boottest/EmployeeRepository.java b/spring-boot/src/main/java/org/baeldung/boot/boottest/EmployeeRepository.java new file mode 100644 index 0000000000..fa234f0e3a --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/boottest/EmployeeRepository.java @@ -0,0 +1,21 @@ +package org.baeldung.boot.boottest; + +import java.util.List; +import java.util.Optional; + +import javax.transaction.Transactional; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +@Transactional +public interface EmployeeRepository extends JpaRepository { + + public Optional findByName(String name); + + public Optional findById(Long id); + + public List findAll(); + +} diff --git a/spring-boot/src/main/java/org/baeldung/boot/boottest/EmployeeRestController.java b/spring-boot/src/main/java/org/baeldung/boot/boottest/EmployeeRestController.java new file mode 100644 index 0000000000..8442fc03a3 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/boottest/EmployeeRestController.java @@ -0,0 +1,32 @@ +package org.baeldung.boot.boottest; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api") +public class EmployeeRestController { + + @Autowired + EmployeeService employeeService; + + @RequestMapping(value = "/employees", method = RequestMethod.POST) + public ResponseEntity createEmployee(@RequestBody Employee employee) { + HttpStatus status = HttpStatus.CREATED; + Employee saved = employeeService.save(employee); + return new ResponseEntity<>(saved, status); + } + + @RequestMapping(value = "/employees", method = RequestMethod.GET) + public List getAllEmployees() { + return employeeService.getAllEmployees(); + } + +} diff --git a/spring-boot/src/main/java/org/baeldung/boot/boottest/EmployeeService.java b/spring-boot/src/main/java/org/baeldung/boot/boottest/EmployeeService.java new file mode 100644 index 0000000000..f0ed49e699 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/boottest/EmployeeService.java @@ -0,0 +1,17 @@ +package org.baeldung.boot.boottest; + +import java.util.List; +import java.util.Optional; + +public interface EmployeeService { + + public Optional getEmployeeById(Long id); + + public Optional getEmployeeByName(String name); + + public List getAllEmployees(); + + public boolean exists(String email); + + public Employee save(Employee employee); +} diff --git a/spring-boot/src/main/java/org/baeldung/boot/boottest/EmployeeServiceImpl.java b/spring-boot/src/main/java/org/baeldung/boot/boottest/EmployeeServiceImpl.java new file mode 100644 index 0000000000..21936255e0 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/boottest/EmployeeServiceImpl.java @@ -0,0 +1,45 @@ +package org.baeldung.boot.boottest; + +import java.util.List; +import java.util.Optional; + +import javax.transaction.Transactional; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +@Transactional +public class EmployeeServiceImpl implements EmployeeService { + + @Autowired + EmployeeRepository employeeRepository; + + @Override + public Optional getEmployeeById(Long id) { + return employeeRepository.findById(id); + } + + @Override + public Optional getEmployeeByName(String name) { + return employeeRepository.findByName(name); + } + + @Override + public boolean exists(String name) { + if (employeeRepository.findByName(name) != null) { + return true; + } + return false; + } + + @Override + public Employee save(Employee employee) { + return employeeRepository.save(employee); + } + + @Override + public List getAllEmployees() { + return employeeRepository.findAll(); + } +} diff --git a/spring-boot/src/main/java/org/baeldung/config/H2JpaConfig.java b/spring-boot/src/main/java/org/baeldung/config/H2JpaConfig.java new file mode 100644 index 0000000000..ace7bb5a6d --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/config/H2JpaConfig.java @@ -0,0 +1,67 @@ +package org.baeldung.config; + +import java.util.Properties; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableJpaRepositories(basePackages = { "org.baeldung.repository", "org.baeldung.boot.repository" }) +@PropertySource("classpath:persistence-generic-entity.properties") +@EnableTransactionManagement +public class H2JpaConfig { + + @Autowired + private Environment env; + + @Bean + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName")); + dataSource.setUrl(env.getProperty("jdbc.url")); + dataSource.setUsername(env.getProperty("jdbc.user")); + dataSource.setPassword(env.getProperty("jdbc.pass")); + + return dataSource; + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "org.baeldung.domain", "org.baeldung.boot.model" }); + em.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); + em.setJpaProperties(additionalProperties()); + return em; + } + + @Bean + JpaTransactionManager transactionManager(final EntityManagerFactory entityManagerFactory) { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory); + return transactionManager; + } + + final Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql")); + + return hibernateProperties; + } + +} diff --git a/spring-boot/src/main/java/org/baeldung/jsoncomponent/UserCombinedSerializer.java b/spring-boot/src/main/java/org/baeldung/jsoncomponent/UserCombinedSerializer.java index 302b0dce61..2001340197 100644 --- a/spring-boot/src/main/java/org/baeldung/jsoncomponent/UserCombinedSerializer.java +++ b/spring-boot/src/main/java/org/baeldung/jsoncomponent/UserCombinedSerializer.java @@ -34,7 +34,6 @@ public class UserCombinedSerializer { } } - @JsonComponent public static class UserJsonDeserializer extends JsonDeserializer { @Override public User deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { diff --git a/spring-boot/src/main/resources/application.properties b/spring-boot/src/main/resources/application.properties index 84315a2477..444f68d50a 100644 --- a/spring-boot/src/main/resources/application.properties +++ b/spring-boot/src/main/resources/application.properties @@ -43,4 +43,6 @@ servlet.mapping=/dispatcherExampleURL #banner.image.width= //TODO #banner.image.height= //TODO #banner.image.margin= //TODO -#banner.image.invert= //TODO \ No newline at end of file +#banner.image.invert= //TODO + +contactInfoType=email \ No newline at end of file diff --git a/spring-boot/src/main/resources/data-expressions.sql b/spring-boot/src/main/resources/data-expressions.sql new file mode 100644 index 0000000000..3e702a759d --- /dev/null +++ b/spring-boot/src/main/resources/data-expressions.sql @@ -0,0 +1,3 @@ +insert into contact_info_expression values ('email','[a-z0-9!#$%&*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?') +insert into contact_info_expression values ('phone','^([0-9]( |-)?)?(\(?[0-9]{3}\)?|[0-9]{3})( |-)?([0-9]{3}( |-)?[0-9]{4}|[a-zA-Z0-9]{7})$') +insert into contact_info_expression values ('website','^(http:\/\/www\.|https:\/\/www\.|http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$') \ No newline at end of file diff --git a/spring-boot/src/main/resources/schema-expressions.sql b/spring-boot/src/main/resources/schema-expressions.sql new file mode 100644 index 0000000000..59f6ab05eb --- /dev/null +++ b/spring-boot/src/main/resources/schema-expressions.sql @@ -0,0 +1,5 @@ +create table contact_info_expression( + expression_type varchar(50) not null, + pattern varchar(500) not null, + PRIMARY KEY ( expression_type ) +); \ No newline at end of file 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/main/resources/templates/customer.html b/spring-boot/src/main/resources/templates/customer.html new file mode 100644 index 0000000000..c8f5a25d5e --- /dev/null +++ b/spring-boot/src/main/resources/templates/customer.html @@ -0,0 +1,16 @@ + + + +Customer Page + + + +
+
+Contact Info:
+ +
+

+
+ + \ No newline at end of file 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/java/org/baeldung/SpringBootH2IntegrationTest.java b/spring-boot/src/test/java/org/baeldung/SpringBootH2IntegrationTest.java new file mode 100644 index 0000000000..185a36e571 --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/SpringBootH2IntegrationTest.java @@ -0,0 +1,28 @@ +package org.baeldung; + +import org.baeldung.config.H2JpaConfig; +import org.baeldung.domain.GenericEntity; +import org.baeldung.repository.GenericEntityRepository; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = { Application.class, H2JpaConfig.class }) +public class SpringBootH2IntegrationTest { + @Autowired + private GenericEntityRepository genericEntityRepository; + + @Test + public void givenGenericEntityRepository_whenSaveAndRetreiveEntity_thenOK() { + GenericEntity genericEntity = genericEntityRepository.save(new GenericEntity("test")); + GenericEntity foundEntity = genericEntityRepository.findOne(genericEntity.getId()); + assertNotNull(foundEntity); + assertEquals(genericEntity.getValue(), foundEntity.getValue()); + } +} \ No newline at end of file diff --git a/spring-boot/src/test/java/org/baeldung/SpringBootJPAIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/SpringBootJPAIntegrationTest.java index d4b19e6a1d..202d24ffc7 100644 --- a/spring-boot/src/test/java/org/baeldung/SpringBootJPAIntegrationTest.java +++ b/spring-boot/src/test/java/org/baeldung/SpringBootJPAIntegrationTest.java @@ -20,8 +20,8 @@ public class SpringBootJPAIntegrationTest { @Test public void givenGenericEntityRepository_whenSaveAndRetreiveEntity_thenOK() { GenericEntity genericEntity = genericEntityRepository.save(new GenericEntity("test")); - GenericEntity foundedEntity = genericEntityRepository.findOne(genericEntity.getId()); - assertNotNull(foundedEntity); - assertEquals(genericEntity.getValue(), foundedEntity.getValue()); + GenericEntity foundEntity = genericEntityRepository.findOne(genericEntity.getId()); + assertNotNull(foundEntity); + assertEquals(genericEntity.getValue(), foundEntity.getValue()); } } diff --git a/spring-boot/src/test/java/org/baeldung/SpringBootProfileIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/SpringBootProfileIntegrationTest.java new file mode 100644 index 0000000000..806b38a8ce --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/SpringBootProfileIntegrationTest.java @@ -0,0 +1,30 @@ +package org.baeldung; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.baeldung.config.H2TestProfileJPAConfig; +import org.baeldung.domain.GenericEntity; +import org.baeldung.repository.GenericEntityRepository; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringBootTest(classes = { Application.class, H2TestProfileJPAConfig.class }) +@ActiveProfiles("test") +public class SpringBootProfileIntegrationTest { + @Autowired + private GenericEntityRepository genericEntityRepository; + + @Test + public void givenGenericEntityRepository_whenSaveAndRetreiveEntity_thenOK() { + GenericEntity genericEntity = genericEntityRepository.save(new GenericEntity("test")); + GenericEntity foundEntity = genericEntityRepository.findOne(genericEntity.getId()); + assertNotNull(foundEntity); + assertEquals(genericEntity.getValue(), foundEntity.getValue()); + } +} diff --git a/spring-boot/src/test/java/org/baeldung/boot/boottest/EmployeeRepositoryTest.java b/spring-boot/src/test/java/org/baeldung/boot/boottest/EmployeeRepositoryTest.java new file mode 100644 index 0000000000..f47e28a7e1 --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/boot/boottest/EmployeeRepositoryTest.java @@ -0,0 +1,78 @@ +package org.baeldung.boot.boottest; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; + +import org.baeldung.boot.boottest.Employee; +import org.baeldung.boot.boottest.EmployeeRepository; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@DataJpaTest +public class EmployeeRepositoryTest { + + @Autowired + TestEntityManager entityManager; + + @Autowired + EmployeeRepository employeeRepository; + + @Test + public void whenFindByName_thenReturnEmployee() { + Employee emp = new Employee("test"); + entityManager.persistAndFlush(emp); + + Optional fromDb = employeeRepository.findByName(emp.getName()); + assertThat(fromDb.get() + .getName()).isEqualTo(emp.getName()); + } + + @Test(expected = NoSuchElementException.class) + public void whenInvalidName_thenNoSuchElementException() { + Optional fromDb = employeeRepository.findByName("doesNotExist"); + fromDb.get(); + } + + @Test + public void whenFindById_thenReturnEmployee() { + Employee emp = new Employee("test"); + entityManager.persistAndFlush(emp); + + Optional fromDb = employeeRepository.findById(emp.getId()); + assertThat(fromDb.get() + .getName()).isEqualTo(emp.getName()); + } + + @Test(expected = NoSuchElementException.class) + public void whenInvalidId_thenNoSuchElementException() { + Optional fromDb = employeeRepository.findById(-11L); + fromDb.get(); + } + + @Test + public void givenSetOfEmployees_whenFindAll_thenReturnAllEmployees() { + Employee alex = new Employee("alex"); + Employee ron = new Employee("ron"); + Employee bob = new Employee("bob"); + + entityManager.persist(alex); + entityManager.persist(bob); + entityManager.persist(ron); + entityManager.flush(); + + List allEmployees = employeeRepository.findAll(); + + assertThat(allEmployees).hasSize(3) + .extracting(Employee::getName) + .containsOnly(alex.getName(), ron.getName(), bob.getName()); + } + +} diff --git a/spring-boot/src/test/java/org/baeldung/boot/boottest/EmployeeRestControllerIntTest.java b/spring-boot/src/test/java/org/baeldung/boot/boottest/EmployeeRestControllerIntTest.java new file mode 100644 index 0000000000..6360970345 --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/boot/boottest/EmployeeRestControllerIntTest.java @@ -0,0 +1,78 @@ +package org.baeldung.boot.boottest; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; +import static org.hamcrest.Matchers.hasSize; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.io.IOException; +import java.util.List; + +import org.baeldung.boot.DemoApplication; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.http.MediaType; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = DemoApplication.class) +@AutoConfigureMockMvc +@TestPropertySource(locations = "classpath:application-integrationtest.properties") +public class EmployeeRestControllerIntTest { + + @Autowired + MockMvc mvc; + + @Autowired + EmployeeRepository repository; + + @After + public void resetDb() { + repository.deleteAll(); + } + + @Test + public void whenValidInput_thenCreateEmployee() throws IOException, Exception { + Employee bob = new Employee("bob"); + mvc.perform(post("/api/employees").contentType(MediaType.APPLICATION_JSON) + .content(JsonUtil.toJson(bob))); + + List found = repository.findAll(); + assertThat(found).extracting(Employee::getName) + .containsOnly("bob"); + } + + @Test + public void givenEmployees_whenGetEmployees_thenStatus200() throws Exception { + + createTestEmployee("bob"); + createTestEmployee("alex"); + + mvc.perform(get("/api/employees").contentType(MediaType.APPLICATION_JSON)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(jsonPath("$", hasSize(greaterThanOrEqualTo(2)))) + .andExpect(jsonPath("$[0].name", is("bob"))) + .andExpect(jsonPath("$[1].name", is("alex"))); + } + + private void createTestEmployee(String name) { + Employee emp = new Employee(name); + repository.saveAndFlush(emp); + } + +} diff --git a/spring-boot/src/test/java/org/baeldung/boot/boottest/EmployeeRestControllerTest.java b/spring-boot/src/test/java/org/baeldung/boot/boottest/EmployeeRestControllerTest.java new file mode 100644 index 0000000000..0187ba9969 --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/boot/boottest/EmployeeRestControllerTest.java @@ -0,0 +1,78 @@ +package org.baeldung.boot.boottest; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.hasSize; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.verify; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.Arrays; +import java.util.List; + +import org.baeldung.boot.boottest.Employee; +import org.baeldung.boot.boottest.EmployeeRestController; +import org.baeldung.boot.boottest.EmployeeService; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.internal.verification.VerificationModeFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +@RunWith(SpringRunner.class) +@WebMvcTest(EmployeeRestController.class) +public class EmployeeRestControllerTest { + + @Autowired + MockMvc mvc; + + @MockBean + EmployeeService service; + + @Before + public void setUp() throws Exception { + } + + @Test + public void whenPostEmployee_thenCreateEmployee() throws Exception { + Employee alex = new Employee("alex"); + given(service.save(Mockito.anyObject())).willReturn(alex); + + mvc.perform(post("/api/employees").contentType(MediaType.APPLICATION_JSON) + .content(JsonUtil.toJson(alex))) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.name", is("alex"))); + verify(service, VerificationModeFactory.times(1)).save(Mockito.anyObject()); + reset(service); + } + + @Test + public void givenEmployees_whenGetEmployees_thenReturnJsonArray() throws Exception { + Employee alex = new Employee("alex"); + Employee john = new Employee("john"); + Employee bob = new Employee("bob"); + + List allEmployees = Arrays.asList(alex, john, bob); + + given(service.getAllEmployees()).willReturn(allEmployees); + + mvc.perform(get("/api/employees").contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$", hasSize(3))) + .andExpect(jsonPath("$[0].name", is(alex.getName()))) + .andExpect(jsonPath("$[1].name", is(john.getName()))) + .andExpect(jsonPath("$[2].name", is(bob.getName()))); + verify(service, VerificationModeFactory.times(1)).getAllEmployees(); + reset(service); + } + +} \ No newline at end of file diff --git a/spring-boot/src/test/java/org/baeldung/boot/boottest/EmployeeServiceImplTest.java b/spring-boot/src/test/java/org/baeldung/boot/boottest/EmployeeServiceImplTest.java new file mode 100644 index 0000000000..345cc29e02 --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/boot/boottest/EmployeeServiceImplTest.java @@ -0,0 +1,145 @@ +package org.baeldung.boot.boottest; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; + +import org.baeldung.boot.boottest.Employee; +import org.baeldung.boot.boottest.EmployeeRepository; +import org.baeldung.boot.boottest.EmployeeService; +import org.baeldung.boot.boottest.EmployeeServiceImpl; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.internal.verification.VerificationModeFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +public class EmployeeServiceImplTest { + + @TestConfiguration + static class EmployeeServiceImplTestContextConfiguration { + @Bean + public EmployeeService employeeService() { + return new EmployeeServiceImpl(); + } + } + + @Autowired + EmployeeService employeeService; + + @MockBean + EmployeeRepository employeeRepository; + + @Before + public void setUp() { + Employee john = new Employee("john"); + john.setId(11L); + + Optional emp = Optional.of(john); + + Employee bob = new Employee("bob"); + Employee alex = new Employee("alex"); + + List allEmployees = Arrays.asList(john, bob, alex); + + Mockito.when(employeeRepository.findByName(john.getName())) + .thenReturn(emp); + Mockito.when(employeeRepository.findByName("wrong_name")) + .thenReturn(Optional.empty()); + Mockito.when(employeeRepository.findById(john.getId())) + .thenReturn(emp); + Mockito.when(employeeRepository.findAll()) + .thenReturn(allEmployees); + Mockito.when(employeeRepository.findById(-99L)) + .thenReturn(Optional.empty()); + } + + @Test + public void whenValidName_thenEmployeeShouldBeFound() { + Optional fromDb = employeeService.getEmployeeByName("john"); + assertThat(fromDb.get() + .getName()).isEqualTo("john"); + + verifyFindByNameIsCalledOnce("john"); + } + + @Test(expected = NoSuchElementException.class) + public void whenInValidName_thenEmployeeShouldNotBeFound() { + Optional fromDb = employeeService.getEmployeeByName("wrong_name"); + fromDb.get(); + + verifyFindByNameIsCalledOnce("wrong_name"); + } + + @Test + public void whenValidName_thenEmployeeShouldExist() { + boolean doesEmployeeExist = employeeService.exists("john"); + assertThat(doesEmployeeExist).isEqualTo(true); + + verifyFindByNameIsCalledOnce("john"); + } + + @Test + public void whenNonExistingName_thenEmployeeShouldNotExist() { + boolean doesEmployeeExist = employeeService.exists("some_name"); + assertThat(doesEmployeeExist).isEqualTo(false); + + verifyFindByNameIsCalledOnce("some_name"); + } + + @Test + public void whenValidI_thendEmployeeShouldBeFound() { + Optional fromDb = employeeService.getEmployeeById(11L); + assertThat(fromDb.get() + .getName()).isEqualTo("john"); + + verifyFindByIdIsCalledOnce(); + } + + @Test(expected = NoSuchElementException.class) + public void whenInValidId_thenEmployeeShouldNotBeFound() { + Optional fromDb = employeeService.getEmployeeById(-99L); + verifyFindByIdIsCalledOnce(); + fromDb.get(); + } + + @Test + public void given3Employees_whengetAll_thenReturn3Records() { + Employee alex = new Employee("alex"); + Employee john = new Employee("john"); + Employee bob = new Employee("bob"); + + List allEmployees = employeeService.getAllEmployees(); + verifyFindAllEmployeesIsCalledOnce(); + assertThat(allEmployees).hasSize(3) + .extracting(Employee::getName) + .contains(alex.getName(), john.getName(), bob.getName()); + } + + private void verifyFindByNameIsCalledOnce(String name) { + Mockito.verify(employeeRepository, VerificationModeFactory.times(1)) + .findByName(name); + Mockito.reset(employeeRepository); + } + + private void verifyFindByIdIsCalledOnce() { + Mockito.verify(employeeRepository, VerificationModeFactory.times(1)) + .findById(Mockito.anyLong()); + Mockito.reset(employeeRepository); + } + + private void verifyFindAllEmployeesIsCalledOnce() { + Mockito.verify(employeeRepository, VerificationModeFactory.times(1)) + .findAll(); + Mockito.reset(employeeRepository); + } +} diff --git a/spring-boot/src/test/java/org/baeldung/boot/boottest/JsonUtil.java b/spring-boot/src/test/java/org/baeldung/boot/boottest/JsonUtil.java new file mode 100644 index 0000000000..3d532ce54a --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/boot/boottest/JsonUtil.java @@ -0,0 +1,14 @@ +package org.baeldung.boot.boottest; + +import java.io.IOException; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class JsonUtil { + public static byte[] toJson(Object object) throws IOException { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + return mapper.writeValueAsBytes(object); + } +} diff --git a/spring-boot/src/test/java/org/baeldung/config/H2TestProfileJPAConfig.java b/spring-boot/src/test/java/org/baeldung/config/H2TestProfileJPAConfig.java new file mode 100644 index 0000000000..1d696f4a5d --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/config/H2TestProfileJPAConfig.java @@ -0,0 +1,66 @@ +package org.baeldung.config; + +import java.util.Properties; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableJpaRepositories(basePackages = { "org.baeldung.repository", "org.baeldung.boot.repository" }) +@EnableTransactionManagement +public class H2TestProfileJPAConfig { + + @Autowired + private Environment env; + + @Bean + @Profile("test") + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName("org.h2.Driver"); + dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1"); + dataSource.setUsername("sa"); + dataSource.setPassword("sa"); + + return dataSource; + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "org.baeldung.domain", "org.baeldung.boot.model" }); + em.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); + em.setJpaProperties(additionalProperties()); + return em; + } + + @Bean + JpaTransactionManager transactionManager(final EntityManagerFactory entityManagerFactory) { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory); + return transactionManager; + } + + final Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql")); + + return hibernateProperties; + } +} diff --git a/spring-boot/src/test/java/org/baeldung/jsoncomponent/UserJsonDeserializerTest.java b/spring-boot/src/test/java/org/baeldung/jsoncomponent/UserJsonDeserializerIntegrationTest.java similarity index 93% rename from spring-boot/src/test/java/org/baeldung/jsoncomponent/UserJsonDeserializerTest.java rename to spring-boot/src/test/java/org/baeldung/jsoncomponent/UserJsonDeserializerIntegrationTest.java index 51c1c72ea3..4f5af3d0e7 100644 --- a/spring-boot/src/test/java/org/baeldung/jsoncomponent/UserJsonDeserializerTest.java +++ b/spring-boot/src/test/java/org/baeldung/jsoncomponent/UserJsonDeserializerIntegrationTest.java @@ -14,7 +14,7 @@ import static org.junit.Assert.assertEquals; @JsonTest @RunWith(SpringRunner.class) -public class UserJsonDeserializerTest { +public class UserJsonDeserializerIntegrationTest { @Autowired private ObjectMapper objectMapper; diff --git a/spring-boot/src/test/java/org/baeldung/jsoncomponent/UserJsonSerializerTest.java b/spring-boot/src/test/java/org/baeldung/jsoncomponent/UserJsonSerializerIntegrationTest.java similarity index 94% rename from spring-boot/src/test/java/org/baeldung/jsoncomponent/UserJsonSerializerTest.java rename to spring-boot/src/test/java/org/baeldung/jsoncomponent/UserJsonSerializerIntegrationTest.java index c85af4a17f..c1b4c8912c 100644 --- a/spring-boot/src/test/java/org/baeldung/jsoncomponent/UserJsonSerializerTest.java +++ b/spring-boot/src/test/java/org/baeldung/jsoncomponent/UserJsonSerializerIntegrationTest.java @@ -14,7 +14,7 @@ import static org.junit.Assert.assertEquals; @JsonTest @RunWith(SpringRunner.class) -public class UserJsonSerializerTest { +public class UserJsonSerializerIntegrationTest { @Autowired private ObjectMapper objectMapper; diff --git a/spring-boot/src/test/resources/application-integrationtest.properties b/spring-boot/src/test/resources/application-integrationtest.properties new file mode 100644 index 0000000000..508acf45e0 --- /dev/null +++ b/spring-boot/src/test/resources/application-integrationtest.properties @@ -0,0 +1,2 @@ +spring.datasource.url = jdbc:h2:mem:test +spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.H2Dialect \ No newline at end of file diff --git a/spring-boot/src/test/resources/application.properties b/spring-boot/src/test/resources/application.properties index 0e6cb86bc5..85e4e6e66f 100644 --- a/spring-boot/src/test/resources/application.properties +++ b/spring-boot/src/test/resources/application.properties @@ -2,4 +2,18 @@ spring.mail.host=localhost spring.mail.port=8025 spring.mail.properties.mail.smtp.auth=false -security.basic.enabled=false \ No newline at end of file +security.basic.enabled=false + +# spring.datasource.x +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 +spring.datasource.username=sa +spring.datasource.password=sa + +# hibernate.X +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=true +hibernate.hbm2ddl.auto=create-drop +hibernate.cache.use_second_level_cache=true +hibernate.cache.use_query_cache=true +hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory \ 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 new file mode 100644 index 0000000000..b19304cb1f --- /dev/null +++ b/spring-boot/src/test/resources/persistence-generic-entity.properties @@ -0,0 +1,8 @@ +jdbc.driverClassName=org.h2.Driver +jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 +jdbc.user=sa +jdbc.pass=sa + +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=true +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-data-flow/data-flow-shell/pom.xml b/spring-cloud-data-flow/data-flow-shell/pom.xml index d3bd297152..350f199d4b 100644 --- a/spring-cloud-data-flow/data-flow-shell/pom.xml +++ b/spring-cloud-data-flow/data-flow-shell/pom.xml @@ -68,6 +68,8 @@ org.apache.maven.plugins maven-surefire-plugin + 3 + true **/*IntegrationTest.java **/*LiveTest.java diff --git a/spring-cloud/pom.xml b/spring-cloud/pom.xml index 5b5b006d01..6d53b24647 100644 --- a/spring-cloud/pom.xml +++ b/spring-cloud/pom.xml @@ -13,6 +13,7 @@ spring-cloud-bootstrap spring-cloud-ribbon-client spring-cloud-rest + spring-cloud-zookeeper pom diff --git a/spring-cloud/spring-cloud-rest/spring-cloud-rest-discovery-server/pom.xml b/spring-cloud/spring-cloud-rest/spring-cloud-rest-discovery-server/pom.xml index d9d08079b7..d9ef26280b 100644 --- a/spring-cloud/spring-cloud-rest/spring-cloud-rest-discovery-server/pom.xml +++ b/spring-cloud/spring-cloud-rest/spring-cloud-rest-discovery-server/pom.xml @@ -76,6 +76,8 @@ org.apache.maven.plugins maven-surefire-plugin + 3 + true **/*IntegrationTest.java **/*LiveTest.java diff --git a/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml b/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml new file mode 100644 index 0000000000..de76c86a24 --- /dev/null +++ b/spring-cloud/spring-cloud-zookeeper/Greeting/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + + com.baeldung.spring.cloud + spring-cloud-zookeeper + 1.0.0-SNAPSHOT + + Greeting + jar + + + org.springframework.boot + spring-boot-starter + 1.5.2.RELEASE + + + org.springframework + spring-web + 4.3.7.RELEASE + + + org.springframework.cloud + spring-cloud-starter-zookeeper-discovery + 1.0.3.RELEASE + + + org.springframework.boot + spring-boot-starter-actuator + 1.5.2.RELEASE + + + org.springframework.cloud + spring-cloud-starter-feign + 1.2.5.RELEASE + + + junit + junit + 4.12 + test + + + org.hamcrest + hamcrest-core + 1.3 + test + + + + + + + org.springframework.cloud + spring-cloud-dependencies + Brixton.SR7 + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + Greeting + \ No newline at end of file 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 new file mode 100644 index 0000000000..8a1662999b --- /dev/null +++ b/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/GreetingApplication.java @@ -0,0 +1,20 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.baeldung.spring.cloud.greeting; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + +@SpringBootApplication +@EnableDiscoveryClient +public class GreetingApplication { + + public static void main(String[] args) { + SpringApplication.run(GreetingApplication.class, args); + } + +} 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 new file mode 100644 index 0000000000..d98e22f822 --- /dev/null +++ b/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/GreetingController.java @@ -0,0 +1,27 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.baeldung.spring.cloud.greeting; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class GreetingController { + + @Autowired + private HelloWorldClient helloWorldClient; + + @RequestMapping(value = "/get-greeting", method = RequestMethod.GET) + + public String greeting() { + + 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 new file mode 100644 index 0000000000..c56cb1907a --- /dev/null +++ b/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/java/com/baeldung/spring/cloud/greeting/HelloWorldClient.java @@ -0,0 +1,41 @@ +package com.baeldung.spring.cloud.greeting; + +import org.springframework.beans.factory.annotation.Autowired; +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.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * This class provides operations on the Validation service. + * + *

+ * When booting up, Spring will try and find a service named "Validation" (see + * the FeignClient below) under the available ZooKeeper instance. + *

+ * + */ +@Configuration +@EnableFeignClients +@EnableDiscoveryClient +public class HelloWorldClient { + + @Autowired + private TheClient theClient; + + @FeignClient(name = "HelloWorld") + interface TheClient { + + @RequestMapping(path = "/helloworld", method = RequestMethod.GET) + @ResponseBody + String HelloWorld(); + } + + public String HelloWorld() { + return theClient.HelloWorld(); + } + +} diff --git a/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/resources/application.yml b/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/resources/application.yml new file mode 100644 index 0000000000..6140f6ab2f --- /dev/null +++ b/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/resources/application.yml @@ -0,0 +1,11 @@ +spring: + application: + name: Greeting + cloud: + zookeeper: + connect-string: localhost:2181 +server: + port: 8083 +logging: + level: + org.apache.zookeeper.ClientCnxn: WARN \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/resources/templates/greeting-view.html b/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/resources/templates/greeting-view.html new file mode 100644 index 0000000000..42cdadb487 --- /dev/null +++ b/spring-cloud/spring-cloud-zookeeper/Greeting/src/main/resources/templates/greeting-view.html @@ -0,0 +1,9 @@ + + + + Greeting Page + + +

+ + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zookeeper/HelloWorld/pom.xml b/spring-cloud/spring-cloud-zookeeper/HelloWorld/pom.xml new file mode 100644 index 0000000000..1c829a50df --- /dev/null +++ b/spring-cloud/spring-cloud-zookeeper/HelloWorld/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + + com.baeldung.spring.cloud + spring-cloud-zookeeper + 1.0.0-SNAPSHOT + + HelloWorld + jar + + + org.springframework.boot + spring-boot-starter + 1.5.2.RELEASE + + + org.springframework + spring-web + 4.3.7.RELEASE + + + org.springframework.cloud + spring-cloud-starter-zookeeper-discovery + 1.0.3.RELEASE + + + + + + + org.springframework.cloud + spring-cloud-dependencies + Brixton.SR7 + pom + import + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + HelloWorld + \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/main/java/com/baeldung/spring/cloud/helloworld/HelloWorldApplication.java b/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/main/java/com/baeldung/spring/cloud/helloworld/HelloWorldApplication.java new file mode 100644 index 0000000000..8b35071516 --- /dev/null +++ b/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/main/java/com/baeldung/spring/cloud/helloworld/HelloWorldApplication.java @@ -0,0 +1,18 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.baeldung.spring.cloud.helloworld; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cloud.client.discovery.EnableDiscoveryClient; + +@SpringBootApplication +@EnableDiscoveryClient +public class HelloWorldApplication { + public static void main(String[] args) { + SpringApplication.run(HelloWorldApplication.class, args); + } +} 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 new file mode 100644 index 0000000000..9048e6bed8 --- /dev/null +++ b/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/main/java/com/baeldung/spring/cloud/helloworld/HelloWorldController.java @@ -0,0 +1,20 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.baeldung.spring.cloud.helloworld; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class HelloWorldController { + + @RequestMapping(path = "/helloworld", method = RequestMethod.GET) + public String HelloWorld() { + return "Hello World!"; + } + +} diff --git a/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/main/resources/application.yml b/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/main/resources/application.yml new file mode 100644 index 0000000000..550165a762 --- /dev/null +++ b/spring-cloud/spring-cloud-zookeeper/HelloWorld/src/main/resources/application.yml @@ -0,0 +1,16 @@ +spring: + application: + name: HelloWorld + cloud: + zookeeper: + connect-string: localhost:2181 + discovery: + enabled: true +server: + port: 8081 +endpoints: + restart: + enabled: true +logging: + level: + org.apache.zookeeper.ClientCnxn: WARN \ No newline at end of file diff --git a/spring-cloud/spring-cloud-zookeeper/pom.xml b/spring-cloud/spring-cloud-zookeeper/pom.xml new file mode 100644 index 0000000000..8406813161 --- /dev/null +++ b/spring-cloud/spring-cloud-zookeeper/pom.xml @@ -0,0 +1,15 @@ + + + 4.0.0 + + com.baeldung.spring.cloud + spring-cloud + 1.0.0-SNAPSHOT + + spring-cloud-zookeeper + pom + + Greeting + HelloWorld + + \ No newline at end of file diff --git a/spring-core/src/main/java/com/baeldung/value/SomeBean.java b/spring-core/src/main/java/com/baeldung/value/SomeBean.java new file mode 100644 index 0000000000..39d5245049 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/value/SomeBean.java @@ -0,0 +1,17 @@ +package com.baeldung.value; + +public class SomeBean { + private int someValue; + + public SomeBean(int someValue) { + this.someValue = someValue; + } + + public int getSomeValue() { + return someValue; + } + + public void setSomeValue(int someValue) { + this.someValue = someValue; + } +} diff --git a/spring-core/src/main/java/com/baeldung/value/ValuesApp.java b/spring-core/src/main/java/com/baeldung/value/ValuesApp.java new file mode 100644 index 0000000000..25f4b9fb9c --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/value/ValuesApp.java @@ -0,0 +1,68 @@ +package com.baeldung.value; + +import java.util.List; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +@Configuration +@PropertySource(name = "myProperties", value = "values.properties") +public class ValuesApp { + + @Value("string value") + private String stringValue; + + @Value("${value.from.file}") + private String valueFromFile; + + @Value("${systemValue}") + private String systemValue; + + @Value("${unknown_param:some default}") + private String someDefault; + + @Value("${priority}") + private String prioritySystemProperty; + + @Value("#{systemProperties['priority']}") + private String spelValue; + + @Value("#{systemProperties['unknown'] ?: 'some default'}") + private String spelSomeDefault; + + @Value("#{someBean.someValue}") + private Integer someBeanValue; + + @Value("#{'${listOfValues}'.split(',')}") + private List valuesList; + + public static void main(String[] args) { + System.setProperty("systemValue", "Some system parameter value"); + System.setProperty("priority", "System property"); + ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ValuesApp.class); + } + + @Bean + public SomeBean someBean() { + return new SomeBean(10); + } + + @PostConstruct + public void afterInitialize() { + System.out.println(stringValue); + System.out.println(valueFromFile); + System.out.println(systemValue); + System.out.println(someDefault); + System.out.println(prioritySystemProperty); + System.out.println(spelValue); + System.out.println(spelSomeDefault); + System.out.println(someBeanValue); + System.out.println(valuesList); + } +} diff --git a/spring-core/src/main/resources/values.properties b/spring-core/src/main/resources/values.properties new file mode 100644 index 0000000000..d7d61b8ee8 --- /dev/null +++ b/spring-core/src/main/resources/values.properties @@ -0,0 +1,3 @@ +value.from.file=Value got from the file +priority=Properties file +listOfValues=A,B,C \ No newline at end of file diff --git a/spring-data-neo4j/pom.xml b/spring-data-neo4j/pom.xml index 96606d597b..7df48498e5 100644 --- a/spring-data-neo4j/pom.xml +++ b/spring-data-neo4j/pom.xml @@ -10,31 +10,31 @@ org.neo4j neo4j - 3.1.0 + ${neo4j.version} org.neo4j neo4j-ogm-core - 2.1.1 + ${neo4j-ogm.version} org.neo4j neo4j-ogm-embedded-driver - 2.1.1 + ${neo4j-ogm.version} org.neo4j.driver neo4j-java-driver - 1.1.1 + ${neo4j-java-driver.version} org.springframework.data spring-data-neo4j - 4.2.0.RELEASE + ${spring-data-neo4j.version} @@ -75,7 +75,7 @@ org.neo4j neo4j-ogm-test - ${neo4j-ogm-test.version} + ${neo4j-ogm.version} test @@ -160,12 +160,13 @@ UTF-8 UTF-8 + 1.1.1 3.1.0 4.1.6.RELEASE 1.1 1.4.3.RELEASE 4.3.5.RELEASE - 2.1.1 + 2.1.1 4.12 diff --git a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jTestConfiguration.java b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jTestConfiguration.java index 7bb1b78a09..fda478e5be 100644 --- a/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jTestConfiguration.java +++ b/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jTestConfiguration.java @@ -5,20 +5,22 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; +import org.springframework.data.neo4j.config.Neo4jConfiguration; import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories; import org.springframework.transaction.annotation.EnableTransactionManagement; +@Configuration @EnableTransactionManagement @ComponentScan(basePackages = { "com.baeldung.spring.data.neo4j.services" }) -@Configuration @EnableNeo4jRepositories(basePackages = "com.baeldung.spring.data.neo4j.repostory") @Profile({ "embedded", "test" }) -public class MovieDatabaseNeo4jTestConfiguration { +public class MovieDatabaseNeo4jTestConfiguration extends Neo4jConfiguration { @Bean public org.neo4j.ogm.config.Configuration getConfiguration() { - org.neo4j.ogm.config.Configuration config = new org.neo4j.ogm.config.Configuration(); - config.driverConfiguration().setDriverClassName("org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver"); + final org.neo4j.ogm.config.Configuration config = new org.neo4j.ogm.config.Configuration(); + config.driverConfiguration() + .setDriverClassName("org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver"); return config; } @@ -26,4 +28,5 @@ public class MovieDatabaseNeo4jTestConfiguration { public SessionFactory getSessionFactory() { return new SessionFactory(getConfiguration(), "com.baeldung.spring.data.neo4j.domain"); } + } diff --git a/spring-data-rest/README.md b/spring-data-rest/README.md index 241f2e3bcf..fa4a264abb 100644 --- a/spring-data-rest/README.md +++ b/spring-data-rest/README.md @@ -17,3 +17,4 @@ To view the running application, visit [http://localhost:8080](http://localhost: - [Guide to Spring Data REST Validators](http://www.baeldung.com/spring-data-rest-validators) - [Working with Relationships in Spring Data REST](http://www.baeldung.com/spring-data-rest-relationships) - [AngularJS CRUD Application with Spring Data REST](http://www.baeldung.com/angularjs-crud-with-spring-data-rest) +- [List of In-Memory Databases](http://www.baeldung.com/java-in-memory-databases) 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-hibernate4/README.md b/spring-hibernate4/README.md index 02888c4ad0..08cfe2b538 100644 --- a/spring-hibernate4/README.md +++ b/spring-hibernate4/README.md @@ -13,6 +13,7 @@ - [Eager/Lazy Loading In Hibernate](http://www.baeldung.com/hibernate-lazy-eager-loading) - [Hibernate Criteria Queries](http://www.baeldung.com/hibernate-criteria-queries) - [Hibernate One to Many Annotation Tutorial](http://www.baeldung.com/hibernate-one-to-many) +- [Guide to @Immutable Annotation in Hibernate](http://www.baeldung.com/hibernate-immutable) ### Quick Start diff --git a/spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java b/spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsIntegrationTest.java similarity index 99% rename from spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java rename to spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsIntegrationTest.java index 2e729c5680..ef83af3a0d 100644 --- a/spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java +++ b/spring-hibernate4/src/test/java/com/baeldung/persistence/save/SaveMethodsIntegrationTest.java @@ -16,7 +16,7 @@ import static org.junit.Assert.*; * Testing specific implementation details for different methods: * persist, save, merge, update, saveOrUpdate. */ -public class SaveMethodsTest { +public class SaveMethodsIntegrationTest { private static SessionFactory sessionFactory; diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java deleted file mode 100644 index 3228f917fd..0000000000 --- a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.baeldung.hibernate.criteria; - -import org.junit.runner.JUnitCore; -import org.junit.runner.Result; -import org.junit.runner.notification.Failure; - -public class HibernateCriteriaTestRunner { - - public static void main(final String[] args) { - Result result = JUnitCore.runClasses(HibernateCriteriaTestSuite.class); - for (Failure failure : result.getFailures()) { - // - } - } -} diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java deleted file mode 100644 index dc1040734f..0000000000 --- a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestSuite.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.hibernate.criteria; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; - -@RunWith(Suite.class) -@Suite.SuiteClasses({ HibernateCriteriaIntegrationTest.class }) - -public class HibernateCriteriaTestSuite { - -} diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodIntegrationTest.java similarity index 94% rename from spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java rename to spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodIntegrationTest.java index d3e90a568a..910cdc597f 100644 --- a/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodIntegrationTest.java @@ -1,14 +1,6 @@ package com.baeldung.persistence.save; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; - -import javax.persistence.PersistenceException; - +import com.baeldung.persistence.model.Person; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; @@ -17,19 +9,17 @@ import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.dialect.HSQLDialect; import org.hibernate.service.ServiceRegistry; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.*; -import com.baeldung.persistence.model.Person; +import javax.persistence.PersistenceException; + +import static org.junit.Assert.*; /** * Testing specific implementation details for different methods: persist, save, * merge, update, saveOrUpdate. */ -public class SaveMethodsTest { +public class SaveMethodIntegrationTest { private static SessionFactory sessionFactory; diff --git a/spring-jersey/pom.xml b/spring-jersey/pom.xml index 41ebb9a6b5..e6c8ea6ef5 100644 --- a/spring-jersey/pom.xml +++ b/spring-jersey/pom.xml @@ -45,6 +45,8 @@ maven-surefire-plugin ${maven-surefire-plugin.version} + 3 + true **/*IntegrationTest.java **/*LiveTest.java diff --git a/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeTestWithoutMockMvc.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeIntegrationTest.java similarity index 97% rename from spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeTestWithoutMockMvc.java rename to spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeIntegrationTest.java index 19806e0559..0c2aa3de1b 100644 --- a/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeTestWithoutMockMvc.java +++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/EmployeeIntegrationTest.java @@ -15,7 +15,7 @@ import com.baeldung.spring.web.config.WebConfig; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = WebConfig.class) -public class EmployeeTestWithoutMockMvc { +public class EmployeeIntegrationTest { @Autowired private EmployeeController employeeController; 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-java/src/test/java/com/baeldung/web/controller/RequestMapingShortcutsUnitTest.java b/spring-mvc-java/src/test/java/com/baeldung/web/controller/RequestMapingShortcutsIntegrationTest.java similarity index 98% rename from spring-mvc-java/src/test/java/com/baeldung/web/controller/RequestMapingShortcutsUnitTest.java rename to spring-mvc-java/src/test/java/com/baeldung/web/controller/RequestMapingShortcutsIntegrationTest.java index d02a7140b5..fb21905027 100644 --- a/spring-mvc-java/src/test/java/com/baeldung/web/controller/RequestMapingShortcutsUnitTest.java +++ b/spring-mvc-java/src/test/java/com/baeldung/web/controller/RequestMapingShortcutsIntegrationTest.java @@ -21,7 +21,7 @@ import com.baeldung.spring.web.config.WebConfig; @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = WebConfig.class) -public class RequestMapingShortcutsUnitTest { +public class RequestMapingShortcutsIntegrationTest { @Autowired private WebApplicationContext ctx; 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-mvc-velocity/pom.xml b/spring-mvc-velocity/pom.xml index 31f2d19375..0a9b3a016e 100644 --- a/spring-mvc-velocity/pom.xml +++ b/spring-mvc-velocity/pom.xml @@ -136,8 +136,9 @@ org.apache.maven.plugins maven-surefire-plugin - ${maven-surefire-plugin.version} + 3 + true **/*IntegrationTest.java 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 ``` diff --git a/spring-security-rest/pom.xml b/spring-security-rest/pom.xml index 320e84fa7a..996161c721 100644 --- a/spring-security-rest/pom.xml +++ b/spring-security-rest/pom.xml @@ -259,10 +259,10 @@ org.apache.maven.plugins maven-surefire-plugin - ${maven-surefire-plugin.version} **/*LiveTest.java + **/*IntegrationTest.java diff --git a/spring-security-rest/src/test/java/org/baeldung/web/AsyncControllerTest.java b/spring-security-rest/src/test/java/org/baeldung/web/AsyncControllerIntegrationTest.java similarity index 97% rename from spring-security-rest/src/test/java/org/baeldung/web/AsyncControllerTest.java rename to spring-security-rest/src/test/java/org/baeldung/web/AsyncControllerIntegrationTest.java index 9cd92880a7..a09c225a4a 100644 --- a/spring-security-rest/src/test/java/org/baeldung/web/AsyncControllerTest.java +++ b/spring-security-rest/src/test/java/org/baeldung/web/AsyncControllerIntegrationTest.java @@ -1,7 +1,5 @@ package org.baeldung.web; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - import org.baeldung.spring.ClientWebConfig; import org.baeldung.spring.SecurityJavaConfig; import org.baeldung.spring.WebConfig; @@ -20,10 +18,12 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + @RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = { ClientWebConfig.class, SecurityJavaConfig.class, WebConfig.class }) -public class AsyncControllerTest { +public class AsyncControllerIntegrationTest { @Autowired WebApplicationContext wac; diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineIntegrationTest.java similarity index 97% rename from spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineTest.java rename to spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineIntegrationTest.java index a9aca82a6e..b34d5c47c6 100644 --- a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineTest.java +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/ForkJoinStateMachineIntegrationTest.java @@ -20,7 +20,7 @@ import static org.junit.Assert.assertTrue; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = ForkJoinStateMachineConfiguration.class) -public class ForkJoinStateMachineTest { +public class ForkJoinStateMachineIntegrationTest { @Autowired private StateMachine stateMachine; diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineIntegrationTest.java similarity index 96% rename from spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineTest.java rename to spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineIntegrationTest.java index a2fa4f9160..3d7c0be828 100644 --- a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineTest.java +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/HierarchicalStateMachineIntegrationTest.java @@ -19,7 +19,7 @@ import static org.junit.Assert.assertEquals; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = HierarchicalStateMachineConfiguration.class) -public class HierarchicalStateMachineTest { +public class HierarchicalStateMachineIntegrationTest { @Autowired private StateMachine stateMachine; diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineIntegrationTest.java similarity index 96% rename from spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineTest.java rename to spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineIntegrationTest.java index 2b5130ab45..93de23fad3 100644 --- a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineTest.java +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/JunctionStateMachineIntegrationTest.java @@ -17,7 +17,7 @@ import javax.annotation.Resource; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = JunctionStateMachineConfiguration.class) -public class JunctionStateMachineTest { +public class JunctionStateMachineIntegrationTest { @Autowired private StateMachine stateMachine; diff --git a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineTest.java b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineIntegrationTest.java similarity index 97% rename from spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineTest.java rename to spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineIntegrationTest.java index 19f24ede2d..9074ece001 100644 --- a/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineTest.java +++ b/spring-state-machine/src/test/java/com/baeldung/spring/statemachine/StateEnumMachineIntegrationTest.java @@ -21,7 +21,7 @@ import static org.junit.Assert.assertTrue; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SimpleEnumStateMachineConfiguration.class) -public class StateEnumMachineTest { +public class StateEnumMachineIntegrationTest { @Autowired private StateMachine stateMachine; diff --git a/spring-thymeleaf/pom.xml b/spring-thymeleaf/pom.xml index f5dfc9931e..be443e15df 100644 --- a/spring-thymeleaf/pom.xml +++ b/spring-thymeleaf/pom.xml @@ -176,6 +176,8 @@ maven-surefire-plugin ${maven-surefire-plugin.version} + 3 + true **/*IntegrationTest.java **/*LiveTest.java diff --git a/spring-userservice/pom.xml b/spring-userservice/pom.xml index c0099173ee..0f3ed96c4e 100644 --- a/spring-userservice/pom.xml +++ b/spring-userservice/pom.xml @@ -239,6 +239,9 @@ maven-surefire-plugin ${maven-surefire-plugin.version} + 3 + true + **/*IntegrationTest.java