diff --git a/.travis.yml b/.travis.yml index c2a369a1b3..6063fbf3e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ install: travis_wait 40 mvn -q clean install -Dgib.enabled=true jdk: - oraclejdk8 -sudo: false addons: apt: packages: @@ -14,4 +13,11 @@ addons: cache: directories: - .autoconf - - $HOME/.m2 \ No newline at end of file + - $HOME/.m2 + + sudo: required + + env: + global: + JAVA_OPTS="-Xmx2048M -Xss128M -XX:MaxPermSize=2048M -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC" + MAVEN_OPTS="-Xmx2048M -Xss128M -XX:MaxPermSize=2048M -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC" diff --git a/Twitter4J/README.md b/Twitter4J/README.md new file mode 100644 index 0000000000..3057c1c4b2 --- /dev/null +++ b/Twitter4J/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [Introduction to Twitter4J](http://www.baeldung.com/twitter4j) diff --git a/Twitter4J/pom.xml b/Twitter4J/pom.xml index ebe5a7d409..7e41d8de76 100644 --- a/Twitter4J/pom.xml +++ b/Twitter4J/pom.xml @@ -17,11 +17,6 @@ - - org.twitter4j - twitter4j-core - 4.0.6 - org.twitter4j twitter4j-stream diff --git a/Twitter4J/src/main/java/com/baeldung/Application.java b/Twitter4J/src/main/java/com/baeldung/Application.java index f7da27db29..3f961ccb4f 100644 --- a/Twitter4J/src/main/java/com/baeldung/Application.java +++ b/Twitter4J/src/main/java/com/baeldung/Application.java @@ -28,11 +28,10 @@ public class Application { */ // ConfigurationBuilder cb = new ConfigurationBuilder(); // cb.setDebugEnabled(true) -// .setOAuthConsumerKey("DPHTBsWWO42d8rzshxlK0OwSY") -// .setOAuthConsumerSecret("ACLXkeRY98NiaVCG1ai8fdYt0GoEGJbFeTuxjulSCO7sLKqls1") -// .setOAuthAccessToken("838080188214759428-9MSK1ddPTN5ZZHbddjFI7s75mYgmCFQ") -// .setOAuthAccessTokenSecret("1eXAADpHShAzQh5hGWLBUQHLysOuAKIOapmQQ8U0OVk2c"); -// +// .setOAuthConsumerKey("//TODO") +// .setOAuthConsumerSecret("//TODO") +// .setOAuthAccessToken("//TODO") +// .setOAuthAccessTokenSecret("//TODO"); // TwitterFactory tf = new TwitterFactory(cb.build()); // Twitter twitter = tf.getSingleton(); diff --git a/algorithms/README.md b/algorithms/README.md index 42f696d9be..a0e10246e0 100644 --- a/algorithms/README.md +++ b/algorithms/README.md @@ -2,3 +2,5 @@ - [Dijkstra Algorithm in Java](http://www.baeldung.com/java-dijkstra) - [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) diff --git a/algorithms/pom.xml b/algorithms/pom.xml index f72457650a..46a2b9d897 100644 --- a/algorithms/pom.xml +++ b/algorithms/pom.xml @@ -9,6 +9,7 @@ 4.12 3.6.0 1.5.0 + 1.16.12 @@ -18,6 +19,12 @@ ${junit.version} test + + org.projectlombok + lombok + ${lombok.version} + provided + diff --git a/core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java b/algorithms/src/main/java/com/baeldung/algorithms/RunAlgorithm.java similarity index 84% rename from core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java rename to algorithms/src/main/java/com/baeldung/algorithms/RunAlgorithm.java index 22c5776293..6ab7dbb4e5 100644 --- a/core-java/src/main/java/com/baeldung/algorithms/RunAlgorithm.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/RunAlgorithm.java @@ -9,13 +9,14 @@ import com.baeldung.algorithms.slope_one.SlopeOne; public class RunAlgorithm { - public static void main(String[] args) { + public static void main(String[] args) throws InstantiationException, IllegalAccessException { Scanner in = new Scanner(System.in); System.out.println("Run algorithm:"); System.out.println("1 - Simulated Annealing"); System.out.println("2 - Slope One"); System.out.println("3 - Simple Genetic Algorithm"); System.out.println("4 - Ant Colony"); + System.out.println("5 - Dijkstra"); int decision = in.nextInt(); switch (decision) { case 1: @@ -33,6 +34,9 @@ public class RunAlgorithm { AntColonyOptimization antColony = new AntColonyOptimization(21); antColony.startAntOptimization(); break; + case 5: + System.out.println("Please run the DijkstraAlgorithmTest."); + break; default: System.out.println("Unknown option"); break; diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/City.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/annealing/City.java similarity index 100% rename from core-java/src/main/java/com/baeldung/algorithms/ga/annealing/City.java rename to algorithms/src/main/java/com/baeldung/algorithms/ga/annealing/City.java diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/SimulatedAnnealing.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/annealing/SimulatedAnnealing.java similarity index 100% rename from core-java/src/main/java/com/baeldung/algorithms/ga/annealing/SimulatedAnnealing.java rename to algorithms/src/main/java/com/baeldung/algorithms/ga/annealing/SimulatedAnnealing.java diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/annealing/Travel.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/annealing/Travel.java similarity index 100% rename from core-java/src/main/java/com/baeldung/algorithms/ga/annealing/Travel.java rename to algorithms/src/main/java/com/baeldung/algorithms/ga/annealing/Travel.java diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/Ant.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/ant_colony/Ant.java similarity index 100% rename from core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/Ant.java rename to algorithms/src/main/java/com/baeldung/algorithms/ga/ant_colony/Ant.java diff --git a/algorithms/src/main/java/com/baeldung/algorithms/ga/ant_colony/AntColonyOptimization.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/ant_colony/AntColonyOptimization.java new file mode 100644 index 0000000000..62e124d3f3 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/ga/ant_colony/AntColonyOptimization.java @@ -0,0 +1,203 @@ +package com.baeldung.algorithms.ga.ant_colony; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.OptionalInt; +import java.util.Random; +import java.util.stream.IntStream; + +public class AntColonyOptimization { + + private double c = 1.0; + private double alpha = 1; + private double beta = 5; + private double evaporation = 0.5; + private double Q = 500; + private double antFactor = 0.8; + private double randomFactor = 0.01; + + private int maxIterations = 1000; + + private int numberOfCities; + private int numberOfAnts; + private double graph[][]; + private double trails[][]; + private List ants = new ArrayList<>(); + private Random random = new Random(); + private double probabilities[]; + + private int currentIndex; + + private int[] bestTourOrder; + private double bestTourLength; + + public AntColonyOptimization(int noOfCities) { + graph = generateRandomMatrix(noOfCities); + numberOfCities = graph.length; + numberOfAnts = (int) (numberOfCities * antFactor); + + trails = new double[numberOfCities][numberOfCities]; + probabilities = new double[numberOfCities]; + IntStream.range(0, numberOfAnts) + .forEach(i -> ants.add(new Ant(numberOfCities))); + } + + /** + * Generate initial solution + */ + public double[][] generateRandomMatrix(int n) { + double[][] randomMatrix = new double[n][n]; + IntStream.range(0, n) + .forEach(i -> IntStream.range(0, n) + .forEach(j -> randomMatrix[i][j] = Math.abs(random.nextInt(100) + 1))); + return randomMatrix; + } + + /** + * Perform ant optimization + */ + public void startAntOptimization() { + IntStream.rangeClosed(1, 3) + .forEach(i -> { + System.out.println("Attempt #" + i); + solve(); + }); + } + + /** + * Use this method to run the main logic + */ + public int[] solve() { + setupAnts(); + clearTrails(); + IntStream.range(0, maxIterations) + .forEach(i -> { + moveAnts(); + updateTrails(); + updateBest(); + }); + System.out.println("Best tour length: " + (bestTourLength - numberOfCities)); + System.out.println("Best tour order: " + Arrays.toString(bestTourOrder)); + return bestTourOrder.clone(); + } + + /** + * Prepare ants for the simulation + */ + private void setupAnts() { + IntStream.range(0, numberOfAnts) + .forEach(i -> { + ants.forEach(ant -> { + ant.clear(); + ant.visitCity(-1, random.nextInt(numberOfCities)); + }); + }); + currentIndex = 0; + } + + /** + * At each iteration, move ants + */ + private void moveAnts() { + IntStream.range(currentIndex, numberOfCities - 1) + .forEach(i -> { + ants.forEach(ant -> ant.visitCity(currentIndex, selectNextCity(ant))); + currentIndex++; + }); + } + + /** + * Select next city for each ant + */ + private int selectNextCity(Ant ant) { + int t = random.nextInt(numberOfCities - currentIndex); + if (random.nextDouble() < randomFactor) { + OptionalInt cityIndex = IntStream.range(0, numberOfCities) + .filter(i -> i == t && !ant.visited(i)) + .findFirst(); + if (cityIndex.isPresent()) { + return cityIndex.getAsInt(); + } + } + calculateProbabilities(ant); + double r = random.nextDouble(); + double total = 0; + for (int i = 0; i < numberOfCities; i++) { + total += probabilities[i]; + if (total >= r) { + return i; + } + } + + throw new RuntimeException("There are no other cities"); + } + + /** + * Calculate the next city picks probabilites + */ + public void calculateProbabilities(Ant ant) { + int i = ant.trail[currentIndex]; + double pheromone = 0.0; + for (int l = 0; l < numberOfCities; l++) { + if (!ant.visited(l)) { + pheromone += Math.pow(trails[i][l], alpha) * Math.pow(1.0 / graph[i][l], beta); + } + } + for (int j = 0; j < numberOfCities; j++) { + if (ant.visited(j)) { + probabilities[j] = 0.0; + } else { + double numerator = Math.pow(trails[i][j], alpha) * Math.pow(1.0 / graph[i][j], beta); + probabilities[j] = numerator / pheromone; + } + } + } + + /** + * Update trails that ants used + */ + private void updateTrails() { + for (int i = 0; i < numberOfCities; i++) { + for (int j = 0; j < numberOfCities; j++) { + trails[i][j] *= evaporation; + } + } + for (Ant a : ants) { + double contribution = Q / a.trailLength(graph); + for (int i = 0; i < numberOfCities - 1; i++) { + trails[a.trail[i]][a.trail[i + 1]] += contribution; + } + trails[a.trail[numberOfCities - 1]][a.trail[0]] += contribution; + } + } + + /** + * Update the best solution + */ + private void updateBest() { + if (bestTourOrder == null) { + bestTourOrder = ants.get(0).trail; + bestTourLength = ants.get(0) + .trailLength(graph); + } + for (Ant a : ants) { + if (a.trailLength(graph) < bestTourLength) { + bestTourLength = a.trailLength(graph); + bestTourOrder = a.trail.clone(); + } + } + } + + /** + * Clear trails after simulation + */ + private void clearTrails() { + IntStream.range(0, numberOfCities) + .forEach(i -> { + IntStream.range(0, numberOfCities) + .forEach(j -> trails[i][j] = c); + }); + } + +} diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/binary/Individual.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/binary/Individual.java similarity index 100% rename from core-java/src/main/java/com/baeldung/algorithms/ga/binary/Individual.java rename to algorithms/src/main/java/com/baeldung/algorithms/ga/binary/Individual.java diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/binary/Population.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/binary/Population.java similarity index 100% rename from core-java/src/main/java/com/baeldung/algorithms/ga/binary/Population.java rename to algorithms/src/main/java/com/baeldung/algorithms/ga/binary/Population.java diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/binary/SimpleGeneticAlgorithm.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/binary/SimpleGeneticAlgorithm.java similarity index 100% rename from core-java/src/main/java/com/baeldung/algorithms/ga/binary/SimpleGeneticAlgorithm.java rename to algorithms/src/main/java/com/baeldung/algorithms/ga/binary/SimpleGeneticAlgorithm.java diff --git a/algorithms/src/main/java/com/baeldung/algorithms/dijkstra/Dijkstra.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/dijkstra/Dijkstra.java similarity index 95% rename from algorithms/src/main/java/com/baeldung/algorithms/dijkstra/Dijkstra.java rename to algorithms/src/main/java/com/baeldung/algorithms/ga/dijkstra/Dijkstra.java index 1d41f46adb..0b01e9b48b 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/dijkstra/Dijkstra.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/ga/dijkstra/Dijkstra.java @@ -1,57 +1,57 @@ -package com.baeldung.algorithms.dijkstra; - -import java.util.HashSet; -import java.util.LinkedList; -import java.util.Map.Entry; -import java.util.Set; - -public class Dijkstra { - - public static Graph calculateShortestPathFromSource(Graph graph, Node source) { - - source.setDistance(0); - - Set settledNodes = new HashSet<>(); - Set unsettledNodes = new HashSet<>(); - unsettledNodes.add(source); - - while (unsettledNodes.size() != 0) { - Node currentNode = getLowestDistanceNode(unsettledNodes); - unsettledNodes.remove(currentNode); - for (Entry adjacencyPair : currentNode.getAdjacentNodes().entrySet()) { - Node adjacentNode = adjacencyPair.getKey(); - Integer edgeWeigh = adjacencyPair.getValue(); - - if (!settledNodes.contains(adjacentNode)) { - CalculateMinimumDistance(adjacentNode, edgeWeigh, currentNode); - unsettledNodes.add(adjacentNode); - } - } - settledNodes.add(currentNode); - } - return graph; - } - - private static void CalculateMinimumDistance(Node evaluationNode, Integer edgeWeigh, Node sourceNode) { - Integer sourceDistance = sourceNode.getDistance(); - if (sourceDistance + edgeWeigh < evaluationNode.getDistance()) { - evaluationNode.setDistance(sourceDistance + edgeWeigh); - LinkedList shortestPath = new LinkedList<>(sourceNode.getShortestPath()); - shortestPath.add(sourceNode); - evaluationNode.setShortestPath(shortestPath); - } - } - - private static Node getLowestDistanceNode(Set unsettledNodes) { - Node lowestDistanceNode = null; - int lowestDistance = Integer.MAX_VALUE; - for (Node node : unsettledNodes) { - int nodeDistance = node.getDistance(); - if (nodeDistance < lowestDistance) { - lowestDistance = nodeDistance; - lowestDistanceNode = node; - } - } - return lowestDistanceNode; - } -} +package com.baeldung.algorithms.ga.dijkstra; + +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map.Entry; +import java.util.Set; + +public class Dijkstra { + + public static Graph calculateShortestPathFromSource(Graph graph, Node source) { + + source.setDistance(0); + + Set settledNodes = new HashSet<>(); + Set unsettledNodes = new HashSet<>(); + unsettledNodes.add(source); + + while (unsettledNodes.size() != 0) { + Node currentNode = getLowestDistanceNode(unsettledNodes); + unsettledNodes.remove(currentNode); + for (Entry adjacencyPair : currentNode.getAdjacentNodes().entrySet()) { + Node adjacentNode = adjacencyPair.getKey(); + Integer edgeWeigh = adjacencyPair.getValue(); + + if (!settledNodes.contains(adjacentNode)) { + CalculateMinimumDistance(adjacentNode, edgeWeigh, currentNode); + unsettledNodes.add(adjacentNode); + } + } + settledNodes.add(currentNode); + } + return graph; + } + + private static void CalculateMinimumDistance(Node evaluationNode, Integer edgeWeigh, Node sourceNode) { + Integer sourceDistance = sourceNode.getDistance(); + if (sourceDistance + edgeWeigh < evaluationNode.getDistance()) { + evaluationNode.setDistance(sourceDistance + edgeWeigh); + LinkedList shortestPath = new LinkedList<>(sourceNode.getShortestPath()); + shortestPath.add(sourceNode); + evaluationNode.setShortestPath(shortestPath); + } + } + + private static Node getLowestDistanceNode(Set unsettledNodes) { + Node lowestDistanceNode = null; + int lowestDistance = Integer.MAX_VALUE; + for (Node node : unsettledNodes) { + int nodeDistance = node.getDistance(); + if (nodeDistance < lowestDistance) { + lowestDistance = nodeDistance; + lowestDistanceNode = node; + } + } + return lowestDistanceNode; + } +} diff --git a/algorithms/src/main/java/com/baeldung/algorithms/dijkstra/Graph.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/dijkstra/Graph.java similarity index 84% rename from algorithms/src/main/java/com/baeldung/algorithms/dijkstra/Graph.java rename to algorithms/src/main/java/com/baeldung/algorithms/ga/dijkstra/Graph.java index f24d6ae60e..76694ed76e 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/dijkstra/Graph.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/ga/dijkstra/Graph.java @@ -1,21 +1,21 @@ -package com.baeldung.algorithms.dijkstra; - -import java.util.HashSet; -import java.util.Set; - -public class Graph { - - private Set nodes = new HashSet<>(); - - public void addNode(Node nodeA) { - nodes.add(nodeA); - } - - public Set getNodes() { - return nodes; - } - - public void setNodes(Set nodes) { - this.nodes = nodes; - } -} +package com.baeldung.algorithms.ga.dijkstra; + +import java.util.HashSet; +import java.util.Set; + +public class Graph { + + private Set nodes = new HashSet<>(); + + public void addNode(Node nodeA) { + nodes.add(nodeA); + } + + public Set getNodes() { + return nodes; + } + + public void setNodes(Set nodes) { + this.nodes = nodes; + } +} diff --git a/algorithms/src/main/java/com/baeldung/algorithms/dijkstra/Node.java b/algorithms/src/main/java/com/baeldung/algorithms/ga/dijkstra/Node.java similarity index 92% rename from algorithms/src/main/java/com/baeldung/algorithms/dijkstra/Node.java rename to algorithms/src/main/java/com/baeldung/algorithms/ga/dijkstra/Node.java index b00127a259..ac34bfadd1 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/dijkstra/Node.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/ga/dijkstra/Node.java @@ -1,58 +1,58 @@ -package com.baeldung.algorithms.dijkstra; - -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -public class Node { - - private String name; - - private LinkedList shortestPath = new LinkedList<>(); - - private Integer distance = Integer.MAX_VALUE; - - private Map adjacentNodes = new HashMap<>(); - - public Node(String name) { - this.name = name; - } - - public void addDestination(Node destination, int distance) { - adjacentNodes.put(destination, distance); - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public Map getAdjacentNodes() { - return adjacentNodes; - } - - public void setAdjacentNodes(Map adjacentNodes) { - this.adjacentNodes = adjacentNodes; - } - - public Integer getDistance() { - return distance; - } - - public void setDistance(Integer distance) { - this.distance = distance; - } - - public List getShortestPath() { - return shortestPath; - } - - public void setShortestPath(LinkedList shortestPath) { - this.shortestPath = shortestPath; - } - -} +package com.baeldung.algorithms.ga.dijkstra; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class Node { + + private String name; + + private LinkedList shortestPath = new LinkedList<>(); + + private Integer distance = Integer.MAX_VALUE; + + private Map adjacentNodes = new HashMap<>(); + + public Node(String name) { + this.name = name; + } + + public void addDestination(Node destination, int distance) { + adjacentNodes.put(destination, distance); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Map getAdjacentNodes() { + return adjacentNodes; + } + + public void setAdjacentNodes(Map adjacentNodes) { + this.adjacentNodes = adjacentNodes; + } + + public Integer getDistance() { + return distance; + } + + public void setDistance(Integer distance) { + this.distance = distance; + } + + public List getShortestPath() { + return shortestPath; + } + + public void setShortestPath(LinkedList shortestPath) { + this.shortestPath = shortestPath; + } + +} diff --git a/core-java/src/main/java/com/baeldung/algorithms/slope_one/InputData.java b/algorithms/src/main/java/com/baeldung/algorithms/slope_one/InputData.java similarity index 100% rename from core-java/src/main/java/com/baeldung/algorithms/slope_one/InputData.java rename to algorithms/src/main/java/com/baeldung/algorithms/slope_one/InputData.java diff --git a/core-java/src/main/java/com/baeldung/algorithms/slope_one/Item.java b/algorithms/src/main/java/com/baeldung/algorithms/slope_one/Item.java similarity index 100% rename from core-java/src/main/java/com/baeldung/algorithms/slope_one/Item.java rename to algorithms/src/main/java/com/baeldung/algorithms/slope_one/Item.java diff --git a/core-java/src/main/java/com/baeldung/algorithms/slope_one/SlopeOne.java b/algorithms/src/main/java/com/baeldung/algorithms/slope_one/SlopeOne.java similarity index 100% rename from core-java/src/main/java/com/baeldung/algorithms/slope_one/SlopeOne.java rename to algorithms/src/main/java/com/baeldung/algorithms/slope_one/SlopeOne.java diff --git a/core-java/src/main/java/com/baeldung/algorithms/slope_one/User.java b/algorithms/src/main/java/com/baeldung/algorithms/slope_one/User.java similarity index 100% rename from core-java/src/main/java/com/baeldung/algorithms/slope_one/User.java rename to algorithms/src/main/java/com/baeldung/algorithms/slope_one/User.java diff --git a/algorithms/src/main/java/com/baeldung/automata/FiniteStateMachine.java b/algorithms/src/main/java/com/baeldung/automata/FiniteStateMachine.java new file mode 100644 index 0000000000..943b44fe05 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/automata/FiniteStateMachine.java @@ -0,0 +1,20 @@ +package com.baeldung.automata; + +/** + * Finite state machine. + */ +public interface FiniteStateMachine { + + /** + * Follow a transition, switch the state of the machine. + * @param c Char. + * @return A new finite state machine with the new state. + */ + FiniteStateMachine switchState(final CharSequence c); + + /** + * Is the current state a final one? + * @return true or false. + */ + boolean canStop(); +} diff --git a/algorithms/src/main/java/com/baeldung/automata/RtFiniteStateMachine.java b/algorithms/src/main/java/com/baeldung/automata/RtFiniteStateMachine.java new file mode 100644 index 0000000000..090e00c73c --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/automata/RtFiniteStateMachine.java @@ -0,0 +1,30 @@ +package com.baeldung.automata; + +/** + * Default implementation of a finite state machine. + * This class is immutable and thread-safe. + */ +public final class RtFiniteStateMachine implements FiniteStateMachine { + + /** + * Current state. + */ + private State current; + + /** + * Ctor. + * @param initial Initial state of this machine. + */ + public RtFiniteStateMachine(final State initial) { + this.current = initial; + } + + public FiniteStateMachine switchState(final CharSequence c) { + return new RtFiniteStateMachine(this.current.transit(c)); + } + + public boolean canStop() { + return this.current.isFinal(); + } + +} diff --git a/algorithms/src/main/java/com/baeldung/automata/RtState.java b/algorithms/src/main/java/com/baeldung/automata/RtState.java new file mode 100644 index 0000000000..ba785eeff0 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/automata/RtState.java @@ -0,0 +1,42 @@ +package com.baeldung.automata; + +import java.util.ArrayList; +import java.util.List; + +/** + * State in a finite state machine. + */ +public final class RtState implements State { + + private List transitions; + private boolean isFinal; + + public RtState() { + this(false); + } + + public RtState(final boolean isFinal) { + this.transitions = new ArrayList<>(); + this.isFinal = isFinal; + } + + public State transit(final CharSequence c) { + for(final Transition t : this.transitions) { + if(t.isPossible(c)) { + return t.state(); + } + } + throw new IllegalArgumentException("Input not accepted: " + c); + } + + public boolean isFinal() { + return this.isFinal; + } + + @Override + public State with(Transition tr) { + this.transitions.add(tr); + return this; + } + +} diff --git a/algorithms/src/main/java/com/baeldung/automata/RtTransition.java b/algorithms/src/main/java/com/baeldung/automata/RtTransition.java new file mode 100644 index 0000000000..560011e42a --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/automata/RtTransition.java @@ -0,0 +1,31 @@ +package com.baeldung.automata; + + +/** + * Transition in finite state machine. + */ +public final class RtTransition implements Transition { + + private String rule; + private State next; + + /** + * Ctor. + * @param rule Rule that a character has to meet + * in order to get to the next state. + * @param next Next state. + */ + public RtTransition (String rule, State next) { + this.rule = rule; + this.next = next; + } + + public State state() { + return this.next; + } + + public boolean isPossible(CharSequence c) { + return this.rule.equalsIgnoreCase(String.valueOf(c)); + } + +} diff --git a/algorithms/src/main/java/com/baeldung/automata/State.java b/algorithms/src/main/java/com/baeldung/automata/State.java new file mode 100644 index 0000000000..a25af9d03a --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/automata/State.java @@ -0,0 +1,29 @@ +package com.baeldung.automata; + +/** + * State. Part of a finite state machine. + */ +public interface State { + + /** + * Add a Transition to this state. + * @param tr Given transition. + * @return Modified State. + */ + State with(final Transition tr); + + /** + * Follow one of the transitions, to get + * to the next state. + * @param c Character. + * @return State. + * @throws IllegalStateException if the char is not accepted. + */ + State transit(final CharSequence c); + + /** + * Can the automaton stop on this state? + * @return true or false + */ + boolean isFinal(); +} diff --git a/algorithms/src/main/java/com/baeldung/automata/Transition.java b/algorithms/src/main/java/com/baeldung/automata/Transition.java new file mode 100644 index 0000000000..d57620f911 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/automata/Transition.java @@ -0,0 +1,20 @@ +package com.baeldung.automata; + +/** + * Transition in a finite State machine. + */ +public interface Transition { + + /** + * Is the transition possible with the given character? + * @param c char. + * @return true or false. + */ + boolean isPossible(final CharSequence c); + + /** + * The state to which this transition leads. + * @return State. + */ + State state(); +} diff --git a/core-java/src/test/java/com/baeldung/algorithms/AntColonyOptimizationTest.java b/algorithms/src/test/java/algorithms/AntColonyOptimizationTest.java similarity index 93% rename from core-java/src/test/java/com/baeldung/algorithms/AntColonyOptimizationTest.java rename to algorithms/src/test/java/algorithms/AntColonyOptimizationTest.java index 40d2464ab6..a11f5db698 100644 --- a/core-java/src/test/java/com/baeldung/algorithms/AntColonyOptimizationTest.java +++ b/algorithms/src/test/java/algorithms/AntColonyOptimizationTest.java @@ -1,4 +1,4 @@ -package com.baeldung.algorithms; +package algorithms; import org.junit.Assert; import org.junit.Test; diff --git a/core-java/src/test/java/com/baeldung/algorithms/BinaryGeneticAlgorithmUnitTest.java b/algorithms/src/test/java/algorithms/BinaryGeneticAlgorithmUnitTest.java similarity index 91% rename from core-java/src/test/java/com/baeldung/algorithms/BinaryGeneticAlgorithmUnitTest.java rename to algorithms/src/test/java/algorithms/BinaryGeneticAlgorithmUnitTest.java index 2e92177c8c..2ba516d310 100644 --- a/core-java/src/test/java/com/baeldung/algorithms/BinaryGeneticAlgorithmUnitTest.java +++ b/algorithms/src/test/java/algorithms/BinaryGeneticAlgorithmUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.algorithms; +package algorithms; import org.junit.Assert; import org.junit.Test; diff --git a/algorithms/src/test/java/algorithms/DijkstraAlgorithmTest.java b/algorithms/src/test/java/algorithms/DijkstraAlgorithmTest.java index 07606bde4b..4d8cebed25 100644 --- a/algorithms/src/test/java/algorithms/DijkstraAlgorithmTest.java +++ b/algorithms/src/test/java/algorithms/DijkstraAlgorithmTest.java @@ -1,10 +1,11 @@ package algorithms; -import com.baeldung.algorithms.dijkstra.Dijkstra; -import com.baeldung.algorithms.dijkstra.Graph; -import com.baeldung.algorithms.dijkstra.Node; import org.junit.Test; +import com.baeldung.algorithms.ga.dijkstra.Dijkstra; +import com.baeldung.algorithms.ga.dijkstra.Graph; +import com.baeldung.algorithms.ga.dijkstra.Node; + import java.util.Arrays; import java.util.List; diff --git a/algorithms/src/test/java/algorithms/RtFiniteStateMachineTest.java b/algorithms/src/test/java/algorithms/RtFiniteStateMachineTest.java new file mode 100644 index 0000000000..089b38ec3f --- /dev/null +++ b/algorithms/src/test/java/algorithms/RtFiniteStateMachineTest.java @@ -0,0 +1,82 @@ +package algorithms; + +import static org.junit.Assert.*; +import org.junit.Test; +import com.baeldung.automata.*; + +/** + * Tests for {@link RtFiniteStateMachine} + */ +public final class RtFiniteStateMachineTest { + + @Test + public void acceptsSimplePair() { + String json = "{\"key\":\"value\"}"; + FiniteStateMachine machine = this.buildJsonStateMachine(); + for (int i=0;i - 4.0.0 - com.baeldung - apache-commons - 0.0.1-SNAPSHOT - - 4.12 - 3.6.0 - - - - - maven-compiler-plugin - ${compiler.version} - - 1.8 - 1.8 - - - - - - - org.apache.commons - commons-lang3 - 3.5 - - - junit - junit - ${junit.version} - test - - - \ No newline at end of file diff --git a/apache-poi/temp.xlsx b/apache-poi/temp.xlsx index 5281b2c4de..50307a28c2 100644 Binary files a/apache-poi/temp.xlsx and b/apache-poi/temp.xlsx differ diff --git a/aws/README.md b/aws/README.md new file mode 100644 index 0000000000..10db004765 --- /dev/null +++ b/aws/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [AWS Lambda Using DynamoDB With Java](http://www.baeldung.com/aws-lambda-dynamodb-java) diff --git a/axon/README.md b/axon/README.md new file mode 100644 index 0000000000..f1ae5d00d8 --- /dev/null +++ b/axon/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [A Guide to the Axon Framework](http://www.baeldung.com/axon-cqrs-event-sourcing) diff --git a/axon/pom.xml b/axon/pom.xml new file mode 100644 index 0000000000..2bffa53bb8 --- /dev/null +++ b/axon/pom.xml @@ -0,0 +1,52 @@ + + + + parent-modules + com.baeldung + 1.0.0-SNAPSHOT + + 4.0.0 + + axon + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + + org.axonframework + axon-test + ${axon.version} + test + + + org.axonframework + axon-core + ${axon.version} + + + junit + junit + ${junit.version} + test + + + + + 3.0.2 + 4.12 + + + + \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/MessagesRunner.java b/axon/src/main/java/com/baeldung/axon/MessagesRunner.java new file mode 100644 index 0000000000..77b50d09bd --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/MessagesRunner.java @@ -0,0 +1,54 @@ +package com.baeldung.axon; + +import com.baeldung.axon.aggregates.MessagesAggregate; +import com.baeldung.axon.commands.CreateMessageCommand; +import com.baeldung.axon.commands.MarkReadMessageCommand; +import com.baeldung.axon.eventhandlers.MessagesEventHandler; +import org.axonframework.commandhandling.AggregateAnnotationCommandHandler; +import org.axonframework.commandhandling.CommandBus; +import org.axonframework.commandhandling.SimpleCommandBus; +import org.axonframework.commandhandling.gateway.CommandGateway; +import org.axonframework.commandhandling.gateway.DefaultCommandGateway; +import org.axonframework.eventhandling.AnnotationEventListenerAdapter; +import org.axonframework.eventsourcing.EventSourcingRepository; +import org.axonframework.eventsourcing.eventstore.EmbeddedEventStore; +import org.axonframework.eventsourcing.eventstore.EventStore; +import org.axonframework.eventsourcing.eventstore.inmemory.InMemoryEventStorageEngine; + +import java.util.UUID; + +public class MessagesRunner { + + public static void main(String[] args) { + CommandBus commandBus = new SimpleCommandBus(); + + CommandGateway commandGateway = new DefaultCommandGateway(commandBus); + + EventStore eventStore = new EmbeddedEventStore(new InMemoryEventStorageEngine()); + + EventSourcingRepository repository = + new EventSourcingRepository<>(MessagesAggregate.class, eventStore); + + + AggregateAnnotationCommandHandler messagesAggregateAggregateAnnotationCommandHandler = + new AggregateAnnotationCommandHandler(MessagesAggregate.class, repository); + messagesAggregateAggregateAnnotationCommandHandler.subscribe(commandBus); + + final AnnotationEventListenerAdapter annotationEventListenerAdapter = + new AnnotationEventListenerAdapter(new MessagesEventHandler()); + eventStore.subscribe(eventMessages -> eventMessages.forEach(e -> { + try { + annotationEventListenerAdapter.handle(e); + } catch (Exception e1) { + throw new RuntimeException(e1); + + } + } + + )); + + final String itemId = UUID.randomUUID().toString(); + commandGateway.send(new CreateMessageCommand(itemId, "Hello, how is your day? :-)")); + commandGateway.send(new MarkReadMessageCommand(itemId)); + } +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/aggregates/MessagesAggregate.java b/axon/src/main/java/com/baeldung/axon/aggregates/MessagesAggregate.java new file mode 100644 index 0000000000..e762604b74 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/aggregates/MessagesAggregate.java @@ -0,0 +1,36 @@ +package com.baeldung.axon.aggregates; + +import com.baeldung.axon.commands.CreateMessageCommand; +import com.baeldung.axon.commands.MarkReadMessageCommand; +import com.baeldung.axon.events.MessageCreatedEvent; +import com.baeldung.axon.events.MessageReadEvent; +import org.axonframework.commandhandling.CommandHandler; +import org.axonframework.commandhandling.model.AggregateIdentifier; +import org.axonframework.eventhandling.EventHandler; + +import static org.axonframework.commandhandling.model.AggregateLifecycle.apply; + + +public class MessagesAggregate { + + @AggregateIdentifier + private String id; + + public MessagesAggregate() { + } + + @CommandHandler + public MessagesAggregate(CreateMessageCommand command) { + apply(new MessageCreatedEvent(command.getId(), command.getText())); + } + + @EventHandler + public void on(MessageCreatedEvent event) { + this.id = event.getId(); + } + + @CommandHandler + public void markRead(MarkReadMessageCommand command) { + apply(new MessageReadEvent(id)); + } +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/commands/CreateMessageCommand.java b/axon/src/main/java/com/baeldung/axon/commands/CreateMessageCommand.java new file mode 100644 index 0000000000..d0651bf12e --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/commands/CreateMessageCommand.java @@ -0,0 +1,24 @@ +package com.baeldung.axon.commands; + + +import org.axonframework.commandhandling.TargetAggregateIdentifier; + +public class CreateMessageCommand { + + @TargetAggregateIdentifier + private final String id; + private final String text; + + public CreateMessageCommand(String id, String text) { + this.id = id; + this.text = text; + } + + public String getId() { + return id; + } + + public String getText() { + return text; + } +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/commands/MarkReadMessageCommand.java b/axon/src/main/java/com/baeldung/axon/commands/MarkReadMessageCommand.java new file mode 100644 index 0000000000..e66582d9ec --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/commands/MarkReadMessageCommand.java @@ -0,0 +1,18 @@ +package com.baeldung.axon.commands; + + +import org.axonframework.commandhandling.TargetAggregateIdentifier; + +public class MarkReadMessageCommand { + + @TargetAggregateIdentifier + private final String id; + + public MarkReadMessageCommand(String id) { + this.id = id; + } + + public String getId() { + return id; + } +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/eventhandlers/MessagesEventHandler.java b/axon/src/main/java/com/baeldung/axon/eventhandlers/MessagesEventHandler.java new file mode 100644 index 0000000000..3e51e19c4e --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/eventhandlers/MessagesEventHandler.java @@ -0,0 +1,19 @@ +package com.baeldung.axon.eventhandlers; + +import com.baeldung.axon.events.MessageReadEvent; +import com.baeldung.axon.events.MessageCreatedEvent; +import org.axonframework.eventhandling.EventHandler; + + +public class MessagesEventHandler { + + @EventHandler + public void handle(MessageCreatedEvent event) { + System.out.println("Message received: " + event.getText() + " (" + event.getId() + ")"); + } + + @EventHandler + public void handle(MessageReadEvent event) { + System.out.println("Message read: " + event.getId()); + } +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/events/MessageCreatedEvent.java b/axon/src/main/java/com/baeldung/axon/events/MessageCreatedEvent.java new file mode 100644 index 0000000000..3c9aac5ed8 --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/events/MessageCreatedEvent.java @@ -0,0 +1,20 @@ +package com.baeldung.axon.events; + +public class MessageCreatedEvent { + + private final String id; + private final String text; + + public MessageCreatedEvent(String id, String text) { + this.id = id; + this.text = text; + } + + public String getId() { + return id; + } + + public String getText() { + return text; + } +} \ No newline at end of file diff --git a/axon/src/main/java/com/baeldung/axon/events/MessageReadEvent.java b/axon/src/main/java/com/baeldung/axon/events/MessageReadEvent.java new file mode 100644 index 0000000000..57bfc8e19e --- /dev/null +++ b/axon/src/main/java/com/baeldung/axon/events/MessageReadEvent.java @@ -0,0 +1,14 @@ +package com.baeldung.axon.events; + +public class MessageReadEvent { + + private final String id; + + public MessageReadEvent(String id) { + this.id = id; + } + + public String getId() { + return id; + } +} \ No newline at end of file diff --git a/axon/src/test/java/com/baeldung/axon/MessagesAggregateTest.java b/axon/src/test/java/com/baeldung/axon/MessagesAggregateTest.java new file mode 100644 index 0000000000..bbeff18f27 --- /dev/null +++ b/axon/src/test/java/com/baeldung/axon/MessagesAggregateTest.java @@ -0,0 +1,42 @@ +package com.baeldung.axon; + +import com.baeldung.axon.aggregates.MessagesAggregate; +import com.baeldung.axon.commands.CreateMessageCommand; +import com.baeldung.axon.commands.MarkReadMessageCommand; +import com.baeldung.axon.events.MessageCreatedEvent; +import com.baeldung.axon.events.MessageReadEvent; +import org.axonframework.test.aggregate.AggregateTestFixture; +import org.axonframework.test.aggregate.FixtureConfiguration; +import org.junit.Before; +import org.junit.Test; + +import java.util.UUID; + +public class MessagesAggregateTest { + + private FixtureConfiguration fixture; + + @Before + public void setUp() throws Exception { + fixture = new AggregateTestFixture(MessagesAggregate.class); + + } + + @Test + public void giveAggregateRoot_whenCreateMessageCommand_thenShouldProduceMessageCreatedEvent() throws Exception { + String eventText = "Hello, how is your day?"; + String id = UUID.randomUUID().toString(); + fixture.given() + .when(new CreateMessageCommand(id, eventText)) + .expectEvents(new MessageCreatedEvent(id, eventText)); + } + + @Test + public void givenMessageCreatedEvent_whenReadMessageCommand_thenShouldProduceMessageReadEvent() throws Exception { + String id = UUID.randomUUID().toString(); + + fixture.given(new MessageCreatedEvent(id, "Hello :-)")) + .when(new MarkReadMessageCommand(id)) + .expectEvents(new MessageReadEvent(id)); + } +} \ No newline at end of file diff --git a/core-java-9/README.md b/core-java-9/README.md index 53ad79e59c..a6cda8e883 100644 --- a/core-java-9/README.md +++ b/core-java-9/README.md @@ -8,3 +8,7 @@ - [Java 9 Stream API Improvements](http://www.baeldung.com/java-9-stream-api) - [Java 9 Convenience Factory Methods for Collections](http://www.baeldung.com/java-9-collections-factory-methods) - [New Stream Collectors in Java 9](http://www.baeldung.com/java9-stream-collectors) +- [Java 9 CompletableFuture API Improvements](http://www.baeldung.com/java9-completablefuture-api-improvements/) +- [Spring Security – Redirect to the Previous URL After Login](http://www.baeldung.com/spring-security-redirect-login) +- [Java 9 Process API Improvements](http://www.baeldung.com/java-9-process-api) +- [Introduction to Java 9 StackWalking API](http://www.baeldung.com/java-9-stackwalking-api) diff --git a/core-java-9/compile-modules.sh b/core-java-9/compile-modules.sh new file mode 100644 index 0000000000..4c9521de75 --- /dev/null +++ b/core-java-9/compile-modules.sh @@ -0,0 +1 @@ +javac -d mods --module-source-path src/modules $(find src/modules -name "*.java") \ No newline at end of file diff --git a/core-java-9/compile-student-client.bat b/core-java-9/compile-student-client.bat new file mode 100644 index 0000000000..72b2774480 --- /dev/null +++ b/core-java-9/compile-student-client.bat @@ -0,0 +1,3 @@ +javac --module-path mods -d mods/com.baeldung.student.client^ + src/modules/com.baeldung.student.client/module-info.java^ + src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java \ No newline at end of file diff --git a/core-java-9/compile-student-model.bat b/core-java-9/compile-student-model.bat new file mode 100644 index 0000000000..902756c274 --- /dev/null +++ b/core-java-9/compile-student-model.bat @@ -0,0 +1,2 @@ +javac -d mods/com.baeldung.student.model src/modules/com.baeldung.student.model/module-info.java^ + src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java \ No newline at end of file diff --git a/core-java-9/compile-student-service-dbimpl.bat b/core-java-9/compile-student-service-dbimpl.bat new file mode 100644 index 0000000000..bd1cfb7cfe --- /dev/null +++ b/core-java-9/compile-student-service-dbimpl.bat @@ -0,0 +1,3 @@ +javac --module-path mods -d mods/com.baeldung.student.service.dbimpl^ + src/modules/com.baeldung.student.service.dbimpl/module-info.java^ + src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java \ No newline at end of file diff --git a/core-java-9/compile-student-service.bat b/core-java-9/compile-student-service.bat new file mode 100644 index 0000000000..2892b237d1 --- /dev/null +++ b/core-java-9/compile-student-service.bat @@ -0,0 +1,3 @@ +javac --module-path mods -d mods/com.baeldung.student.service^ + src/modules/com.baeldung.student.service/module-info.java^ + src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java \ No newline at end of file diff --git a/core-java-9/run-student-client.bat b/core-java-9/run-student-client.bat new file mode 100644 index 0000000000..2b78a26ec4 --- /dev/null +++ b/core-java-9/run-student-client.bat @@ -0,0 +1 @@ +java --module-path mods -m com.baeldung.student.client/com.baeldung.student.client.StudentClient \ No newline at end of file diff --git a/core-java-9/run-student-client.sh b/core-java-9/run-student-client.sh new file mode 100644 index 0000000000..2b78a26ec4 --- /dev/null +++ b/core-java-9/run-student-client.sh @@ -0,0 +1 @@ +java --module-path mods -m com.baeldung.student.client/com.baeldung.student.client.StudentClient \ No newline at end of file diff --git a/core-java-9/src/main/java/com/baeldung/java9/stackwalker/StackWalkerDemo.java b/core-java-9/src/main/java/com/baeldung/java9/stackwalker/StackWalkerDemo.java new file mode 100644 index 0000000000..a0e632d569 --- /dev/null +++ b/core-java-9/src/main/java/com/baeldung/java9/stackwalker/StackWalkerDemo.java @@ -0,0 +1,84 @@ +package com.baeldung.java9.stackwalker; + +import java.lang.StackWalker.StackFrame; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class StackWalkerDemo { + + public void methodOne() { + this.methodTwo(); + } + + public void methodTwo() { + this.methodThree(); + } + + public void methodThree() { + List stackTrace = StackWalker.getInstance() + .walk(this::walkExample); + + printStackTrace(stackTrace); + + System.out.println("---------------------------------------------"); + + stackTrace = StackWalker.getInstance() + .walk(this::walkExample2); + + printStackTrace(stackTrace); + + System.out.println("---------------------------------------------"); + + String line = StackWalker.getInstance().walk(this::walkExample3); + System.out.println(line); + + System.out.println("---------------------------------------------"); + + stackTrace = StackWalker.getInstance(StackWalker.Option.SHOW_REFLECT_FRAMES) + .walk(this::walkExample); + + printStackTrace(stackTrace); + + System.out.println("---------------------------------------------"); + + Runnable r = () -> { + List stackTrace2 = StackWalker.getInstance(StackWalker.Option.SHOW_HIDDEN_FRAMES) + .walk(this::walkExample); + printStackTrace(stackTrace2); + }; + r.run(); + } + + public List walkExample(Stream stackFrameStream) { + return stackFrameStream.collect(Collectors.toList()); + } + + public List walkExample2(Stream stackFrameStream) { + return stackFrameStream.filter(frame -> frame.getClassName() + .contains("com.baeldung")) + .collect(Collectors.toList()); + } + + public String walkExample3(Stream stackFrameStream) { + return stackFrameStream.filter(frame -> frame.getClassName() + .contains("com.baeldung") + && frame.getClassName() + .endsWith("Test")) + .findFirst() + .map(frame -> frame.getClassName() + "#" + frame.getMethodName() + ", Line " + frame.getLineNumber()) + .orElse("Unknown caller"); + } + + public void findCaller() { + Class caller = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).getCallerClass(); + System.out.println(caller.getCanonicalName()); + } + + public void printStackTrace(List stackTrace) { + for (StackFrame stackFrame : stackTrace) { + System.out.println(stackFrame.getClassName() + .toString() + "#" + stackFrame.getMethodName() + ", Line " + stackFrame.getLineNumber()); + } + } +} diff --git a/core-java-9/src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java b/core-java-9/src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java new file mode 100644 index 0000000000..e6fce9163f --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.client/com/baeldung/student/client/StudentClient.java @@ -0,0 +1,16 @@ +package com.baeldung.student.client; + +import com.baeldung.student.service.StudentService; +import com.baeldung.student.service.dbimpl.StudentDbService; +import com.baeldung.student.model.Student; + +public class StudentClient { + + public static void main(String[] args) { + StudentService service = new StudentDbService(); + service.create(new Student()); + service.read("17SS0001"); + service.update(new Student()); + service.delete("17SS0001"); + } +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.client/module-info.java b/core-java-9/src/modules/com.baeldung.student.client/module-info.java new file mode 100644 index 0000000000..7ef7b430fc --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.client/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.student.client{ + requires com.baeldung.student.service.dbimpl; +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java b/core-java-9/src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java new file mode 100644 index 0000000000..d7f8f69107 --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.model/com/baeldung/student/model/Student.java @@ -0,0 +1,15 @@ +package com.baeldung.student.model; + +import java.util.Date; + +public class Student { + private String registrationId; + + public String getRegistrationId() { + return registrationId; + } + + public void setRegistrationId(String registrationId) { + this.registrationId = registrationId; + } +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.model/module-info.java b/core-java-9/src/modules/com.baeldung.student.model/module-info.java new file mode 100644 index 0000000000..3bdab058d4 --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.model/module-info.java @@ -0,0 +1,3 @@ +module com.baeldung.student.model{ + exports com.baeldung.student.model; +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java b/core-java-9/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java new file mode 100644 index 0000000000..2519da085b --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.service.dbimpl/com/baeldung/student/service/dbimpl/StudentDbService.java @@ -0,0 +1,30 @@ +package com.baeldung.student.service.dbimpl; + +import com.baeldung.student.service.StudentService; +import com.baeldung.student.model.Student; +import java.util.logging.*; + +public class StudentDbService implements StudentService { + + private static Logger logger = Logger.getLogger("StudentDbService"); + + public String create(Student student) { + logger.log(Level.INFO, "Creating student in DB..."); + return student.getRegistrationId(); + } + + public Student read(String registrationId) { + logger.log(Level.INFO, "Reading student from DB..."); + return new Student(); + } + + public Student update(Student student) { + logger.log(Level.INFO, "Updating sutdent in DB..."); + return student; + } + + public String delete(String registrationId) { + logger.log(Level.INFO, "Deleteing sutdent in DB..."); + return registrationId; + } +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.service.dbimpl/module-info.java b/core-java-9/src/modules/com.baeldung.student.service.dbimpl/module-info.java new file mode 100644 index 0000000000..96a453ea6b --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.service.dbimpl/module-info.java @@ -0,0 +1,5 @@ +module com.baeldung.student.service.dbimpl{ + requires transitive com.baeldung.student.service; + exports com.baeldung.student.service.dbimpl; + requires java.logging; +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java b/core-java-9/src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java new file mode 100644 index 0000000000..6076bf12e3 --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.service/com/baeldung/student/service/StudentService.java @@ -0,0 +1,14 @@ +package com.baeldung.student.service; + +import com.baeldung.student.model.Student; + +public interface StudentService { + + public String create(Student student); + + public Student read(String registrationId); + + public Student update(Student student); + + public String delete(String registrationId); +} \ No newline at end of file diff --git a/core-java-9/src/modules/com.baeldung.student.service/module-info.java b/core-java-9/src/modules/com.baeldung.student.service/module-info.java new file mode 100644 index 0000000000..5de9e58348 --- /dev/null +++ b/core-java-9/src/modules/com.baeldung.student.service/module-info.java @@ -0,0 +1,4 @@ +module com.baeldung.student.service{ + requires transitive com.baeldung.student.model; + exports com.baeldung.student.service; +} \ No newline at end of file diff --git a/core-java-9/src/test/java/com/baeldung/java9/concurrent/future/CompletableFutureTest.java b/core-java-9/src/test/java/com/baeldung/java9/concurrent/future/CompletableFutureTest.java new file mode 100644 index 0000000000..b71c211177 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/concurrent/future/CompletableFutureTest.java @@ -0,0 +1,74 @@ +package com.baeldung.java9.concurrent.future; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import org.junit.Test; + +public class CompletableFutureTest { + @Test + public void testDelay () throws Exception { + Object input = new Object(); + CompletableFuture future = new CompletableFuture<>(); + future.completeAsync(() -> input, CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS)); + + Thread.sleep(100); + + assertFalse(future.isDone()); + + Thread.sleep(1000); + assertTrue(future.isDone()); + assertSame(input, future.get()); + } + + @Test + public void testTimeoutTriggered () throws Exception { + CompletableFuture future = new CompletableFuture<>(); + future.orTimeout(1, TimeUnit.SECONDS); + + Thread.sleep(1100); + + assertTrue(future.isDone()); + + try { + future.get(); + } catch (ExecutionException e) { + assertTrue(e.getCause() instanceof TimeoutException); + } + } + + @Test + public void testTimeoutNotTriggered () throws Exception { + Object input = new Object(); + CompletableFuture future = new CompletableFuture<>(); + + future.orTimeout(1, TimeUnit.SECONDS); + + Thread.sleep(100); + + future.complete(input); + + Thread.sleep(1000); + + assertTrue(future.isDone()); + assertSame(input, future.get()); + } + + + + @Test + public void completeOnTimeout () throws Exception { + Object input = new Object(); + CompletableFuture future = new CompletableFuture<>(); + future.completeOnTimeout(input, 1, TimeUnit.SECONDS); + + Thread.sleep(1100); + + assertTrue(future.isDone()); + assertSame(input, future.get()); + } +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/stackwalker/StackWalkerDemoTest.java b/core-java-9/src/test/java/com/baeldung/java9/stackwalker/StackWalkerDemoTest.java new file mode 100644 index 0000000000..b523b7dfb2 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/stackwalker/StackWalkerDemoTest.java @@ -0,0 +1,16 @@ +package com.baeldung.java9.stackwalker; + +import org.junit.Test; + +public class StackWalkerDemoTest { + + @Test + public void giveStalkWalker_whenWalkingTheStack_thenShowStackFrames() { + new StackWalkerDemo().methodOne(); + } + + @Test + public void giveStalkWalker_whenInvokingFindCaller_thenFindCallingClass() { + new StackWalkerDemo().findCaller(); + } +} diff --git a/core-java/README.md b/core-java/README.md index a34908d8ae..63e3748ec6 100644 --- a/core-java/README.md +++ b/core-java/README.md @@ -79,3 +79,9 @@ - [The Java HashMap Under the Hood](http://www.baeldung.com/java-hashmap) - [A Guide to LinkedHashMap in Java](http://www.baeldung.com/java-linked-hashmap) - [A Guide to TreeMap in Java](http://www.baeldung.com/java-treemap) +- [A Quick JUnit vs TestNG Comparison](http://www.baeldung.com/junit-vs-testng) +- [Finding Max/Min of a List or Collection](http://www.baeldung.com/java-collection-min-max) +- [Guide to java.util.concurrent.Locks](http://www.baeldung.com/java-concurrent-locks) +- [Java Primitive Conversions](http://www.baeldung.com/java-primitive-conversions) +- [Java Money and the Currency API](http://www.baeldung.com/java-money-and-currency) + diff --git a/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/AntColonyOptimization.java b/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/AntColonyOptimization.java deleted file mode 100644 index 27a270f906..0000000000 --- a/core-java/src/main/java/com/baeldung/algorithms/ga/ant_colony/AntColonyOptimization.java +++ /dev/null @@ -1,207 +0,0 @@ -package com.baeldung.algorithms.ga.ant_colony; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Random; -import java.util.stream.IntStream; - -public class AntColonyOptimization { - - private double c = 1.0; - private double alpha = 1; - private double beta = 5; - private double evaporation = 0.5; - private double Q = 500; - private double antFactor = 0.8; - private double randomFactor = 0.01; - - private int maxIterations = 1000; - - public int numberOfCities; - public int numberOfAnts; - private double graph[][]; - private double trails[][]; - private List ants = new ArrayList<>(); - private Random random = new Random(); - private double probabilities[]; - - private int currentIndex; - - public int[] bestTourOrder; - public double bestTourLength; - - public AntColonyOptimization(int noOfCities) { - graph = generateRandomMatrix(noOfCities); - numberOfCities = graph.length; - numberOfAnts = (int) (numberOfCities * antFactor); - - trails = new double[numberOfCities][numberOfCities]; - probabilities = new double[numberOfCities]; - IntStream.range(0, numberOfAnts).forEach(i -> ants.add(new Ant(numberOfCities))); - } - - /** - * Generate initial solution - * - * @param n - * @return - */ - public double[][] generateRandomMatrix(int n) { - double[][] randomMatrix = new double[n][n]; - random.setSeed(System.currentTimeMillis()); - IntStream.range(0, n).forEach(i -> { - IntStream.range(0, n).forEach(j -> { - Integer r = random.nextInt(100) + 1; - randomMatrix[i][j] = Math.abs(r); - }); - }); - return randomMatrix; - } - - /** - * Perform ant optimization - * - * @return - */ - public void startAntOptimization() { - IntStream.rangeClosed(1, 3).forEach(i -> { - System.out.println("Attempt #" + i); - solve(); - }); - } - - /** - * Use this method to run the main logic - * - * @return - */ - public int[] solve() { - setupAnts(); - clearTrails(); - IntStream.range(0, maxIterations).forEach(i -> { - moveAnts(); - updateTrails(); - updateBest(); - }); - System.out.println("Best tour length: " + (bestTourLength - numberOfCities)); - System.out.println("Best tour order: " + Arrays.toString(bestTourOrder)); - return bestTourOrder.clone(); - } - - /** - * Prepare ants for the simulation - */ - private void setupAnts() { - IntStream.range(0, numberOfAnts).forEach(i -> { - ants.stream().forEach(ant -> { - ant.clear(); - ant.visitCity(-1, random.nextInt(numberOfCities)); - }); - }); - currentIndex = 0; - } - - /** - * At each iteration, move ants - */ - private void moveAnts() { - IntStream.range(currentIndex, numberOfCities - 1).forEach(i -> { - ants.stream().forEach(ant -> { - ant.visitCity(currentIndex, selectNextCity(ant)); - }); - currentIndex++; - }); - } - - /** - * Select next city for each ant - * - * @param ant - * @return - */ - private int selectNextCity(Ant ant) { - int t = random.nextInt(numberOfCities - currentIndex); - if (random.nextDouble() < randomFactor) { - IntStream.range(0, numberOfCities).filter(i -> i == t && !ant.visited(i)).findFirst(); - } - calculateProbabilities(ant); - double r = random.nextDouble(); - double total = 0; - for (int i = 0; i < numberOfCities; i++) { - total += probabilities[i]; - if (total >= r) { - return i; - } - } - - throw new RuntimeException("There are no other cities"); - } - - /** - * Calculate the next city picks probabilites - * - * @param ant - */ - public void calculateProbabilities(Ant ant) { - int i = ant.trail[currentIndex]; - double pheromone = 0.0; - for (int l = 0; l < numberOfCities; l++) { - if (!ant.visited(l)) { - pheromone += Math.pow(trails[i][l], alpha) * Math.pow(1.0 / graph[i][l], beta); - } - } - for (int j = 0; j < numberOfCities; j++) { - if (ant.visited(j)) { - probabilities[j] = 0.0; - } else { - double numerator = Math.pow(trails[i][j], alpha) * Math.pow(1.0 / graph[i][j], beta); - probabilities[j] = numerator / pheromone; - } - } - } - - /** - * Update trails that ants used - */ - private void updateTrails() { - for (int i = 0; i < numberOfCities; i++) { - for (int j = 0; j < numberOfCities; j++) { - trails[i][j] *= evaporation; - } - } - for (Ant a : ants) { - double contribution = Q / a.trailLength(graph); - for (int i = 0; i < numberOfCities - 1; i++) { - trails[a.trail[i]][a.trail[i + 1]] += contribution; - } - trails[a.trail[numberOfCities - 1]][a.trail[0]] += contribution; - } - } - - /** - * Update the best solution - */ - private void updateBest() { - if (bestTourOrder == null) { - bestTourOrder = ants.get(0).trail; - bestTourLength = ants.get(0).trailLength(graph); - } - for (Ant a : ants) { - if (a.trailLength(graph) < bestTourLength) { - bestTourLength = a.trailLength(graph); - bestTourOrder = a.trail.clone(); - } - } - } - - /** - * Clear trails after simulation - */ - private void clearTrails() { - IntStream.range(0, numberOfCities).forEach(i -> { - IntStream.range(0, numberOfCities).forEach(j -> trails[i][j] = c); - }); - } - -} diff --git a/core-java/src/test/java/com/baeldung/PrimitiveConversionsJUnitTest.java b/core-java/src/test/java/com/baeldung/PrimitiveConversionsJUnitTest.java index 4137b5af00..10ceaf85a4 100644 --- a/core-java/src/test/java/com/baeldung/PrimitiveConversionsJUnitTest.java +++ b/core-java/src/test/java/com/baeldung/PrimitiveConversionsJUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.primitiveconversions; +package com.baeldung; import org.junit.Test; import static org.junit.Assert.*; diff --git a/core-java/src/test/java/com/baeldung/java8/comparator/Employee.java b/core-java/src/test/java/com/baeldung/java8/comparator/Employee.java new file mode 100644 index 0000000000..bbc4e3e320 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/java8/comparator/Employee.java @@ -0,0 +1,23 @@ +package com.baeldung.java8.comparator; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Data +@AllArgsConstructor +@ToString +@EqualsAndHashCode +public class Employee implements Comparable{ + String name; + int age; + double salary; + long mobile; + + + @Override + public int compareTo(Employee argEmployee) { + return name.compareTo(argEmployee.getName()); + } +} diff --git a/core-java/src/test/java/com/baeldung/java8/comparator/Java8ComparatorTest.java b/core-java/src/test/java/com/baeldung/java8/comparator/Java8ComparatorTest.java new file mode 100644 index 0000000000..5c338101d8 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/java8/comparator/Java8ComparatorTest.java @@ -0,0 +1,192 @@ +package com.baeldung.java8.comparator; + +import java.util.Arrays; +import java.util.Comparator; + +import org.junit.Before; +import org.junit.Test; + +import lombok.Data; +import static org.junit.Assert.assertTrue; + +public class Java8ComparatorTest { + + private Employee[] employees; + private Employee[] employeesArrayWithNulls; + private Employee[] sortedEmployeesByName; + private Employee[] sortedEmployeesByNameDesc; + private Employee[] sortedEmployeesByAge; + private Employee[] sortedEmployeesByMobile; + private Employee[] sortedEmployeesBySalary; + private Employee[] sortedEmployeesArray_WithNullsFirst; + private Employee[] sortedEmployeesArray_WithNullsLast; + private Employee[] sortedEmployeesByNameAge; + private Employee[] someMoreEmployees; + private Employee[] sortedEmployeesByAgeName;; + + @Before + public void initData() { + employees = new Employee[] { new Employee("John", 25, 3000, 9922001), new Employee("Ace", 22, 2000, 5924001), + new Employee("Keith", 35, 4000, 3924401) }; + employeesArrayWithNulls = new Employee[] { new Employee("John", 25, 3000, 9922001), null, new Employee("Ace", 22, 2000, 5924001), + null, new Employee("Keith", 35, 4000, 3924401) }; + + sortedEmployeesByName = new Employee[] { new Employee("Ace", 22, 2000, 5924001), + new Employee("John", 25, 3000, 9922001), new Employee("Keith", 35, 4000, 3924401) }; + sortedEmployeesByNameDesc = new Employee[] { new Employee("Keith", 35, 4000, 3924401), new Employee("John", 25, 3000, 9922001), + new Employee("Ace", 22, 2000, 5924001) }; + + sortedEmployeesByAge = new Employee[] { new Employee("Ace", 22, 2000, 5924001), + new Employee("John", 25, 3000, 9922001), new Employee("Keith", 35, 4000, 3924401) }; + + sortedEmployeesByMobile = new Employee[] { new Employee("Keith", 35, 4000, 3924401), new Employee("Ace", 22, 2000, 5924001), + new Employee("John", 25, 3000, 9922001), }; + + sortedEmployeesBySalary = new Employee[] { new Employee("Ace", 22, 2000, 5924001), new Employee("John", 25, 3000, 9922001), + new Employee("Keith", 35, 4000, 3924401), }; + + sortedEmployeesArray_WithNullsFirst = new Employee[] { null, null, new Employee("Ace", 22, 2000, 5924001), + new Employee("John", 25, 3000, 9922001), new Employee("Keith", 35, 4000, 3924401) }; + sortedEmployeesArray_WithNullsLast = new Employee[] { new Employee("Ace", 22, 2000, 5924001), + new Employee("John", 25, 3000, 9922001), new Employee("Keith", 35, 4000, 3924401), null, null }; + + someMoreEmployees = new Employee[] { new Employee("Jake", 25, 3000, 9922001), new Employee("Jake", 22, 2000, 5924001), + new Employee("Ace", 22, 3000, 6423001), new Employee("Keith", 35, 4000, 3924401) }; + + sortedEmployeesByAgeName = new Employee[] { new Employee("Ace", 22, 3000, 6423001), + new Employee("Jake", 22, 2000, 5924001), new Employee("Jake", 25, 3000, 9922001), new Employee("Keith", 35, 4000, 3924401) }; + sortedEmployeesByNameAge = new Employee[] { new Employee("Ace", 22, 3000, 6423001), + new Employee("Jake", 22, 2000, 5924001), new Employee("Jake", 25, 3000, 9922001), new Employee("Keith", 35, 4000, 3924401) }; + } + + @Test + public void givenEmployeeArray_whenUsingComparing_thenCheckingSort() { + Comparator employeeNameComparator = Comparator.comparing(Employee::getName); + Arrays.sort(employees, employeeNameComparator); +// System.out.println(Arrays.toString(employees)); + assertTrue(Arrays.equals(employees, sortedEmployeesByName)); + } + + @Test + public void givenEmployeeArray_whenUsingComparingWithComparator_thenCheckingSort() { + Comparator employeeNameComparator = Comparator.comparing(Employee::getName, (s1, s2) -> { + return s2.compareTo(s1); + }); + Arrays.sort(employees, employeeNameComparator); +// System.out.println(Arrays.toString(employees)); + assertTrue(Arrays.equals(employees, sortedEmployeesByNameDesc)); + } + + @Test + public void givenEmployeeArray_whenUsingComparingInt_thenCheckingSort() { + Comparator employeeAgeComparator = Comparator.comparingInt(Employee::getAge); + Arrays.sort(employees, employeeAgeComparator); +// System.out.println(Arrays.toString(employees)); + assertTrue(Arrays.equals(employees, sortedEmployeesByAge)); + } + + @Test + public void givenEmployeeArray_whenUsingComparingLong_thenCheckingSort() { + Comparator employeeMobileComparator = Comparator.comparingLong(Employee::getMobile); + Arrays.sort(employees, employeeMobileComparator); +// System.out.println(Arrays.toString(employees)); + assertTrue(Arrays.equals(employees, sortedEmployeesByMobile)); + } + + @Test + public void givenEmployeeArray_whenUsingComparingDouble_thenCheckingSort() { + Comparator employeeSalaryComparator = Comparator.comparingDouble(Employee::getSalary); + Arrays.sort(employees, employeeSalaryComparator); +// System.out.println(Arrays.toString(employees)); + assertTrue(Arrays.equals(employees, sortedEmployeesBySalary)); + } + + @Test + public void givenEmployeeArray_whenUsingNaturalOrder_thenCheckingSort() { + Comparator employeeNameComparator = Comparator. naturalOrder(); + Arrays.sort(employees, employeeNameComparator); +// System.out.println(Arrays.toString(employees)); + assertTrue(Arrays.equals(employees, sortedEmployeesByName)); + } + + @Test + public void givenEmployeeArray_whenUsingReverseOrder_thenCheckingSort() { + Comparator employeeNameComparator = Comparator. reverseOrder(); + Arrays.sort(employees, employeeNameComparator); +// System.out.println(Arrays.toString(employees)); + assertTrue(Arrays.equals(employees, sortedEmployeesByNameDesc)); + } + + @Test + public void givenEmployeeArray_whenUsingNullFirst_thenCheckingSort() { + Comparator employeeNameComparator = Comparator.comparing(Employee::getName); + Comparator employeeNameComparator_nullFirst = Comparator.nullsFirst(employeeNameComparator); + Arrays.sort(employeesArrayWithNulls, employeeNameComparator_nullFirst); +// System.out.println(Arrays.toString(employeesArrayWithNulls)); + assertTrue(Arrays.equals(employeesArrayWithNulls, sortedEmployeesArray_WithNullsFirst)); + } + + @Test + public void givenEmployeeArray_whenUsingNullLast_thenCheckingSort() { + Comparator employeeNameComparator = Comparator.comparing(Employee::getName); + Comparator employeeNameComparator_nullLast = Comparator.nullsLast(employeeNameComparator); + Arrays.sort(employeesArrayWithNulls, employeeNameComparator_nullLast); +// System.out.println(Arrays.toString(employeesArrayWithNulls)); + assertTrue(Arrays.equals(employeesArrayWithNulls, sortedEmployeesArray_WithNullsLast)); + } + + @Test + public void givenEmployeeArray_whenUsingThenComparing_thenCheckingSort() { + Comparator employee_Age_Name_Comparator = Comparator.comparing(Employee::getAge).thenComparing(Employee::getName); + + Arrays.sort(someMoreEmployees, employee_Age_Name_Comparator); +// System.out.println(Arrays.toString(someMoreEmployees)); + assertTrue(Arrays.equals(someMoreEmployees, sortedEmployeesByAgeName)); + } + + @Test + public void givenEmployeeArray_whenUsingThenComparingInt_thenCheckingSort() { + Comparator employee_Name_Age_Comparator = Comparator.comparing(Employee::getName).thenComparingInt(Employee::getAge); + + Arrays.sort(someMoreEmployees, employee_Name_Age_Comparator); +// System.out.println(Arrays.toString(someMoreEmployees)); + assertTrue(Arrays.equals(someMoreEmployees, sortedEmployeesByNameAge)); + } + + @Before + public void printData() { +// System.out.println("employees"); +// System.out.println(Arrays.toString(employees)); + // +// System.out.println("employeesArrayWithNulls"); +// System.out.println(Arrays.toString(employeesArrayWithNulls)); + // + // System.out.println("sortedEmployeesByName"); + // System.out.println(Arrays.toString(sortedEmployeesByName)); + // + // System.out.println("sortedEmployeesByNameDesc"); + // System.out.println(Arrays.toString(sortedEmployeesByNameDesc)); + // + // System.out.println("sortedEmployeesByAge"); + // System.out.println(Arrays.toString(sortedEmployeesByAge)); + // + // System.out.println("sortedEmployeesByMobile"); + // System.out.println(Arrays.toString(sortedEmployeesByMobile)); + // + // System.out.println("sortedEmployeesBySalary"); + // System.out.println(Arrays.toString(sortedEmployeesBySalary)); + // + // System.out.println("sortedEmployeesArray_WithNullsFirst"); + // System.out.println(Arrays.toString(sortedEmployeesArray_WithNullsFirst)); + // + // System.out.println("sortedEmployeesArray_WithNullsLast"); + // System.out.println(Arrays.toString(sortedEmployeesArray_WithNullsLast)); + // + // System.out.println("sortedEmployeesByNameAge"); + // System.out.println(Arrays.toString(sortedEmployeesByNameAge)); + // +// System.out.println("someMoreEmployees"); +// System.out.println(Arrays.toString(someMoreEmployees)); + // + } +} 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 new file mode 100644 index 0000000000..cf9334954b --- /dev/null +++ b/core-java/src/test/java/com/baeldung/list/flattennestedlist/FlattenNestedListTest.java @@ -0,0 +1,64 @@ +package com.baeldung.list.flattennestedlist; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class FlattenNestedListTest { + + @Test + public void givenListOfListOfString_flattenNestedList1() { + // given + List ls1 = Arrays.asList("one:one", "one:two", "one:three"); + List ls2 = Arrays.asList("two:one", "two:two", "two:three"); + List ls3 = Arrays.asList("three:one", "three:two", "three:three"); + + List> list = Arrays.asList(ls1, ls2, ls3); + + // when + List ls = flattenListOfListsImperatively(list); + + // then + assertNotNull(ls); + assertTrue(ls.size() == 9); + //TODO content assertion + } + + @Test + public void givenListOfListOfString_flattenNestedList2() { + // given + List ls1 = Arrays.asList("one:one", "one:two", "one:three"); + List ls2 = Arrays.asList("two:one", "two:two", "two:three"); + List ls3 = Arrays.asList("three:one", "three:two", "three:three"); + + List> list = Arrays.asList(ls1, ls2, ls3); + + // when + List ls = flattenListOfListsStream(list); + + // then + assertNotNull(ls); + assertTrue(ls.size() == 9); + //TODO content assertion + } + + public List flattenListOfListsImperatively(List> list) { + List ls = new ArrayList<>(); + list.forEach(ls::addAll); + return ls; + } + + public List flattenListOfListsStream(List> list) { + return list.stream() + .flatMap(Collection::stream) + .collect(Collectors.toList()); + } + +} diff --git a/core-java/src/test/java/com/baeldung/money/JavaMoneyTest.java b/core-java/src/test/java/com/baeldung/money/JavaMoneyTest.java index 3d2f986c30..140560d079 100644 --- a/core-java/src/test/java/com/baeldung/money/JavaMoneyTest.java +++ b/core-java/src/test/java/com/baeldung/money/JavaMoneyTest.java @@ -15,6 +15,8 @@ import javax.money.convert.MonetaryConversions; import javax.money.format.AmountFormatQueryBuilder; import javax.money.format.MonetaryAmountFormat; import javax.money.format.MonetaryFormats; +import java.util.Arrays; +import java.util.List; import java.util.Locale; import static org.junit.Assert.*; @@ -40,7 +42,11 @@ public class JavaMoneyTest { @Test public void givenAmounts_whenStringified_thanEquals() { CurrencyUnit usd = Monetary.getCurrency("USD"); - MonetaryAmount fstAmtUSD = Monetary.getDefaultAmountFactory().setCurrency(usd).setNumber(200).create(); + MonetaryAmount fstAmtUSD = Monetary + .getDefaultAmountFactory() + .setCurrency(usd) + .setNumber(200) + .create(); Money moneyof = Money.of(12, usd); FastMoney fastmoneyof = FastMoney.of(2, usd); @@ -52,7 +58,11 @@ public class JavaMoneyTest { @Test public void givenCurrencies_whenCompared_thanNotequal() { - MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory().setCurrency("USD").setNumber(1).create(); + MonetaryAmount oneDolar = Monetary + .getDefaultAmountFactory() + .setCurrency("USD") + .setNumber(1) + .create(); Money oneEuro = Money.of(1, "EUR"); assertFalse(oneEuro.equals(FastMoney.of(1, "EUR"))); @@ -61,20 +71,22 @@ public class JavaMoneyTest { @Test(expected = ArithmeticException.class) public void givenAmount_whenDivided_thanThrowsException() { - MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory().setCurrency("USD").setNumber(1).create(); + MonetaryAmount oneDolar = Monetary + .getDefaultAmountFactory() + .setCurrency("USD") + .setNumber(1) + .create(); oneDolar.divide(3); fail(); // if no exception } @Test public void givenAmounts_whenSummed_thanCorrect() { - MonetaryAmount[] monetaryAmounts = new MonetaryAmount[]{ - Money.of(100, "CHF"), Money.of(10.20, "CHF"), Money.of(1.15, "CHF")}; + List monetaryAmounts = Arrays.asList(Money.of(100, "CHF"), Money.of(10.20, "CHF"), Money.of(1.15, "CHF")); - Money sumAmtCHF = Money.of(0, "CHF"); - for (MonetaryAmount monetaryAmount : monetaryAmounts) { - sumAmtCHF = sumAmtCHF.add(monetaryAmount); - } + Money sumAmtCHF = (Money) monetaryAmounts + .stream() + .reduce(Money.of(0, "CHF"), MonetaryAmount::add); assertEquals("CHF 111.35", sumAmtCHF.toString()); } @@ -84,9 +96,19 @@ public class JavaMoneyTest { CurrencyUnit usd = Monetary.getCurrency("USD"); Money moneyof = Money.of(12, usd); - MonetaryAmount fstAmtUSD = Monetary.getDefaultAmountFactory().setCurrency(usd).setNumber(200.50).create(); - MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory().setCurrency("USD").setNumber(1).create(); - Money subtractedAmount = Money.of(1, "USD").subtract(fstAmtUSD); + MonetaryAmount fstAmtUSD = Monetary + .getDefaultAmountFactory() + .setCurrency(usd) + .setNumber(200.50) + .create(); + MonetaryAmount oneDolar = Monetary + .getDefaultAmountFactory() + .setCurrency("USD") + .setNumber(1) + .create(); + Money subtractedAmount = Money + .of(1, "USD") + .subtract(fstAmtUSD); MonetaryAmount multiplyAmount = oneDolar.multiply(0.25); MonetaryAmount divideAmount = oneDolar.divide(0.25); @@ -101,53 +123,64 @@ public class JavaMoneyTest { @Test public void givenAmount_whenRounded_thanEquals() { - MonetaryAmount fstAmtEUR = Monetary.getDefaultAmountFactory().setCurrency("EUR").setNumber(1.30473908).create(); + MonetaryAmount fstAmtEUR = Monetary + .getDefaultAmountFactory() + .setCurrency("EUR") + .setNumber(1.30473908) + .create(); MonetaryAmount roundEUR = fstAmtEUR.with(Monetary.getDefaultRounding()); assertEquals("EUR 1.30473908", fstAmtEUR.toString()); assertEquals("EUR 1.3", roundEUR.toString()); } @Test - public void givenAmount_whenCustomFormat_thanEquals() { - MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory().setCurrency("USD").setNumber(1).create(); - MonetaryAmountFormat formatUSD = MonetaryFormats.getAmountFormat(Locale.US); - String usFormatted = formatUSD.format(oneDolar); + public void givenAmount_whenConversion_thenNotNull() { + MonetaryAmount oneDollar = Monetary + .getDefaultAmountFactory() + .setCurrency("USD") + .setNumber(1) + .create(); - MonetaryAmountFormat customFormat = MonetaryFormats.getAmountFormat(AmountFormatQueryBuilder.of(Locale.US).set(CurrencyStyle.NAME).set("pattern", "00000.00 ¤").build()); - String customFormatted = customFormat.format(oneDolar); + CurrencyConversion conversionEUR = MonetaryConversions.getConversion("EUR"); - assertEquals("USD 1", oneDolar.toString()); - assertNotNull(formatUSD); - assertNotNull(customFormat); - assertEquals("USD1.00", usFormatted); - assertEquals("00001.00 US Dollar", customFormatted); + MonetaryAmount convertedAmountUSDtoEUR = oneDollar.with(conversionEUR); + + assertEquals("USD 1", oneDollar.toString()); + assertNotNull(convertedAmountUSDtoEUR); } @Test - public void givenAmount_whenConversion_thenNotNull() { - CurrencyUnit USD = Monetary.getCurrency("USD"); - MonetaryAmount oneDolar = Monetary.getDefaultAmountFactory().setCurrency("USD").setNumber(1).create(); - MonetaryAmount fstAmtEUR = Monetary.getDefaultAmountFactory().setCurrency("EUR").setNumber(1.30473908).create(); + public void givenLocale_whenFormatted_thanEquals() { + MonetaryAmount oneDollar = Monetary + .getDefaultAmountFactory() + .setCurrency("USD") + .setNumber(1) + .create(); + MonetaryAmountFormat formatUSD = MonetaryFormats.getAmountFormat(Locale.US); + String usFormatted = formatUSD.format(oneDollar); - CurrencyConversion convEUR = MonetaryConversions.getConversion(ConversionQueryBuilder.of().setTermCurrency("EUR").build()); - CurrencyConversion convUSD = MonetaryConversions.getConversion(ConversionQueryBuilder.of().setTermCurrency(USD).build()); + assertEquals("USD 1", oneDollar.toString()); + assertNotNull(formatUSD); + assertEquals("USD1.00", usFormatted); + } - CurrencyConversion conversionUSD = MonetaryConversions.getConversion("USD"); - CurrencyConversion conversionEUR = MonetaryConversions.getConversion("EUR"); + @Test + public void givenAmount_whenCustomFormat_thanEquals() { + MonetaryAmount oneDollar = Monetary + .getDefaultAmountFactory() + .setCurrency("USD") + .setNumber(1) + .create(); - MonetaryAmount convertedAmountEURtoUSD = fstAmtEUR.with(conversionUSD); - MonetaryAmount convertedAmountEURtoUSD2 = fstAmtEUR.with(convUSD); - MonetaryAmount convertedAmountUSDtoEUR = oneDolar.with(conversionEUR); - MonetaryAmount convertedAmountUSDtoEUR2 = oneDolar.with(convEUR); + MonetaryAmountFormat customFormat = MonetaryFormats.getAmountFormat(AmountFormatQueryBuilder + .of(Locale.US) + .set(CurrencyStyle.NAME) + .set("pattern", "00000.00 ¤") + .build()); + String customFormatted = customFormat.format(oneDollar); - assertEquals("USD", USD.toString()); - assertEquals("USD 1", oneDolar.toString()); - assertEquals("EUR 1.30473908", fstAmtEUR.toString()); - assertNotNull(convEUR); - assertNotNull(convUSD); - assertNotNull(convertedAmountEURtoUSD); - assertNotNull(convertedAmountEURtoUSD2); - assertNotNull(convertedAmountUSDtoEUR); - assertNotNull(convertedAmountUSDtoEUR2); + assertNotNull(customFormat); + assertEquals("USD 1", oneDollar.toString()); + assertEquals("00001.00 US Dollar", customFormatted); } } diff --git a/guava/README.md b/guava/README.md index ee224bae5f..f46c4dd3de 100644 --- a/guava/README.md +++ b/guava/README.md @@ -24,3 +24,4 @@ - [Guide to Guava RangeSet](http://www.baeldung.com/guava-rangeset) - [Guide to Guava RangeMap](http://www.baeldung.com/guava-rangemap) - [Guide to Guava Table](http://www.baeldung.com/guava-table) +- [Guide to Guava’s Reflection Utilities](http://www.baeldung.com/guava-reflection) diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/marker/Communicator.java b/guice-intro/src/main/java/com/baeldung/examples/guice/marker/Communicator.java deleted file mode 100644 index 239666b6ab..0000000000 --- a/guice-intro/src/main/java/com/baeldung/examples/guice/marker/Communicator.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.baeldung.examples.guice.marker; - -/** - * - * @author Baeldung - */ -public interface Communicator { - - public boolean sendMessage(String message); - -} diff --git a/guice/README.md b/guice/README.md new file mode 100644 index 0000000000..d1bd1ff883 --- /dev/null +++ b/guice/README.md @@ -0,0 +1,4 @@ +## Google Guice Tutorials Project + +### Relevant Articles +- [Guide to Google Guice](http://www.baeldung.com/guice) diff --git a/guice-intro/pom.xml b/guice/pom.xml similarity index 94% rename from guice-intro/pom.xml rename to guice/pom.xml index 1f0d7679b7..df87021794 100644 --- a/guice-intro/pom.xml +++ b/guice/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.baeldung.examples.guice - guice-intro + guice 1.0-SNAPSHOT jar @@ -30,5 +30,5 @@ 1.8 4.1.0 - guice-intro + guice diff --git a/guice-intro/src/main/java/com/baeldung/examples/RunGuice.java b/guice/src/main/java/com/baeldung/examples/RunGuice.java similarity index 76% rename from guice-intro/src/main/java/com/baeldung/examples/RunGuice.java rename to guice/src/main/java/com/baeldung/examples/RunGuice.java index b4b3e8571e..660952f325 100644 --- a/guice-intro/src/main/java/com/baeldung/examples/RunGuice.java +++ b/guice/src/main/java/com/baeldung/examples/RunGuice.java @@ -1,36 +1,32 @@ - -package com.baeldung.examples; - -import com.baeldung.examples.guice.Communication; -import com.baeldung.examples.guice.binding.AOPModule; -import com.baeldung.examples.guice.modules.BasicModule; -import com.google.inject.Guice; -import com.google.inject.Injector; -import java.util.Scanner; - -/** - * - * @author Baeldung - */ -public class RunGuice { - - public static void main(String[] args) { - Injector injector = Guice.createInjector(new BasicModule(), new AOPModule()); - Communication comms = injector.getInstance(Communication.class); - Scanner scanner = new Scanner(System.in); - System.out.println("Enter your message to be sent; press Q to quit and P to print the message log"); - while (true) { - String input = scanner.nextLine(); - if (input.equalsIgnoreCase("q")) { - System.exit(0); - } - if (input.equalsIgnoreCase("p")) { - comms.print(); - } else { - comms.sendMessage(input); - } - - } - - } -} + +package com.baeldung.examples; + +import com.baeldung.examples.guice.Communication; +import com.baeldung.examples.guice.binding.AOPModule; +import com.baeldung.examples.guice.modules.BasicModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import java.util.Scanner; + +/** + * + * @author baeldung + */ +public class RunGuice { + + public static void main(String[] args) { + Injector injector = Guice.createInjector(new BasicModule(), new AOPModule()); + Communication comms = injector.getInstance(Communication.class); + Scanner scanner = new Scanner(System.in); + while (true) { + String input = scanner.nextLine(); + if (input.equalsIgnoreCase("q")) { + System.exit(0); + } else { + comms.sendMessage(input); + } + + } + + } +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/Communication.java b/guice/src/main/java/com/baeldung/examples/guice/Communication.java similarity index 54% rename from guice-intro/src/main/java/com/baeldung/examples/guice/Communication.java rename to guice/src/main/java/com/baeldung/examples/guice/Communication.java index c4b17b57d2..464e0c641d 100644 --- a/guice-intro/src/main/java/com/baeldung/examples/guice/Communication.java +++ b/guice/src/main/java/com/baeldung/examples/guice/Communication.java @@ -1,57 +1,40 @@ - -package com.baeldung.examples.guice; - -import com.google.inject.Inject; -import com.google.inject.name.Named; -import java.util.Date; -import java.util.LinkedList; -import java.util.Queue; -import java.util.logging.Logger; - -/** - * - * @author Baeldung - */ -public class Communication { - - final Date start = new Date(); - - @Inject - private Logger logger; - - private Queue messageLog; - - @Named("CommsUUID") - private String commsID; - - @Inject - private DefaultCommunicator communicator; - - public Communication(Boolean keepRecords) { - if (keepRecords) { - messageLog = new LinkedList(); - } - } - - public boolean sendMessage(String message) { - if (!message.isEmpty() && messageLog != null) { - messageLog.add(message); - } - return communicator.sendMessage(message); - } - - public void print() { - if (messageLog != null) { - for (String message : messageLog) { - logger.info(message); - } - } else { - logger.info("Message logging wasn't enabled"); - } - } - - public DefaultCommunicator getCommunicator() { - return this.communicator; - } - -} + +package com.baeldung.examples.guice; + +import com.google.inject.Inject; +import com.google.inject.name.Named; +import java.util.Date; +import java.util.LinkedList; +import java.util.Queue; +import java.util.logging.Logger; + +/** + * + * @author baeldung + */ +public class Communication { + + final Date start = new Date(); + + @Inject + private Logger logger; + + @Inject + private DefaultCommunicator communicator; + + public Communication(Boolean keepRecords) { + if (keepRecords) { + System.out.println("keeping records"); + } + } + + public boolean sendMessage(String message) { + + return communicator.sendMessage(message); + } + + public DefaultCommunicator getCommunicator() { + return this.communicator; + } + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/CommunicationMode.java b/guice/src/main/java/com/baeldung/examples/guice/CommunicationMode.java similarity index 95% rename from guice-intro/src/main/java/com/baeldung/examples/guice/CommunicationMode.java rename to guice/src/main/java/com/baeldung/examples/guice/CommunicationMode.java index 444b775478..7a36f0c276 100644 --- a/guice-intro/src/main/java/com/baeldung/examples/guice/CommunicationMode.java +++ b/guice/src/main/java/com/baeldung/examples/guice/CommunicationMode.java @@ -1,12 +1,12 @@ - -package com.baeldung.examples.guice; - -import com.baeldung.examples.guice.constant.CommunicationModel; - -public interface CommunicationMode { - - public CommunicationModel getMode(); - - public boolean sendMessage(String message); - -} + +package com.baeldung.examples.guice; + +import com.baeldung.examples.guice.constant.CommunicationModel; + +public interface CommunicationMode { + + public CommunicationModel getMode(); + + public boolean sendMessage(String message); + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/DefaultCommunicator.java b/guice/src/main/java/com/baeldung/examples/guice/DefaultCommunicator.java similarity index 96% rename from guice-intro/src/main/java/com/baeldung/examples/guice/DefaultCommunicator.java rename to guice/src/main/java/com/baeldung/examples/guice/DefaultCommunicator.java index 423c24f789..24e0c28dd1 100644 --- a/guice-intro/src/main/java/com/baeldung/examples/guice/DefaultCommunicator.java +++ b/guice/src/main/java/com/baeldung/examples/guice/DefaultCommunicator.java @@ -1,48 +1,51 @@ - -package com.baeldung.examples.guice; - -import com.baeldung.examples.guice.marker.Communicator; -import com.google.inject.Inject; -import com.google.inject.name.Named; - - -public class DefaultCommunicator implements Communicator { - - private CommunicationMode defaultCommsMode; - @Inject - @Named("SMSComms") - CommunicationMode smsCommsMode; - @Inject - @Named("EmailComms") - CommunicationMode emailCommsMode; - @Inject - @Named("IMComms") - CommunicationMode imCommsMode; - - protected DefaultCommunicator(CommunicationMode defaultComms) { - this.defaultCommsMode = defaultComms; - } - - public DefaultCommunicator() { - - } - - public boolean sendMessage(String message) { - boolean sent = false; - if (defaultCommsMode != null) { - sent = sendMessageByDefault(message); - } else { - sent = smsCommsMode.sendMessage(message); - } - return sent; - } - - private boolean sendMessageByDefault(String message) { - boolean sent = false; - if (message != null && !message.trim().equals("")) { - return defaultCommsMode.sendMessage(message); - } - return sent; - } - -} + +package com.baeldung.examples.guice; + +import com.baeldung.examples.guice.marker.Communicator; +import com.google.inject.Inject; +import com.google.inject.name.Named; + +/** + * + * @author baeldung + */ +public class DefaultCommunicator implements Communicator { + + private CommunicationMode defaultCommsMode; + @Inject + @Named("SMSComms") + CommunicationMode smsCommsMode; + @Inject + @Named("EmailComms") + CommunicationMode emailCommsMode; + @Inject + @Named("IMComms") + CommunicationMode imCommsMode; + + protected DefaultCommunicator(CommunicationMode defaultComms) { + this.defaultCommsMode = defaultComms; + } + + public DefaultCommunicator() { + + } + + public boolean sendMessage(String message) { + boolean sent = false; + if (defaultCommsMode != null) { + sent = sendMessageByDefault(message); + } else { + sent = smsCommsMode.sendMessage(message); + } + return sent; + } + + private boolean sendMessageByDefault(String message) { + boolean sent = false; + if (message != null && !message.trim().equals("")) { + return defaultCommsMode.sendMessage(message); + } + return sent; + } + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/EmailCommunicationMode.java b/guice/src/main/java/com/baeldung/examples/guice/EmailCommunicationMode.java similarity index 93% rename from guice-intro/src/main/java/com/baeldung/examples/guice/EmailCommunicationMode.java rename to guice/src/main/java/com/baeldung/examples/guice/EmailCommunicationMode.java index 642ee7ace0..06e77a58e2 100644 --- a/guice-intro/src/main/java/com/baeldung/examples/guice/EmailCommunicationMode.java +++ b/guice/src/main/java/com/baeldung/examples/guice/EmailCommunicationMode.java @@ -1,23 +1,24 @@ -package com.baeldung.examples.guice; - -import com.baeldung.examples.guice.aop.MessageSentLoggable; -import com.baeldung.examples.guice.constant.CommunicationModel; - -/** - * - * @author Baekdung - */ -public class EmailCommunicationMode implements CommunicationMode { - - @Override - public CommunicationModel getMode() { - return CommunicationModel.EMAIL; - } - - @Override - @MessageSentLoggable - public boolean sendMessage(String Message) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - -} + +package com.baeldung.examples.guice; + +import com.baeldung.examples.guice.aop.MessageSentLoggable; +import com.baeldung.examples.guice.constant.CommunicationModel; + +/** + * + * @author baeldung + */ +public class EmailCommunicationMode implements CommunicationMode { + + @Override + public CommunicationModel getMode() { + return CommunicationModel.EMAIL; + } + + @Override + @MessageSentLoggable + public boolean sendMessage(String Message) { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/IMCommunicationMode.java b/guice/src/main/java/com/baeldung/examples/guice/IMCommunicationMode.java similarity index 92% rename from guice-intro/src/main/java/com/baeldung/examples/guice/IMCommunicationMode.java rename to guice/src/main/java/com/baeldung/examples/guice/IMCommunicationMode.java index 9f34e9a241..42b0c82b90 100644 --- a/guice-intro/src/main/java/com/baeldung/examples/guice/IMCommunicationMode.java +++ b/guice/src/main/java/com/baeldung/examples/guice/IMCommunicationMode.java @@ -1,30 +1,30 @@ - -package com.baeldung.examples.guice; - -import com.baeldung.examples.guice.aop.MessageSentLoggable; -import com.baeldung.examples.guice.constant.CommunicationModel; -import com.google.inject.Inject; -import java.util.logging.Logger; - -/** - * - * @author Baeldung - */ -public class IMCommunicationMode implements CommunicationMode { - - @Inject - private Logger logger; - - @Override - public CommunicationModel getMode() { - return CommunicationModel.IM; - } - - @Override - @MessageSentLoggable - public boolean sendMessage(String message) { - logger.info("IM Message Sent"); - return true; - } - -} + +package com.baeldung.examples.guice; + +import com.baeldung.examples.guice.aop.MessageSentLoggable; +import com.baeldung.examples.guice.constant.CommunicationModel; +import com.google.inject.Inject; +import java.util.logging.Logger; + +/** + * + * @author baeldung + */ +public class IMCommunicationMode implements CommunicationMode { + + @Inject + private Logger logger; + + @Override + public CommunicationModel getMode() { + return CommunicationModel.IM; + } + + @Override + @MessageSentLoggable + public boolean sendMessage(String message) { + logger.info("IM Message Sent"); + return true; + } + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/SMSCommunicationMode.java b/guice/src/main/java/com/baeldung/examples/guice/SMSCommunicationMode.java similarity index 92% rename from guice-intro/src/main/java/com/baeldung/examples/guice/SMSCommunicationMode.java rename to guice/src/main/java/com/baeldung/examples/guice/SMSCommunicationMode.java index 251e249971..7a30e51f10 100644 --- a/guice-intro/src/main/java/com/baeldung/examples/guice/SMSCommunicationMode.java +++ b/guice/src/main/java/com/baeldung/examples/guice/SMSCommunicationMode.java @@ -1,29 +1,30 @@ -package com.baeldung.examples.guice; - -import com.baeldung.examples.guice.aop.MessageSentLoggable; -import com.baeldung.examples.guice.constant.CommunicationModel; -import com.google.inject.Inject; -import java.util.logging.Logger; - -/** - * - * @author Baeldung - */ -public class SMSCommunicationMode implements CommunicationMode { - - @Inject - private Logger logger; - - @Override - public CommunicationModel getMode() { - return CommunicationModel.SMS; - } - - @Override - @MessageSentLoggable - public boolean sendMessage(String message) { - logger.info("SMS message sent"); - return true; - } - -} + +package com.baeldung.examples.guice; + +import com.baeldung.examples.guice.aop.MessageSentLoggable; +import com.baeldung.examples.guice.constant.CommunicationModel; +import com.google.inject.Inject; +import java.util.logging.Logger; + +/** + * + * @author baeldung + */ +public class SMSCommunicationMode implements CommunicationMode { + + @Inject + private Logger logger; + + @Override + public CommunicationModel getMode() { + return CommunicationModel.SMS; + } + + @Override + @MessageSentLoggable + public boolean sendMessage(String message) { + logger.info("SMS message sent"); + return true; + } + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/aop/MessageLogger.java b/guice/src/main/java/com/baeldung/examples/guice/aop/MessageLogger.java similarity index 91% rename from guice-intro/src/main/java/com/baeldung/examples/guice/aop/MessageLogger.java rename to guice/src/main/java/com/baeldung/examples/guice/aop/MessageLogger.java index 8926dfa714..379cd5f18b 100644 --- a/guice-intro/src/main/java/com/baeldung/examples/guice/aop/MessageLogger.java +++ b/guice/src/main/java/com/baeldung/examples/guice/aop/MessageLogger.java @@ -1,22 +1,24 @@ -package com.baeldung.examples.guice.aop; - -import java.util.logging.Logger; -import org.aopalliance.intercept.MethodInterceptor; -import org.aopalliance.intercept.MethodInvocation; - -/** - * - * @author Baeldung - */ -public class MessageLogger implements MethodInterceptor { - - @Override - public Object invoke(MethodInvocation invocation) throws Throwable { - Object[] objectArray = invocation.getArguments(); - int i = 0; - for (Object object : objectArray) { - Logger.getAnonymousLogger().info("Sending message: " + object.toString()); - } - return invocation.proceed(); - } -} + +package com.baeldung.examples.guice.aop; + +import com.google.inject.Inject; +import java.util.logging.Logger; +import org.aopalliance.intercept.MethodInterceptor; +import org.aopalliance.intercept.MethodInvocation; + +/** + * + * @author baeldung + */ +public class MessageLogger implements MethodInterceptor { + + @Override + public Object invoke(MethodInvocation invocation) throws Throwable { + Object[] objectArray = invocation.getArguments(); + int i = 0; + for (Object object : objectArray) { + Logger.getAnonymousLogger().info("Sending message: " + object.toString()); + } + return invocation.proceed(); + } +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/aop/MessageSentLoggable.java b/guice/src/main/java/com/baeldung/examples/guice/aop/MessageSentLoggable.java similarity index 89% rename from guice-intro/src/main/java/com/baeldung/examples/guice/aop/MessageSentLoggable.java rename to guice/src/main/java/com/baeldung/examples/guice/aop/MessageSentLoggable.java index cacf3bde7c..431c4bc0ce 100644 --- a/guice-intro/src/main/java/com/baeldung/examples/guice/aop/MessageSentLoggable.java +++ b/guice/src/main/java/com/baeldung/examples/guice/aop/MessageSentLoggable.java @@ -1,16 +1,17 @@ -package com.baeldung.examples.guice.aop; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * @author Baeldung - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) -public @interface MessageSentLoggable { - -} + +package com.baeldung.examples.guice.aop; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * + * @author baeldung + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface MessageSentLoggable { + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/binding/AOPModule.java b/guice/src/main/java/com/baeldung/examples/guice/binding/AOPModule.java similarity index 92% rename from guice-intro/src/main/java/com/baeldung/examples/guice/binding/AOPModule.java rename to guice/src/main/java/com/baeldung/examples/guice/binding/AOPModule.java index dc9d258efa..b41dcf16e5 100644 --- a/guice-intro/src/main/java/com/baeldung/examples/guice/binding/AOPModule.java +++ b/guice/src/main/java/com/baeldung/examples/guice/binding/AOPModule.java @@ -1,22 +1,23 @@ -package com.baeldung.examples.guice.binding; - -import com.baeldung.examples.guice.aop.MessageLogger; -import com.baeldung.examples.guice.aop.MessageSentLoggable; -import com.google.inject.AbstractModule; -import com.google.inject.matcher.Matchers; - -/** - * - * @author Baeldung - */ -public class AOPModule extends AbstractModule { - - @Override - protected void configure() { - bindInterceptor(Matchers.any(), - Matchers.annotatedWith(MessageSentLoggable.class), - new MessageLogger() - ); - } - -} + +package com.baeldung.examples.guice.binding; + +import com.baeldung.examples.guice.aop.MessageLogger; +import com.baeldung.examples.guice.aop.MessageSentLoggable; +import com.google.inject.AbstractModule; +import com.google.inject.matcher.Matchers; + +/** + * + * @author baeldung + */ +public class AOPModule extends AbstractModule { + + @Override + protected void configure() { + bindInterceptor(Matchers.any(), + Matchers.annotatedWith(MessageSentLoggable.class), + new MessageLogger() + ); + } + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/binding/BasicModule.java b/guice/src/main/java/com/baeldung/examples/guice/binding/BasicModule.java similarity index 96% rename from guice-intro/src/main/java/com/baeldung/examples/guice/binding/BasicModule.java rename to guice/src/main/java/com/baeldung/examples/guice/binding/BasicModule.java index 9168195130..1cd9d624ab 100644 --- a/guice-intro/src/main/java/com/baeldung/examples/guice/binding/BasicModule.java +++ b/guice/src/main/java/com/baeldung/examples/guice/binding/BasicModule.java @@ -1,36 +1,37 @@ -package com.baeldung.examples.guice.binding; - -import com.baeldung.examples.guice.Communication; -import com.baeldung.examples.guice.CommunicationMode; -import com.baeldung.examples.guice.DefaultCommunicator; -import com.baeldung.examples.guice.EmailCommunicationMode; -import com.baeldung.examples.guice.IMCommunicationMode; -import com.baeldung.examples.guice.SMSCommunicationMode; -import com.google.inject.AbstractModule; -import com.google.inject.name.Names; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * - * @author Baeldung - */ -public class BasicModule extends AbstractModule { - - @Override - protected void configure() { - try { - bind(Communication.class).toConstructor(Communication.class.getConstructor(Boolean.TYPE)); - } catch (NoSuchMethodException ex) { - Logger.getLogger(BasicModule.class.getName()).log(Level.SEVERE, null, ex); - } catch (SecurityException ex) { - Logger.getLogger(BasicModule.class.getName()).log(Level.SEVERE, null, ex); - } - bind(DefaultCommunicator.class).annotatedWith(Names.named("AnotherCommunicator")).to(DefaultCommunicator.class).asEagerSingleton(); - - bind(CommunicationMode.class).annotatedWith(Names.named("IMComms")).to(IMCommunicationMode.class); - bind(CommunicationMode.class).annotatedWith(Names.named("EmailComms")).to(EmailCommunicationMode.class); - bind(CommunicationMode.class).annotatedWith(Names.named("SMSComms")).to(SMSCommunicationMode.class); - } - -} + +package com.baeldung.examples.guice.binding; + +import com.baeldung.examples.guice.Communication; +import com.baeldung.examples.guice.CommunicationMode; +import com.baeldung.examples.guice.DefaultCommunicator; +import com.baeldung.examples.guice.EmailCommunicationMode; +import com.baeldung.examples.guice.IMCommunicationMode; +import com.baeldung.examples.guice.SMSCommunicationMode; +import com.google.inject.AbstractModule; +import com.google.inject.name.Names; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author baeldung + */ +public class BasicModule extends AbstractModule { + + @Override + protected void configure() { + try { + bind(Communication.class).toConstructor(Communication.class.getConstructor(Boolean.TYPE)); + } catch (NoSuchMethodException ex) { + Logger.getLogger(BasicModule.class.getName()).log(Level.SEVERE, null, ex); + } catch (SecurityException ex) { + Logger.getLogger(BasicModule.class.getName()).log(Level.SEVERE, null, ex); + } + bind(DefaultCommunicator.class).annotatedWith(Names.named("AnotherCommunicator")).to(DefaultCommunicator.class).asEagerSingleton(); + + bind(CommunicationMode.class).annotatedWith(Names.named("IMComms")).to(IMCommunicationMode.class); + bind(CommunicationMode.class).annotatedWith(Names.named("EmailComms")).to(EmailCommunicationMode.class); + bind(CommunicationMode.class).annotatedWith(Names.named("SMSComms")).to(SMSCommunicationMode.class); + } + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/constant/CommunicationModel.java b/guice/src/main/java/com/baeldung/examples/guice/constant/CommunicationModel.java similarity index 87% rename from guice-intro/src/main/java/com/baeldung/examples/guice/constant/CommunicationModel.java rename to guice/src/main/java/com/baeldung/examples/guice/constant/CommunicationModel.java index b9fa604a32..3483e9cefd 100644 --- a/guice-intro/src/main/java/com/baeldung/examples/guice/constant/CommunicationModel.java +++ b/guice/src/main/java/com/baeldung/examples/guice/constant/CommunicationModel.java @@ -1,16 +1,17 @@ -package com.baeldung.examples.guice.constant; - -/** - * - * @author Baeldung - */ -public enum CommunicationModel { - - EMAIL("Email"), SMS("SMS"), IM("IM"), PHONE("Phone"); - - final String name; - - CommunicationModel(String name) { - this.name = name; - } -} + +package com.baeldung.examples.guice.constant; + +/** + * + * @author baeldung + */ +public enum CommunicationModel { + + EMAIL("Email"), SMS("SMS"), IM("IM"), PHONE("Phone"); + + final String name; + + CommunicationModel(String name) { + this.name = name; + } +} diff --git a/guice/src/main/java/com/baeldung/examples/guice/marker/Communicator.java b/guice/src/main/java/com/baeldung/examples/guice/marker/Communicator.java new file mode 100644 index 0000000000..45c729a9a3 --- /dev/null +++ b/guice/src/main/java/com/baeldung/examples/guice/marker/Communicator.java @@ -0,0 +1,14 @@ +/* + * 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.examples.guice.marker; + +/** + * + * @author Tayo + */ +public interface Communicator { + +} diff --git a/guice-intro/src/main/java/com/baeldung/examples/guice/modules/BasicModule.java b/guice/src/main/java/com/baeldung/examples/guice/modules/BasicModule.java similarity index 96% rename from guice-intro/src/main/java/com/baeldung/examples/guice/modules/BasicModule.java rename to guice/src/main/java/com/baeldung/examples/guice/modules/BasicModule.java index 47b3e2e573..f27d8b3a53 100644 --- a/guice-intro/src/main/java/com/baeldung/examples/guice/modules/BasicModule.java +++ b/guice/src/main/java/com/baeldung/examples/guice/modules/BasicModule.java @@ -1,37 +1,38 @@ -package com.baeldung.examples.guice.modules; - -import com.baeldung.examples.guice.Communication; -import com.baeldung.examples.guice.CommunicationMode; -import com.baeldung.examples.guice.DefaultCommunicator; -import com.baeldung.examples.guice.EmailCommunicationMode; -import com.baeldung.examples.guice.IMCommunicationMode; -import com.baeldung.examples.guice.SMSCommunicationMode; -import com.google.inject.AbstractModule; -import com.google.inject.name.Names; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * - * @author Baeldung - */ -public class BasicModule extends AbstractModule { - - @Override - protected void configure() { - try { - bind(Communication.class).toConstructor(Communication.class.getConstructor(Boolean.class)); - bind(Boolean.class).toInstance(true); - } catch (NoSuchMethodException ex) { - Logger.getLogger(com.baeldung.examples.guice.binding.BasicModule.class.getName()).log(Level.SEVERE, null, ex); - } catch (SecurityException ex) { - Logger.getLogger(com.baeldung.examples.guice.binding.BasicModule.class.getName()).log(Level.SEVERE, null, ex); - } - bind(DefaultCommunicator.class).annotatedWith(Names.named("AnotherCommunicator")).to(DefaultCommunicator.class).asEagerSingleton(); - - bind(CommunicationMode.class).annotatedWith(Names.named("IMComms")).to(IMCommunicationMode.class); - bind(CommunicationMode.class).annotatedWith(Names.named("EmailComms")).to(EmailCommunicationMode.class); - bind(CommunicationMode.class).annotatedWith(Names.named("SMSComms")).to(SMSCommunicationMode.class); - } - -} + +package com.baeldung.examples.guice.modules; + +import com.baeldung.examples.guice.Communication; +import com.baeldung.examples.guice.CommunicationMode; +import com.baeldung.examples.guice.DefaultCommunicator; +import com.baeldung.examples.guice.EmailCommunicationMode; +import com.baeldung.examples.guice.IMCommunicationMode; +import com.baeldung.examples.guice.SMSCommunicationMode; +import com.google.inject.AbstractModule; +import com.google.inject.name.Names; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author baeldung + */ +public class BasicModule extends AbstractModule { + + @Override + protected void configure() { + try { + bind(Communication.class).toConstructor(Communication.class.getConstructor(Boolean.class)); + bind(Boolean.class).toInstance(true); + } catch (NoSuchMethodException ex) { + Logger.getLogger(com.baeldung.examples.guice.binding.BasicModule.class.getName()).log(Level.SEVERE, null, ex); + } catch (SecurityException ex) { + Logger.getLogger(com.baeldung.examples.guice.binding.BasicModule.class.getName()).log(Level.SEVERE, null, ex); + } + bind(DefaultCommunicator.class).annotatedWith(Names.named("AnotherCommunicator")).to(DefaultCommunicator.class).asEagerSingleton(); + + bind(CommunicationMode.class).annotatedWith(Names.named("IMComms")).to(IMCommunicationMode.class); + bind(CommunicationMode.class).annotatedWith(Names.named("EmailComms")).to(EmailCommunicationMode.class); + bind(CommunicationMode.class).annotatedWith(Names.named("SMSComms")).to(SMSCommunicationMode.class); + } + +} diff --git a/hbase/README.md b/hbase/README.md new file mode 100644 index 0000000000..df2683b27a --- /dev/null +++ b/hbase/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [HBase with Java](http://www.baeldung.com/hbase) diff --git a/java-websocket/README.md b/java-websocket/README.md new file mode 100644 index 0000000000..f9f0784043 --- /dev/null +++ b/java-websocket/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [A Guide to the Java API for WebSocket](http://www.baeldung.com/java-websockets) diff --git a/java-websocket/pom.xml b/java-websocket/pom.xml index 929e6491fd..e19706b4d9 100644 --- a/java-websocket/pom.xml +++ b/java-websocket/pom.xml @@ -17,6 +17,7 @@ javax.websocket javax.websocket-api 1.1 + provided com.google.code.gson diff --git a/java-websocket/src/main/java/com/baeldung/websocket/MessageDecoder.java b/java-websocket/src/main/java/com/baeldung/websocket/MessageDecoder.java index 29ae5b93e6..3bb3c4391d 100644 --- a/java-websocket/src/main/java/com/baeldung/websocket/MessageDecoder.java +++ b/java-websocket/src/main/java/com/baeldung/websocket/MessageDecoder.java @@ -8,9 +8,11 @@ import com.baeldung.model.Message; import com.google.gson.Gson; public class MessageDecoder implements Decoder.Text { + + private static Gson gson = new Gson(); + @Override public Message decode(String s) throws DecodeException { - Gson gson = new Gson(); Message message = gson.fromJson(s, Message.class); return message; } diff --git a/java-websocket/src/main/java/com/baeldung/websocket/MessageEncoder.java b/java-websocket/src/main/java/com/baeldung/websocket/MessageEncoder.java index bfecc87a96..6e7ba06ff0 100644 --- a/java-websocket/src/main/java/com/baeldung/websocket/MessageEncoder.java +++ b/java-websocket/src/main/java/com/baeldung/websocket/MessageEncoder.java @@ -8,9 +8,11 @@ import com.baeldung.model.Message; import com.google.gson.Gson; public class MessageEncoder implements Encoder.Text { + + private static Gson gson = new Gson(); + @Override public String encode(Message message) throws EncodeException { - Gson gson = new Gson(); String json = gson.toJson(message); return json; } diff --git a/java-websocket/src/main/webapp/websocket.js b/java-websocket/src/main/webapp/websocket.js index 39e5687f0c..c23b2722fe 100644 --- a/java-websocket/src/main/webapp/websocket.js +++ b/java-websocket/src/main/webapp/websocket.js @@ -2,8 +2,11 @@ var ws; function connect() { var username = document.getElementById("username").value; - ws = new WebSocket("ws://" + document.location.host + "/java-websocket/chat/" + username); - + + var host = document.location.host; + var pathname = document.location.pathname; + + ws = new WebSocket("ws://" +host + pathname + "chat/" + username); ws.onmessage = function(event) { var log = document.getElementById("log"); diff --git a/jee7/src/main/java/com/baeldung/javaeeannotations/LoggingFilter.java b/jee7/src/main/java/com/baeldung/javaeeannotations/LogInFilter.java similarity index 88% rename from jee7/src/main/java/com/baeldung/javaeeannotations/LoggingFilter.java rename to jee7/src/main/java/com/baeldung/javaeeannotations/LogInFilter.java index 97de5ec0de..4e4aef2672 100644 --- a/jee7/src/main/java/com/baeldung/javaeeannotations/LoggingFilter.java +++ b/jee7/src/main/java/com/baeldung/javaeeannotations/LogInFilter.java @@ -1,36 +1,36 @@ -package com.baeldung.javaeeannotations; - -import java.io.IOException; - -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.annotation.WebFilter; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -@WebFilter( - urlPatterns = "/bankAccount/*", - filterName = "LoggingFilter", - description = "Filter all account transaction URLs" - ) -public class LoggingFilter implements javax.servlet.Filter { - @Override - public void init(FilterConfig filterConfig) throws ServletException { - } - - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - HttpServletRequest req = (HttpServletRequest) request; - HttpServletResponse res = (HttpServletResponse) response; - - res.sendRedirect(req.getContextPath() + "/login.jsp"); - chain.doFilter(request, response); - } - - @Override - public void destroy() { - } - -} +package com.baeldung.javaeeannotations; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@WebFilter( + urlPatterns = "/bankAccount/*", + filterName = "LogInFilter", + description = "Filter all account transaction URLs" + ) +public class LogInFilter implements javax.servlet.Filter { + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse res = (HttpServletResponse) response; + + res.sendRedirect(req.getContextPath() + "/login.jsp"); + chain.doFilter(request, response); + } + + @Override + public void destroy() { + } + +} diff --git a/jooq/README.md b/jooq/README.md new file mode 100644 index 0000000000..2f09cab46b --- /dev/null +++ b/jooq/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [Introduction to jOOL](http://www.baeldung.com/jool) diff --git a/jws/.gitignore b/jws/.gitignore new file mode 100644 index 0000000000..6346853947 --- /dev/null +++ b/jws/.gitignore @@ -0,0 +1,7 @@ +/target/ +.classpath +.project +.settings +/.settings/ +/settings/ +.tern-project diff --git a/jws/java-core-samples-lib/jardiff.jar b/jws/java-core-samples-lib/jardiff.jar new file mode 100644 index 0000000000..08b5bb61ab Binary files /dev/null and b/jws/java-core-samples-lib/jardiff.jar differ diff --git a/jws/java-core-samples-lib/jnlp-servlet.jar b/jws/java-core-samples-lib/jnlp-servlet.jar new file mode 100644 index 0000000000..c27167c647 Binary files /dev/null and b/jws/java-core-samples-lib/jnlp-servlet.jar differ diff --git a/jws/pom.xml b/jws/pom.xml new file mode 100644 index 0000000000..dea98fb41a --- /dev/null +++ b/jws/pom.xml @@ -0,0 +1,86 @@ + + + 4.0.0 + com.example + jws + war + 0.0.1-SNAPSHOT + + jws-example + + + 3.0.2 + 3.0.0 + 7.0 + 7.0 + + + + + javax.jnlp + jnlp-servlet + ${jnlp-servlet.version} + system + ${project.basedir}/java-core-samples-lib/jnlp-servlet.jar + + + javax.jnlp + jardiff + ${jardiff.version} + system + ${project.basedir}/java-core-samples-lib/jardiff.jar + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + ${maven-jar-plugin.version} + + + compile + + jar + + + + + com.example.Hello + + + ${project.basedir}/target/jws + + + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + + package + + + + + + ${project.basedir}/java-core-samples-lib/ + + **/*.jar + + WEB-INF/lib + + + + + + ${project.artifactId} + + + diff --git a/jws/src/main/java/com/example/Hello.java b/jws/src/main/java/com/example/Hello.java new file mode 100644 index 0000000000..3479277ace --- /dev/null +++ b/jws/src/main/java/com/example/Hello.java @@ -0,0 +1,15 @@ +package com.example; + +import javax.swing.*; + +public class Hello { + public static void main(String[] args) { + JFrame f = new JFrame("main"); + f.setSize(200, 100); + f.setLocationRelativeTo(null); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + JLabel label = new JLabel("Hello, world!"); + f.add(label); + f.setVisible(true); + } +} diff --git a/jws/src/main/webapp/WEB-INF/web.xml b/jws/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..18f29ddd12 --- /dev/null +++ b/jws/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,24 @@ + + + Java Web Start + JNLP Example for Java Web Start Article + + + JnlpDownloadServlet + jnlp.sample.servlet.JnlpDownloadServlet + + + JnlpDownloadServlet + *.jar + + + JnlpDownloadServlet + *.jnlp + + + + index.html + + diff --git a/jws/src/main/webapp/hello.jnlp b/jws/src/main/webapp/hello.jnlp new file mode 100644 index 0000000000..950c0d716f --- /dev/null +++ b/jws/src/main/webapp/hello.jnlp @@ -0,0 +1,12 @@ + + + + Hello + Example + + + + + + + diff --git a/jws/src/main/webapp/index.html b/jws/src/main/webapp/index.html new file mode 100644 index 0000000000..212607b850 --- /dev/null +++ b/jws/src/main/webapp/index.html @@ -0,0 +1,10 @@ + + +Hello World JNLP + + +

+ Launch the example +

+ + diff --git a/kotlin/README.md b/kotlin/README.md index 6447a26f5c..ceebde4573 100644 --- a/kotlin/README.md +++ b/kotlin/README.md @@ -1,3 +1,4 @@ ## Relevant articles: - [Introduction to the Kotlin Language](http://www.baeldung.com/kotlin) +- [A guide to the “when{}” block in Kotlin](http://www.baeldung.com/kotlin-when) diff --git a/libraries/README.md b/libraries/README.md new file mode 100644 index 0000000000..a8ecf56cc2 --- /dev/null +++ b/libraries/README.md @@ -0,0 +1,14 @@ +### Relevant articles + +- [Intro to Jasypt](http://www.baeldung.com/jasypt) +- [Array Processing with Apache Commons Lang 3](http://www.baeldung.com/array-processing-commons-lang) +- [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) + + +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. + +The code examples related to different libraries should go in a new package. + +Remember, for advanced libraries like JUnit, Jackson, etc. we already have separate modules. Please make sure to have a look at the existing modules in such cases. diff --git a/libraries/pom.xml b/libraries/pom.xml index ee93ee934f..85c777b12c 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -1,7 +1,6 @@ - + parent-modules com.baeldung @@ -31,18 +30,54 @@ cglib ${cglib.version}
+ + org.apache.commons + commons-lang3 + ${commons-lang.version} + junit junit ${junit.version} test + + org.jasypt + jasypt + ${jasypt.version} + + + org.javatuples + javatuples + ${javatuples.version} + + + org.javassist + javassist + ${javaassist.version} + + + + org.assertj + assertj-core + ${assertj.version} + + + org.skyscreamer + jsonassert + ${jsonassert.version} + 3.2.4 + 3.5 4.12 + 1.9.2 + 1.2 + 3.21.0-GA + 3.6.2 + 1.4.0 - \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/javasisst/Point.java b/libraries/src/main/java/com/baeldung/javasisst/Point.java new file mode 100644 index 0000000000..7e5c1cedd5 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/javasisst/Point.java @@ -0,0 +1,17 @@ +package com.baeldung.javasisst; + + +public class Point { + public int x = 0; + public int y = 0; + + public Point(int x, int y) { + this.x = x; + this.y = y; + } + + public void move(int x, int y) { + this.x = x; + this.y = y; + } +} diff --git a/libraries/src/main/java/com/baeldung/javasisst/ThreeDimensionalPoint.java b/libraries/src/main/java/com/baeldung/javasisst/ThreeDimensionalPoint.java new file mode 100644 index 0000000000..fb24d4b85d --- /dev/null +++ b/libraries/src/main/java/com/baeldung/javasisst/ThreeDimensionalPoint.java @@ -0,0 +1,19 @@ +package com.baeldung.javasisst; + + +public class ThreeDimensionalPoint { + public int x = 0; + public int y = 0; + public int z = 0; + + public ThreeDimensionalPoint(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } + + public void move(int x, int y) { + this.x = x; + this.y = y; + } +} diff --git a/libraries/src/test/java/com/baeldung/cglib/proxy/README.md b/libraries/src/test/java/com/baeldung/cglib/proxy/README.md new file mode 100644 index 0000000000..abeabc6162 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/cglib/proxy/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [Introduction to cglib](http://www.baeldung.com/cglib) diff --git a/apache-commons/src/test/java/com/baeldung/commons/lang3/ArrayUtilsTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/ArrayUtilsTest.java similarity index 100% rename from apache-commons/src/test/java/com/baeldung/commons/lang3/ArrayUtilsTest.java rename to libraries/src/test/java/com/baeldung/commons/lang3/ArrayUtilsTest.java diff --git a/apache-commons/src/test/java/com/baeldung/commons/lang3/StringUtilsTest.java b/libraries/src/test/java/com/baeldung/commons/lang3/StringUtilsTest.java similarity index 100% rename from apache-commons/src/test/java/com/baeldung/commons/lang3/StringUtilsTest.java rename to libraries/src/test/java/com/baeldung/commons/lang3/StringUtilsTest.java diff --git a/jasypt/src/test/java/org/baeldung/jasypt/JasyptTest.java b/libraries/src/test/java/com/baeldung/jasypt/JasyptTest.java similarity index 66% rename from jasypt/src/test/java/org/baeldung/jasypt/JasyptTest.java rename to libraries/src/test/java/com/baeldung/jasypt/JasyptTest.java index c4bed5de83..fbfa7f823d 100644 --- a/jasypt/src/test/java/org/baeldung/jasypt/JasyptTest.java +++ b/libraries/src/test/java/com/baeldung/jasypt/JasyptTest.java @@ -1,4 +1,4 @@ -package org.baeldung.jasypt; +package com.baeldung.jasypt; import org.jasypt.encryption.pbe.PooledPBEStringEncryptor; @@ -8,27 +8,25 @@ import org.jasypt.util.text.BasicTextEncryptor; import org.junit.Ignore; import org.junit.Test; -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertNotSame; -import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.*; import static junit.framework.TestCase.assertEquals; public class JasyptTest { @Test - public void givenTextPassword_whenDecrypt_thenCompareToEncrypted() { + public void givenTextPrivateData_whenDecrypt_thenCompareToEncrypted() { //given BasicTextEncryptor textEncryptor = new BasicTextEncryptor(); - String password = "secret-pass"; - textEncryptor.setPasswordCharArray("some-random-password".toCharArray()); + String privateData = "secret-data"; + textEncryptor.setPasswordCharArray("some-random-data".toCharArray()); //when - String myEncryptedText = textEncryptor.encrypt(password); - assertNotSame(password, myEncryptedText); //myEncryptedText can be save in db + String myEncryptedText = textEncryptor.encrypt(privateData); + assertNotSame(privateData, myEncryptedText); //myEncryptedText can be save in db //then String plainText = textEncryptor.decrypt(myEncryptedText); - assertEquals(plainText, password); + assertEquals(plainText, privateData); } @Test @@ -61,38 +59,38 @@ public class JasyptTest { @Test @Ignore("should have installed local_policy.jar") - public void givenTextPassword_whenDecrypt_thenCompareToEncryptedWithCustomAlgorithm() { + public void givenTextPrivateData_whenDecrypt_thenCompareToEncryptedWithCustomAlgorithm() { //given StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); - String password = "secret-pass"; - encryptor.setPassword("secret-pass"); + String privateData = "secret-data"; + encryptor.setPassword("some-random-data"); encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); //when String encryptedText = encryptor.encrypt("secret-pass"); - assertNotSame(password, encryptedText); + assertNotSame(privateData, encryptedText); //then String plainText = encryptor.decrypt(encryptedText); - assertEquals(plainText, password); + assertEquals(plainText, privateData); } @Test @Ignore("should have installed local_policy.jar") - public void givenTextPassword_whenDecryptOnHighPerformance_thenDecrypt(){ + public void givenTextPrivateData_whenDecryptOnHighPerformance_thenDecrypt(){ //given - String password = "secret-pass"; + String privateData = "secret-data"; PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); encryptor.setPoolSize(4); - encryptor.setPassword(password); + encryptor.setPassword("some-random-data"); encryptor.setAlgorithm("PBEWithMD5AndTripleDES"); //when - String encryptedText = encryptor.encrypt(password); - assertNotSame(password, encryptedText); + String encryptedText = encryptor.encrypt(privateData); + assertNotSame(privateData, encryptedText); //then String plainText = encryptor.decrypt(encryptedText); - assertEquals(plainText, password); + assertEquals(plainText, privateData); } } diff --git a/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java b/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java new file mode 100644 index 0000000000..da5ae02c56 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/javassist/JavasisstTest.java @@ -0,0 +1,119 @@ +package com.baeldung.javassist; + + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.NotFoundException; +import javassist.bytecode.*; +import org.junit.Test; + +import java.io.DataOutputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.lang.reflect.Field; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class JavasisstTest { + @Test + public void givenJavasisstAPI_whenConstructClass_thenGenerateAClassFile() throws CannotCompileException, IOException, ClassNotFoundException, IllegalAccessException, InstantiationException { + //given + String classNameWithPackage = "com.baeldung.JavassistGeneratedClass"; + ClassFile cf = new ClassFile(false, classNameWithPackage, null); + cf.setInterfaces(new String[]{"java.lang.Cloneable"}); + + FieldInfo f = new FieldInfo(cf.getConstPool(), "id", "I"); + f.setAccessFlags(AccessFlag.PUBLIC); + cf.addField(f); + + //when + String className = "JavassistGeneratedClass.class"; + cf.write(new DataOutputStream(new FileOutputStream(className))); + + //then + ClassPool classPool = ClassPool.getDefault(); + Field[] fields = classPool.makeClass(cf).toClass().getFields(); + assertEquals(fields[0].getName(), "id"); + + String classContent = new String(Files.readAllBytes(Paths.get(className))); + assertTrue(classContent.contains("java/lang/Cloneable")); + } + + @Test + public void givenJavaClass_whenLoadAtByJavassist_thenTraversWholeClass() throws NotFoundException, CannotCompileException, BadBytecode { + //given + ClassPool cp = ClassPool.getDefault(); + ClassFile cf = cp.get("com.baeldung.javasisst.Point").getClassFile(); + MethodInfo minfo = cf.getMethod("move"); + CodeAttribute ca = minfo.getCodeAttribute(); + CodeIterator ci = ca.iterator(); + + //when + List operations = new LinkedList<>(); + while (ci.hasNext()) { + int index = ci.next(); + int op = ci.byteAt(index); + operations.add(Mnemonic.OPCODE[op]); + } + + //then + assertEquals(operations, + Arrays.asList("aload_0", "iload_1", "putfield", "aload_0", "iload_2", "putfield", "return")); + + } + + @Test + public void givenTableOfInstructions_whenAddNewInstruction_thenShouldConstructProperSequence() throws NotFoundException, BadBytecode, CannotCompileException, IllegalAccessException, InstantiationException { + //given + ClassFile cf = ClassPool.getDefault().get("com.baeldung.javasisst.ThreeDimensionalPoint").getClassFile(); + + //when + FieldInfo f = new FieldInfo(cf.getConstPool(), "id", "I"); + f.setAccessFlags(AccessFlag.PUBLIC); + cf.addField(f); + + + ClassPool classPool = ClassPool.getDefault(); + Field[] fields = classPool.makeClass(cf).toClass().getFields(); + List fieldsList = Stream.of(fields).map(Field::getName).collect(Collectors.toList()); + assertTrue(fieldsList.contains("id")); + + } + + @Test + public void givenLoadedClass_whenAddConstructorToClass_shouldCreateClassWithConstructor() throws NotFoundException, CannotCompileException, BadBytecode { + //given + ClassFile cf = ClassPool.getDefault().get("com.baeldung.javasisst.Point").getClassFile(); + Bytecode code = new Bytecode(cf.getConstPool()); + code.addAload(0); + code.addInvokespecial("java/lang/Object", MethodInfo.nameInit, "()V"); + code.addReturn(null); + + //when + MethodInfo minfo = new MethodInfo(cf.getConstPool(), MethodInfo.nameInit, "()V"); + minfo.setCodeAttribute(code.toCodeAttribute()); + cf.addMethod(minfo); + + //then + CodeIterator ci = code.toCodeAttribute().iterator(); + List operations = new LinkedList<>(); + while (ci.hasNext()) { + int index = ci.next(); + int op = ci.byteAt(index); + operations.add(Mnemonic.OPCODE[op]); + } + + assertEquals(operations, + Arrays.asList("aload_0", "invokespecial", "return")); + + + } +} diff --git a/libraries/src/test/java/com/baeldung/javatuples/JavaTuplesTest.java b/libraries/src/test/java/com/baeldung/javatuples/JavaTuplesTest.java new file mode 100644 index 0000000000..af4308e188 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/javatuples/JavaTuplesTest.java @@ -0,0 +1,118 @@ +package com.baeldung.javatuples; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.List; + +import org.javatuples.KeyValue; +import org.javatuples.LabelValue; +import org.javatuples.Pair; +import org.javatuples.Quartet; +import org.javatuples.Triplet; +import org.javatuples.Unit; +import org.junit.Test; + +public class JavaTuplesTest { + + @SuppressWarnings("unused") + @Test + public void whenCreatingTuples_thenCreateTuples() { + Pair pair = new Pair("This is a pair", 55); + Triplet triplet = Triplet.with("hello", 23, 33.2); + + List collectionOfNames = Arrays.asList("john", "doe", "anne", "alex"); + Quartet quartet = Quartet.fromCollection(collectionOfNames); + + Pair pairFromList = Pair.fromIterable(collectionOfNames, 2); + + String[] names = new String[] { "john", "doe", "anne" }; + Triplet triplet2 = Triplet.fromArray(names); + } + + @Test + public void whenGetValuexFromTuples_thenRetriveValueWithType() { + Quartet quartet = Quartet.with("john", 72.5, 32, "1051 SW"); + + String name = quartet.getValue0(); + Integer age = quartet.getValue2(); + assertThat(name).isEqualTo("john"); + assertThat(age).isEqualTo(32); + } + + @Test + public void whenGetKeyValue_thenGetKeyValue() { + KeyValue keyValue = KeyValue.with(5, "F"); + Integer key = keyValue.getKey(); + String value = keyValue.getValue(); + + assertThat(key).isEqualTo(5); + assertThat(value).isEqualTo("F"); + } + + @Test + public void whenGetLabelValue_thenGetLabelValue() { + LabelValue labelValue = LabelValue.with(5, "F"); + Integer key = labelValue.getLabel(); + String value = labelValue.getValue(); + + assertThat(key).isEqualTo(5); + assertThat(value).isEqualTo("F"); + } + + @Test + public void whenGetValueFromTuples_thenRetriveValueWithoutType() { + Quartet quartet = Quartet.with("john", 72.5, 32, "1051 SW"); + + String name = (String) quartet.getValue(0); + Integer age = (Integer) quartet.getValue(2); + assertThat(name).isEqualTo("john"); + assertThat(age).isEqualTo(32); + } + + @Test + public void whenSetValueInTuple_thenGetANewTuple() { + Pair john = Pair.with("john", 32); + Pair alex = john.setAt0("alex"); + assertThat(john.toString()).isNotEqualTo(alex.toString()); + } + + @Test + public void whenAddNewElement_thenCreateNewTuple() { + Pair pair1 = Pair.with("john", 32); + Triplet triplet1 = pair1.add("1051 SW"); + assertThat(triplet1.contains("john")); + assertThat(triplet1.contains(32)); + assertThat(triplet1.contains("1051 SW")); + + Pair pair2 = Pair.with("alex", 45); + Quartet quartet2 = pair1.add(pair2); + assertThat(quartet2.containsAll(pair1)); + assertThat(quartet2.containsAll(pair2)); + + Quartet quartet1 = pair1.add("alex", 45); + assertThat(quartet1.containsAll("alex", "john", 32, 45)); + + Triplet triplet2 = pair1.addAt1("1051 SW"); + assertThat(triplet2.indexOf("john")).isEqualTo(0); + assertThat(triplet2.indexOf("1051 SW")).isEqualTo(1); + assertThat(triplet2.indexOf(32)).isEqualTo(2); + + Unit unit = pair1.removeFrom0(); + assertThat(unit.contains(32)); + } + + @Test + public void whenCallingToList_thenReturnList() { + Quartet quartet = Quartet.with("john", 72.5, 32, "1051 SW"); + List list = quartet.toList(); + assertThat(list.size()).isEqualTo(4); + } + + @Test + public void whenCallingToArray_thenReturnArray() { + Quartet quartet = Quartet.with("john", 72.5, 32, "1051 SW"); + Object[] array = quartet.toArray(); + assertThat(array.length).isEqualTo(4); + } +} diff --git a/libraries/src/test/java/com/baeldung/jsonassert/JsonAssertTest.java b/libraries/src/test/java/com/baeldung/jsonassert/JsonAssertTest.java new file mode 100644 index 0000000000..c169d83897 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/jsonassert/JsonAssertTest.java @@ -0,0 +1,115 @@ +package com.baeldung.jsonassert; + +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.Test; +import org.skyscreamer.jsonassert.Customization; +import org.skyscreamer.jsonassert.JSONAssert; +import org.skyscreamer.jsonassert.JSONCompareMode; +import org.skyscreamer.jsonassert.RegularExpressionValueMatcher; +import org.skyscreamer.jsonassert.comparator.ArraySizeComparator; +import org.skyscreamer.jsonassert.comparator.CustomComparator; + +public class JsonAssertTest { + + @Test + public void givenLenientode_whenAssertEqualsSameJsonString_thenPass() throws JSONException { + String actual = "{id:123,name:\"John\"}"; + JSONAssert.assertEquals("{id:123,name:\"John\"}", actual, JSONCompareMode.LENIENT); + + actual = "{id:123,name:\"John\",zip:\"33025\"}"; + JSONAssert.assertEquals("{id:123,name:\"John\"}", actual, JSONCompareMode.LENIENT); + } + + @Test + public void givenStrictMode_whenAssertNotEqualsExtendedJsonString_thenPass() throws JSONException { + String actual = "{id:123,name:\"John\"}"; + JSONAssert.assertNotEquals("{name:\"John\"}", actual, JSONCompareMode.STRICT); + } + + @Test + public void whenUsingCompareModeOrBoolean_thenBothAreSame() throws JSONException { + String actual = "{id:123,name:\"John\",zip:\"33025\"}"; + JSONAssert.assertEquals("{id:123,name:\"John\"}", actual, JSONCompareMode.LENIENT); + JSONAssert.assertEquals("{id:123,name:\"John\"}", actual, false); + + actual = "{id:123,name:\"John\"}"; + JSONAssert.assertNotEquals("{name:\"John\"}", actual, JSONCompareMode.STRICT); + JSONAssert.assertNotEquals("{name:\"John\"}", actual, true); + } + + @Test + public void givenDifferentOrderForJsonObject_whenAssertEquals_thenPass() throws JSONException { + String result = "{id:1,name:\"John\"}"; + + JSONAssert.assertEquals("{name:\"John\",id:1}", result, JSONCompareMode.STRICT); + JSONAssert.assertEquals("{name:\"John\",id:1}", result, JSONCompareMode.LENIENT); + } + + @Test + public void givenDifferentTypes_whenAssertEqualsSameValue_thenPass() throws JSONException { + JSONObject expected = new JSONObject(); + JSONObject actual = new JSONObject(); + expected.put("id", Integer.valueOf(12345)); + actual.put("id", Double.valueOf(12345)); + + JSONAssert.assertEquals(expected, actual, false); + JSONAssert.assertEquals(expected, actual, JSONCompareMode.LENIENT); + } + + @Test + public void givenNestedObjects_whenAssertEquals_thenPass() throws JSONException { + String result = "{id:1,name:\"Juergen\", address:{city:\"Hollywood\", " + + "state:\"LA\", zip:91601}}"; + JSONAssert.assertEquals("{id:1,name:\"Juergen\", address:{city:\"Hollywood\", " + + "state:\"LA\", zip:91601}}", result, false); + } + + @Test + public void givenArray_whenComparing_thenOrderMustMatchForStrict() throws JSONException { + String result = "[Alex, Barbera, Charlie, Xavier]"; + JSONAssert.assertEquals("[Charlie, Alex, Xavier, Barbera]", result, JSONCompareMode.LENIENT); + JSONAssert.assertEquals("[Alex, Barbera, Charlie, Xavier]", result, JSONCompareMode.STRICT); + JSONAssert.assertNotEquals("[Charlie, Alex, Xavier, Barbera]", result, JSONCompareMode.STRICT); + } + + @Test + public void givenArray_whenComparingExtended_thenNotEqual() throws JSONException { + String result = "[1,2,3,4,5]"; + JSONAssert.assertEquals("[1,2,3,4,5]", result, JSONCompareMode.LENIENT); + JSONAssert.assertNotEquals("[1,2,3]", result, JSONCompareMode.LENIENT); + JSONAssert.assertNotEquals("[1,2,3,4,5,6]", result, JSONCompareMode.LENIENT); + } + + @Test + public void whenComparingSizeOfArray_thenPass() throws JSONException { + String names = "{names:[Alex, Barbera, Charlie, Xavier]}"; + JSONAssert.assertEquals( + "{names:[4]}", + names, + new ArraySizeComparator(JSONCompareMode.LENIENT)); + } + + @Test + public void whenComparingContentsOfArray_thenPass() throws JSONException { + String ratings = "{ratings:[3.2,3.5,4.1,5,1]}"; + JSONAssert.assertEquals( + "{ratings:[1,5]}", + ratings, + new ArraySizeComparator(JSONCompareMode.LENIENT)); + } + + @Test + public void givenValueMatcher_whenComparingUsingRegex_thenPass() throws IllegalArgumentException, JSONException { + JSONAssert.assertEquals("{entry:{id:x}}", "{entry:{id:1, id:2}}", + new CustomComparator( + JSONCompareMode.STRICT, + new Customization("entry.id", + new RegularExpressionValueMatcher("\\d")))); + + JSONAssert.assertNotEquals("{entry:{id:x}}", "{entry:{id:1, id:as}}", + new CustomComparator(JSONCompareMode.STRICT, + new Customization("entry.id", + new RegularExpressionValueMatcher("\\d")))); + } +} diff --git a/log4j2/README.md b/log4j2/README.md new file mode 100644 index 0000000000..3afd842c82 --- /dev/null +++ b/log4j2/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [Intro to Log4j2 – Appenders, Layouts and Filters](http://www.baeldung.com/log4j2-appenders-layouts-filters) diff --git a/mesos-marathon/README.md b/mesos-marathon/README.md new file mode 100644 index 0000000000..3223eb2478 --- /dev/null +++ b/mesos-marathon/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [Simple Jenkins Pipeline with Marathon and Mesos](http://www.baeldung.com/jenkins-pipeline-with-marathon-mesos) diff --git a/mockito2/README.md b/mockito2/README.md index 587f1341bb..49741c66d1 100644 --- a/mockito2/README.md +++ b/mockito2/README.md @@ -1,4 +1,6 @@ -========= +### Relevant articles + +- [Mockito’s Java 8 Features](http://www.baeldung.com/mockito-2-java-8) ## Mockito 2 and Java 8 Tips diff --git a/pom.xml b/pom.xml index 312e2aef9f..9bbb6b5360 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,7 @@ aspectj assertj autovalue + axon cdi @@ -46,7 +47,7 @@ guava guava18 guava19 - guice-intro + guice disruptor handling-spring-static-resources @@ -59,11 +60,10 @@ immutables jackson - java-cassandra + javaslang javax-servlets javaxval - jasypt jaxb jee7 jjwt @@ -74,6 +74,7 @@ json jsoup junit5 + jws kotlin @@ -94,6 +95,7 @@ patterns pdf + protobuffer querydsl @@ -108,11 +110,11 @@ selenium-junit-testng solr-fulltext-search spark-java + spring-5 spring-akka spring-amqp spring-all spring-apache-camel - spring-autowire spring-batch spring-boot spring-cloud-data-flow @@ -133,12 +135,14 @@ spring-freemarker spring-hibernate3 spring-hibernate4 + spring-hibernate5 spring-integration spring-jersey spring-jms spring-jooq spring-jpa spring-katharsis + spring-ldap spring-mockito spring-mvc-email spring-mvc-forms @@ -205,7 +209,6 @@ rabbitmq vertx - @@ -187,7 +187,7 @@ UTF-8 1.8 - 4.3.4.RELEASE + 4.3.7.RELEASE 2.2.1 3.1.1 3.3.7-1 diff --git a/spring-boot-auditing/src/main/java/org/baeldung/WebSecurityConfig.java b/spring-boot-auditing/src/main/java/org/baeldung/WebSecurityConfig.java index 199edce0bc..9339d8e804 100755 --- a/spring-boot-auditing/src/main/java/org/baeldung/WebSecurityConfig.java +++ b/spring-boot-auditing/src/main/java/org/baeldung/WebSecurityConfig.java @@ -29,6 +29,6 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() - .withUser("user").password("password").roles("USER"); + .withUser("user").password("password").roles("USER", "ACTUATOR"); } } diff --git a/spring-boot/README.MD b/spring-boot/README.MD index 9fe18aaacc..d70e83525b 100644 --- a/spring-boot/README.MD +++ b/spring-boot/README.MD @@ -1,7 +1,8 @@ ###The Course The "REST With Spring" Classes: http://bit.ly/restwithspring -###Relevant Articles: +### Relevant Articles: + - [Quick Guide to @RestClientTest in Spring Boot](http://www.baeldung.com/restclienttest-in-spring-boot) - [Intro to Spring Boot Starters](http://www.baeldung.com/spring-boot-starters) - [A Guide to Spring in Eclipse STS](http://www.baeldung.com/eclipse-sts-spring) @@ -11,3 +12,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [A Custom Data Binder in Spring MVC](http://www.baeldung.com/spring-mvc-custom-data-binder) - [Intro to Building an Application with Spring Boot](http://www.baeldung.com/intro-to-spring-boot) - [How to Register a Servlet in a Java Web Application](http://www.baeldung.com/register-servlet) +- [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) + diff --git a/spring-boot/pom.xml b/spring-boot/pom.xml index 65b0f247f8..f087617709 100644 --- a/spring-boot/pom.xml +++ b/spring-boot/pom.xml @@ -12,7 +12,7 @@ org.springframework.boot spring-boot-starter-parent - 1.5.1.RELEASE + 1.5.2.RELEASE @@ -106,6 +106,12 @@ ${jquery.version} + + com.google.guava + guava + 18.0 + + org.apache.tomcat tomcat-servlet-api diff --git a/spring-boot/src/main/java/com/baeldung/internationalization/InternationalizationApp.java b/spring-boot/src/main/java/com/baeldung/internationalization/InternationalizationApp.java new file mode 100644 index 0000000000..c92d1c32e6 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/internationalization/InternationalizationApp.java @@ -0,0 +1,15 @@ +package com.baeldung.internationalization; + +import javax.annotation.security.RolesAllowed; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class InternationalizationApp { + @RolesAllowed("*") + public static void main(String[] args) { + System.setProperty("security.basic.enabled", "false"); + SpringApplication.run(InternationalizationApp.class, args); + } +} diff --git a/spring-boot/src/main/java/com/baeldung/internationalization/config/MvcConfig.java b/spring-boot/src/main/java/com/baeldung/internationalization/config/MvcConfig.java new file mode 100644 index 0000000000..59f7fd3ba5 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/internationalization/config/MvcConfig.java @@ -0,0 +1,38 @@ +package com.baeldung.internationalization.config; + +import java.util.Locale; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; +import org.springframework.web.servlet.i18n.SessionLocaleResolver; + +@Configuration +@EnableWebMvc +@ComponentScan(basePackages = "com.baeldung.internationalization.config") +public class MvcConfig extends WebMvcConfigurerAdapter { + + @Bean + public LocaleResolver localeResolver() { + SessionLocaleResolver slr = new SessionLocaleResolver(); + slr.setDefaultLocale(Locale.US); + return slr; + } + + @Bean + public LocaleChangeInterceptor localeChangeInterceptor() { + LocaleChangeInterceptor lci = new LocaleChangeInterceptor(); + lci.setParamName("lang"); + return lci; + } + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(localeChangeInterceptor()); + } +} diff --git a/spring-boot/src/main/java/com/baeldung/internationalization/config/PageController.java b/spring-boot/src/main/java/com/baeldung/internationalization/config/PageController.java new file mode 100644 index 0000000000..96a534b853 --- /dev/null +++ b/spring-boot/src/main/java/com/baeldung/internationalization/config/PageController.java @@ -0,0 +1,14 @@ +package com.baeldung.internationalization.config; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class PageController { + + @GetMapping("/international") + public String getInternationalPage() { + return "international"; + } + +} diff --git a/spring-boot/src/main/java/org/baeldung/boot/components/FooService.java b/spring-boot/src/main/java/org/baeldung/boot/components/FooService.java new file mode 100644 index 0000000000..235fd43299 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/components/FooService.java @@ -0,0 +1,21 @@ +package org.baeldung.boot.components; + +import org.baeldung.boot.model.Foo; +import org.baeldung.boot.repository.FooRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class FooService { + + @Autowired + private FooRepository fooRepository; + + public Foo getFooWithId(Integer id) throws Exception { + return fooRepository.findOne(id); + } + + public Foo getFooWithName(String name) { + return fooRepository.findByName(name); + } +} \ No newline at end of file diff --git a/spring-boot/src/main/java/org/baeldung/boot/exceptions/CommonException.java b/spring-boot/src/main/java/org/baeldung/boot/exceptions/CommonException.java new file mode 100644 index 0000000000..1f008440e6 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/exceptions/CommonException.java @@ -0,0 +1,13 @@ +package org.baeldung.boot.exceptions; + +public class CommonException extends RuntimeException{ + + /** + * + */ + private static final long serialVersionUID = 3080004140659213332L; + + public CommonException(String message){ + super(message); + } +} diff --git a/spring-boot/src/main/java/org/baeldung/boot/exceptions/FooNotFoundException.java b/spring-boot/src/main/java/org/baeldung/boot/exceptions/FooNotFoundException.java new file mode 100644 index 0000000000..68ef3fa389 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/exceptions/FooNotFoundException.java @@ -0,0 +1,13 @@ +package org.baeldung.boot.exceptions; + +public class FooNotFoundException extends RuntimeException{ + + /** + * + */ + private static final long serialVersionUID = 9042200028456133589L; + + public FooNotFoundException(String message){ + super(message); + } +} diff --git a/spring-boot/src/main/java/org/baeldung/boot/model/Foo.java b/spring-boot/src/main/java/org/baeldung/boot/model/Foo.java index 6a36459e3c..ac8a8fe429 100644 --- a/spring-boot/src/main/java/org/baeldung/boot/model/Foo.java +++ b/spring-boot/src/main/java/org/baeldung/boot/model/Foo.java @@ -21,6 +21,13 @@ public class Foo implements Serializable { this.name = name; } + + public Foo(Integer id, String name) { + super(); + this.id = id; + this.name = name; + } + public Integer getId() { return id; } diff --git a/spring-boot/src/main/java/org/baeldung/boot/service/FooController.java b/spring-boot/src/main/java/org/baeldung/boot/service/FooController.java new file mode 100644 index 0000000000..834fa342e2 --- /dev/null +++ b/spring-boot/src/main/java/org/baeldung/boot/service/FooController.java @@ -0,0 +1,26 @@ +package org.baeldung.boot.service; + +import org.baeldung.boot.components.FooService; +import org.baeldung.boot.model.Foo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class FooController { + + @Autowired + private FooService fooService; + + @GetMapping("/{id}") + public Foo getFooWithId(@PathVariable Integer id) throws Exception { + return fooService.getFooWithId(id); + } + + @GetMapping("/") + public Foo getFooWithName(@RequestParam String name) throws Exception { + return fooService.getFooWithName(name); + } +} \ No newline at end of file diff --git a/spring-boot/src/main/resources/application.properties b/spring-boot/src/main/resources/application.properties index 8c6549f53d..1ffc95849d 100644 --- a/spring-boot/src/main/resources/application.properties +++ b/spring-boot/src/main/resources/application.properties @@ -33,3 +33,11 @@ logging.level.org.springframework=INFO #Servlet Configuration servlet.name=dispatcherExample servlet.mapping=/dispatcherExampleURL + +#banner.charset=UTF-8 +#banner.location=classpath:banner.txt +#banner.image.location=classpath:banner.gif +#banner.image.width= //TODO +#banner.image.height= //TODO +#banner.image.margin= //TODO +#banner.image.invert= //TODO \ No newline at end of file diff --git a/spring-boot/src/main/resources/banner.txt b/spring-boot/src/main/resources/banner.txt new file mode 100644 index 0000000000..abfa666eb6 --- /dev/null +++ b/spring-boot/src/main/resources/banner.txt @@ -0,0 +1,14 @@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@#@@@@@########@@@@@@@@@@@@@@@@@@@@@@@@...@@@@@@@@@:..@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@#. @@@@@* *@@@@@@@@@@@@@@@@@@@@@ @@@@@@@@@. @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@#o @@@@@* @@@@@* @@@:*.*@@@@@@@: *8@@@ @@@@&:.#@. @o**@@@@**:@o*o@@:.:@@@@@:.o#@&*:@@@@ +@@@@@@@@@@@@* @@@@@* 8888 8@ @@@8 #@o 8@# .@ @@* :. @* @@@@ @. : &@ ** .@@@@ +@@@@@@@@@@. @ o@@@@@* *@@@o::& .* 8@@@@. @@ 8@@@@. @* @@@@ @. @@@& * @@@@# .@@@@ +@@@@@@@@@& @ @@@@@@* @@@@@@ 8 @@@@ .. o&&&&&&& @@ #@@@@. @* @@@@ @. @@@# * @@@@@ .@@@@ +@@@@@@@@@ @@o @@@@@@@* oooo* 8 @@@& @* @@@ # 88. 88. *& o#: @. @@@# *@ &#& .@@@@ +@@@@@@@@# @@@8 @@@@@@@* .*@@@#. *@@ @@@& :#@@@o .@@: *&@8 @o o@@: @. @@@# *@@#. :8# .@@@@ +@@@@@@@@@ @@@@ &@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@# o@@@@ @@@@@ +@@@@@& &@@@@ 8@@@@@@@@@8&8@@@@@#8#@@@o8@#&@@o&@@@&@@8@@&@@@@88@@8#@8&@@##@@@@@@#8@@#8@@88@@@@@ *@@@@@@@ +@@@# #@@@@#. @@@@@@@@@@@@@8@@8#o@&#@@@@o.@o*@@*.@@@.@&:8o8*@@@8&@@#@@@8@@@@8@#@@@8&@@@@@@#@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ \ No newline at end of file diff --git a/spring-boot/src/main/resources/messages.properties b/spring-boot/src/main/resources/messages.properties new file mode 100644 index 0000000000..e4dbc44c3f --- /dev/null +++ b/spring-boot/src/main/resources/messages.properties @@ -0,0 +1,4 @@ +greeting=Hello! Welcome to our website! +lang.change=Change the language +lang.eng=English +lang.fr=French \ No newline at end of file diff --git a/spring-boot/src/main/resources/messages_fr.properties b/spring-boot/src/main/resources/messages_fr.properties new file mode 100644 index 0000000000..ac5853717d --- /dev/null +++ b/spring-boot/src/main/resources/messages_fr.properties @@ -0,0 +1,4 @@ +greeting=Bonjour! Bienvenue sur notre site! +lang.change=Changez la langue +lang.eng=Anglais +lang.fr=Francais \ No newline at end of file diff --git a/spring-boot/src/main/resources/templates/international.html b/spring-boot/src/main/resources/templates/international.html new file mode 100644 index 0000000000..a2a5fbb591 --- /dev/null +++ b/spring-boot/src/main/resources/templates/international.html @@ -0,0 +1,29 @@ + + + + +Home + + + + +

+ +

+: + + + \ No newline at end of file diff --git a/spring-boot/src/test/java/org/baeldung/boot/FooComponentTests.java b/spring-boot/src/test/java/org/baeldung/boot/FooComponentTests.java new file mode 100644 index 0000000000..72ccc0bfb8 --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/boot/FooComponentTests.java @@ -0,0 +1,70 @@ +package org.baeldung.boot; + +import org.baeldung.boot.components.FooService; +import org.baeldung.boot.model.Foo; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.doReturn; + +@RunWith(SpringRunner.class) +@SpringBootTest( + classes = DemoApplication.class, + webEnvironment = WebEnvironment.RANDOM_PORT) +public class FooComponentTests { + + @Autowired + private TestRestTemplate testRestTemplate; + + @SpyBean + private FooService fooService; + + @Before + public void init() throws Exception { + Foo foo = new Foo(); + foo.setId(5); + foo.setName("MOCKED_FOO"); + + doReturn(foo).when(fooService).getFooWithId(anyInt()); + + // doCallRealMethod().when(fooComponent).getFooWithName(anyString()); + } + + @Test + public void givenInquiryingFooWithId_whenFooComponentIsMocked_thenAssertMockedResult() { + Map pathVariables = new HashMap<>(); + pathVariables.put("id", "1"); + ResponseEntity fooResponse = testRestTemplate.getForEntity("/{id}", Foo.class, pathVariables); + + assertNotNull(fooResponse); + assertEquals(HttpStatus.OK, fooResponse.getStatusCode()); + assertEquals(5, fooResponse.getBody().getId().longValue()); + assertEquals("MOCKED_FOO", fooResponse.getBody().getName()); + } + + @Test + public void givenInquiryingFooWithName_whenFooComponentIsMocked_thenAssertMockedResult() { + Map pathVariables = new HashMap<>(); + pathVariables.put("name", "Foo_Name"); + ResponseEntity fooResponse = testRestTemplate.getForEntity("/?name={name}", Foo.class, pathVariables); + + assertNotNull(fooResponse); + assertEquals(HttpStatus.OK, fooResponse.getStatusCode()); + assertEquals(1, fooResponse.getBody().getId().longValue()); + } +} \ No newline at end of file diff --git a/spring-boot/src/test/java/org/baeldung/boot/FooIntegrationTest.java b/spring-boot/src/test/java/org/baeldung/boot/FooIntegrationTest.java new file mode 100644 index 0000000000..932cce26d5 --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/boot/FooIntegrationTest.java @@ -0,0 +1,43 @@ +package org.baeldung.boot; +import java.util.HashMap; +import java.util.Map; + +import org.baeldung.boot.DemoApplication; +import org.baeldung.boot.model.Foo; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes=DemoApplication.class,webEnvironment = WebEnvironment.RANDOM_PORT) +public class FooIntegrationTest { + + @Autowired + private TestRestTemplate testRestTemplate; + + + @Test + public void givenInquiryingFooWithId_whenIdIsValid_thenHttpStatusOK(){ + Map pathVariables = new HashMap(); + pathVariables.put("id", "1"); + ResponseEntity fooResponse = testRestTemplate.getForEntity("/{id}", Foo.class, pathVariables); + Assert.assertNotNull(fooResponse); + Assert.assertEquals(HttpStatus.OK,fooResponse.getStatusCode()); + } + + @Test + public void givenInquiryingFooWithName_whenNameIsValid_thenHttpStatusOK(){ + Map pathVariables = new HashMap(); + pathVariables.put("name", "Foo_Name"); + ResponseEntity fooResponse = testRestTemplate.getForEntity("/?name={name}", Foo.class, pathVariables); + Assert.assertNotNull(fooResponse); + Assert.assertEquals(HttpStatus.OK,fooResponse.getStatusCode()); + } +} \ No newline at end of file diff --git a/spring-boot/src/test/java/org/baeldung/boot/FooJPATest.java b/spring-boot/src/test/java/org/baeldung/boot/FooJPATest.java new file mode 100644 index 0000000000..c29aa64e6c --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/boot/FooJPATest.java @@ -0,0 +1,34 @@ +package org.baeldung.boot; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.baeldung.boot.model.Foo; +import org.baeldung.boot.repository.FooRepository; +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 FooJPATest { + + @Autowired + private TestEntityManager entityManager; + + @Autowired + private FooRepository repository; + + @Test + public void findFooByName() { + this.entityManager.persist(new Foo("Foo_Name_2")); + Foo foo = this.repository.findByName("Foo_Name_2"); + assertNotNull(foo); + assertEquals("Foo_Name_2",foo.getName()); + // Due to having Insert query for Foo with Id 1, so TestEntityManager generates new Id of 2 + assertEquals(2l,foo.getId().longValue()); + } +} \ No newline at end of file diff --git a/spring-boot/src/test/java/org/baeldung/boot/FooJsonTest.java b/spring-boot/src/test/java/org/baeldung/boot/FooJsonTest.java new file mode 100644 index 0000000000..2789ed0a8c --- /dev/null +++ b/spring-boot/src/test/java/org/baeldung/boot/FooJsonTest.java @@ -0,0 +1,35 @@ +package org.baeldung.boot; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.baeldung.boot.model.Foo; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.json.JsonTest; +import org.springframework.boot.test.json.JacksonTester; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@JsonTest +public class FooJsonTest { + + @Autowired + private JacksonTester json; + + + @Test + public void testSerialize() throws Exception { + Foo foo = new Foo(3, "Foo_Name_3"); + assertThat(this.json.write(foo)).isEqualToJson("expected.json"); + assertThat(this.json.write(foo)).hasJsonPathStringValue("@.name"); + assertThat(this.json.write(foo)).extractingJsonPathStringValue("@.name").isEqualTo("Foo_Name_3"); + } + + @Test + public void testDeserialize() throws Exception { + String content = "{\"id\":4,\"name\":\"Foo_Name_4\"}"; + assertThat(this.json.parseObject(content).getName()).isEqualTo("Foo_Name_4"); + assertThat(this.json.parseObject(content).getId()==4); + } +} \ 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 14b190629e..0e6cb86bc5 100644 --- a/spring-boot/src/test/resources/application.properties +++ b/spring-boot/src/test/resources/application.properties @@ -1,3 +1,5 @@ spring.mail.host=localhost spring.mail.port=8025 -spring.mail.properties.mail.smtp.auth=false \ No newline at end of file +spring.mail.properties.mail.smtp.auth=false + +security.basic.enabled=false \ No newline at end of file diff --git a/spring-boot/src/test/resources/import.sql b/spring-boot/src/test/resources/import.sql new file mode 100644 index 0000000000..a382410271 --- /dev/null +++ b/spring-boot/src/test/resources/import.sql @@ -0,0 +1 @@ +Insert into Foo values(1,'Foo_Name'); \ No newline at end of file diff --git a/spring-boot/src/test/resources/org/baeldung/boot/expected.json b/spring-boot/src/test/resources/org/baeldung/boot/expected.json new file mode 100644 index 0000000000..f5409421a6 --- /dev/null +++ b/spring-boot/src/test/resources/org/baeldung/boot/expected.json @@ -0,0 +1,4 @@ +{ + "id":3, + "name":"Foo_Name_3" +} \ No newline at end of file diff --git a/spring-cloud/spring-cloud-bootstrap/README.MD b/spring-cloud/spring-cloud-bootstrap/README.MD index 251c861830..d8eedc3249 100644 --- a/spring-cloud/spring-cloud-bootstrap/README.MD +++ b/spring-cloud/spring-cloud-bootstrap/README.MD @@ -1,6 +1,8 @@ ### Relevant Articles: - [Spring Cloud – Bootstrapping](http://www.baeldung.com/spring-cloud-bootstrapping) - [Spring Cloud – Securing Services](http://www.baeldung.com/spring-cloud-securing-services) +- [Spring Cloud – Tracing Services with Zipkin](http://www.baeldung.com/tracing-services-with-zipkin) + - To run the project: - copy the appliction-config folder to c:\Users\{username}\ on Windows or /Users/{username}/ on *nix. Then open a git bash terminal in application-config and run: diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookController.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookController.java index d00f114b8c..192f9c2342 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookController.java +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookController.java @@ -1,11 +1,19 @@ package com.baeldung.spring.cloud.bootstrap.svcbook.book; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - import java.util.List; import java.util.Map; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + @RestController @RequestMapping("/books") public class BookController { @@ -13,7 +21,7 @@ public class BookController { @Autowired private BookService bookService; - @GetMapping("") + @GetMapping public List findAllBooks() { return bookService.findAllBooks(); } @@ -23,7 +31,7 @@ public class BookController { return bookService.findBookById(bookId); } - @PostMapping("") + @PostMapping public Book createBook(@RequestBody Book book) { return bookService.createBook(book); } @@ -33,7 +41,12 @@ public class BookController { bookService.deleteBook(bookId); } - @PatchMapping("/{bookId") + @PutMapping("/{bookId}") + public Book updateBook(@RequestBody Book book, @PathVariable Long bookId) { + return bookService.updateBook(book, bookId); + } + + @PatchMapping("/{bookId}") public Book updateBook(@RequestBody Map updates, @PathVariable Long bookId) { return bookService.updateBook(updates, bookId); } diff --git a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java index cfcbf15757..106fdad5d9 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java +++ b/spring-cloud/spring-cloud-bootstrap/svc-book/src/main/java/com/baeldung/spring/cloud/bootstrap/svcbook/book/BookService.java @@ -1,13 +1,15 @@ package com.baeldung.spring.cloud.bootstrap.svcbook.book; +import java.util.List; +import java.util.Map; +import java.util.Optional; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import com.google.common.base.Preconditions; @Service @Transactional(readOnly = true) @@ -27,7 +29,7 @@ public class BookService { @Transactional(propagation = Propagation.REQUIRED) public Book createBook(Book book) { - Book newBook = new Book(); + final Book newBook = new Book(); newBook.setTitle(book.getTitle()); newBook.setAuthor(book.getAuthor()); return bookRepository.save(newBook); @@ -40,16 +42,25 @@ public class BookService { @Transactional(propagation = Propagation.REQUIRED) public Book updateBook(Map updates, Long bookId) { - Book book = findBookById(bookId); - updates.keySet().forEach(key -> { - switch (key) { - case "author": - book.setAuthor(updates.get(key)); - break; - case "title": - book.setTitle(updates.get(key)); - } - }); + final Book book = findBookById(bookId); + updates.keySet() + .forEach(key -> { + switch (key) { + case "author": + book.setAuthor(updates.get(key)); + break; + case "title": + book.setTitle(updates.get(key)); + } + }); + return bookRepository.save(book); + } + + @Transactional(propagation = Propagation.REQUIRED) + public Book updateBook(Book book, Long bookId) { + Preconditions.checkNotNull(book); + Preconditions.checkState(book.getId() == bookId); + Preconditions.checkNotNull(bookRepository.findOne(bookId)); return bookRepository.save(book); } } diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingController.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingController.java index 83452ad747..cbfeda49c0 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingController.java +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingController.java @@ -1,11 +1,20 @@ package com.baeldung.spring.cloud.bootstrap.svcrating.rating; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; - import java.util.List; import java.util.Map; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + @RestController @RequestMapping("/ratings") public class RatingController { @@ -13,7 +22,7 @@ public class RatingController { @Autowired private RatingService ratingService; - @GetMapping("") + @GetMapping public List findRatingsByBookId(@RequestParam(required = false, defaultValue = "0") Long bookId) { if (bookId.equals(0L)) { return ratingService.findAllRatings(); @@ -21,7 +30,7 @@ public class RatingController { return ratingService.findRatingsByBookId(bookId); } - @PostMapping("") + @PostMapping public Rating createRating(@RequestBody Rating rating) { return ratingService.createRating(rating); } @@ -31,7 +40,12 @@ public class RatingController { ratingService.deleteRating(ratingId); } - @PatchMapping("/{ratingId") + @PutMapping("/{ratingId}") + public Rating updateRating(@RequestBody Rating rating, @PathVariable Long ratingId) { + return ratingService.updateRating(rating, ratingId); + } + + @PatchMapping("/{ratingId}") public Rating updateRating(@RequestBody Map updates, @PathVariable Long ratingId) { return ratingService.updateRating(updates, ratingId); } diff --git a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java index a2360b7be5..b05d7e2f1f 100644 --- a/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java +++ b/spring-cloud/spring-cloud-bootstrap/svc-rating/src/main/java/com/baeldung/spring/cloud/bootstrap/svcrating/rating/RatingService.java @@ -1,13 +1,15 @@ package com.baeldung.spring.cloud.bootstrap.svcrating.rating; +import java.util.List; +import java.util.Map; +import java.util.Optional; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import com.google.common.base.Preconditions; @Service @Transactional(readOnly = true) @@ -31,7 +33,7 @@ public class RatingService { @Transactional(propagation = Propagation.REQUIRED) public Rating createRating(Rating rating) { - Rating newRating = new Rating(); + final Rating newRating = new Rating(); newRating.setBookId(rating.getBookId()); newRating.setStars(rating.getStars()); return ratingRepository.save(newRating); @@ -44,14 +46,22 @@ public class RatingService { @Transactional(propagation = Propagation.REQUIRED) public Rating updateRating(Map updates, Long ratingId) { - Rating rating = findRatingById(ratingId); - updates.keySet().forEach(key -> { - switch (key) { + final Rating rating = findRatingById(ratingId); + updates.keySet() + .forEach(key -> { + switch (key) { case "stars": rating.setStars(Integer.parseInt(updates.get(key))); break; - } - }); + } + }); + return ratingRepository.save(rating); + } + + public Rating updateRating(Rating rating, Long ratingId) { + Preconditions.checkNotNull(rating); + Preconditions.checkState(rating.getId() == ratingId); + Preconditions.checkNotNull(ratingRepository.findOne(ratingId)); return ratingRepository.save(rating); } } diff --git a/spring-core/src/main/java/com/baeldung/beaninjection/AnotherSampleDAOBean.java b/spring-core/src/main/java/com/baeldung/beaninjection/AnotherSampleDAOBean.java new file mode 100644 index 0000000000..6313ba5a65 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/beaninjection/AnotherSampleDAOBean.java @@ -0,0 +1,17 @@ +package com.baeldung.beaninjection; + +public class AnotherSampleDAOBean implements IAnotherSampleDAO { + + private String propertyY; + + public AnotherSampleDAOBean(String propertyY) { + this.propertyY = propertyY; + } + + // standard setters and getters + + public String getPropertyY() { + return propertyY; + } + +} diff --git a/spring-core/src/main/java/com/baeldung/beaninjection/ExampleDAOBean.java b/spring-core/src/main/java/com/baeldung/beaninjection/ExampleDAOBean.java new file mode 100644 index 0000000000..cbc7b35a7c --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/beaninjection/ExampleDAOBean.java @@ -0,0 +1,39 @@ +package com.baeldung.beaninjection; + +import java.util.List; + +public class ExampleDAOBean implements IExampleDAO { + + private String propertyX; + + public ExampleDAOBean(String propertyX) { + this.propertyX = propertyX; + } + + public String getPropertyX() { + return propertyX; + } + + public void setPropertyX(String propertyX) { + this.propertyX = propertyX; + } + + @Override + public List getDomainList() { + // TODO Auto-generated method stub + return null; + } + + @Override + public SampleDomainObject createNewDomain(SampleDomainObject inputDomain) { + // TODO Auto-generated method stub + return null; + } + + @Override + public SampleDomainObject getSomeDomain() { + // TODO Auto-generated method stub + return new SampleDomainObject(); + } + +} diff --git a/spring-core/src/main/java/com/baeldung/beaninjection/ExampleServiceBean.java b/spring-core/src/main/java/com/baeldung/beaninjection/ExampleServiceBean.java new file mode 100644 index 0000000000..e5a5dfff5d --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/beaninjection/ExampleServiceBean.java @@ -0,0 +1,47 @@ +package com.baeldung.beaninjection; + +import java.util.List; + +public class ExampleServiceBean implements IExampleService { + + private IExampleDAO exampleDAO; + private IAnotherSampleDAO anotherSampleDAO; + + public ExampleServiceBean(IExampleDAO exampleDAO) { + this.exampleDAO = exampleDAO; + } + + public void setAnotherSampleDAO(IAnotherSampleDAO anotherSampleDAO) { + this.anotherSampleDAO = anotherSampleDAO; + } + + // standard setters and getters + + public IAnotherSampleDAO getAnotherSampleDAO() { + return anotherSampleDAO; + } + + public void setExampleDAO(ExampleDAOBean exampleDAO) { + this.exampleDAO = exampleDAO; + } + + public IExampleDAO getExampleDAO() { + return exampleDAO; + } + + private String propertyX; + + public String getPropertyX() { + return propertyX; + } + + public void setPropertyX(String propertyX) { + this.propertyX = propertyX; + } + + public List serviceMethodX() { + /*get domain list from DAO .. business logic on domain objects..return*/ + return exampleDAO.getDomainList(); + } + +} diff --git a/spring-core/src/main/java/com/baeldung/beaninjection/IAnotherSampleDAO.java b/spring-core/src/main/java/com/baeldung/beaninjection/IAnotherSampleDAO.java new file mode 100644 index 0000000000..ed4ad42705 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/beaninjection/IAnotherSampleDAO.java @@ -0,0 +1,5 @@ +package com.baeldung.beaninjection; + +public interface IAnotherSampleDAO { + +} diff --git a/spring-core/src/main/java/com/baeldung/beaninjection/IExampleDAO.java b/spring-core/src/main/java/com/baeldung/beaninjection/IExampleDAO.java new file mode 100644 index 0000000000..f7dbd2f9fe --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/beaninjection/IExampleDAO.java @@ -0,0 +1,12 @@ +package com.baeldung.beaninjection; + +import java.util.List; + +public interface IExampleDAO { + + List getDomainList(); + + SampleDomainObject createNewDomain(SampleDomainObject domainObject); + + SampleDomainObject getSomeDomain(); +} diff --git a/spring-core/src/main/java/com/baeldung/beaninjection/IExampleService.java b/spring-core/src/main/java/com/baeldung/beaninjection/IExampleService.java new file mode 100644 index 0000000000..9ea572d16b --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/beaninjection/IExampleService.java @@ -0,0 +1,9 @@ +package com.baeldung.beaninjection; + +import java.util.List; + +public interface IExampleService { + + List serviceMethodX(); + +} diff --git a/spring-core/src/main/java/com/baeldung/beaninjection/SampleDomainObject.java b/spring-core/src/main/java/com/baeldung/beaninjection/SampleDomainObject.java new file mode 100644 index 0000000000..3a5a913aa6 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/beaninjection/SampleDomainObject.java @@ -0,0 +1,31 @@ +package com.baeldung.beaninjection; + +import java.io.Serializable; + +public class SampleDomainObject implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 449859763481296747L; + + private String domainPropX; + private String domainPropY; + + public String getDomainPropX() { + return domainPropX; + } + + public void setDomainPropX(String domainPropX) { + this.domainPropX = domainPropX; + } + + public String getDomainPropY() { + return domainPropY; + } + + public void setDomainPropY(String domainPropY) { + this.domainPropY = domainPropY; + } + +} diff --git a/spring-core/src/main/java/com/baeldung/configuration/ApplicationContextTestBeanInjectionTypes.java b/spring-core/src/main/java/com/baeldung/configuration/ApplicationContextTestBeanInjectionTypes.java new file mode 100644 index 0000000000..3939abf148 --- /dev/null +++ b/spring-core/src/main/java/com/baeldung/configuration/ApplicationContextTestBeanInjectionTypes.java @@ -0,0 +1,36 @@ +package com.baeldung.configuration; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; + +import com.baeldung.beaninjection.AnotherSampleDAOBean; +import com.baeldung.beaninjection.ExampleDAOBean; +import com.baeldung.beaninjection.ExampleServiceBean; +import com.baeldung.beaninjection.IAnotherSampleDAO; +import com.baeldung.beaninjection.IExampleDAO; +import com.baeldung.beaninjection.IExampleService; + +@Configuration +@ComponentScan(basePackages = { "com.baeldung.beaninjection" }) +public class ApplicationContextTestBeanInjectionTypes { + + @Bean + public IExampleDAO exampleDAO() { + return new ExampleDAOBean("Mandatory DAO Property X"); + } + + @Bean + public IExampleService exampleServiceBean() { + ExampleServiceBean serviceBean = new ExampleServiceBean(exampleDAO()); + serviceBean.setAnotherSampleDAO(anotherSampleDAO()); + serviceBean.setPropertyX("Some Service Property X"); + return serviceBean; + } + + @Bean + public IAnotherSampleDAO anotherSampleDAO() { + return new AnotherSampleDAOBean("Mandatory DAO Property Y"); + } + +} diff --git a/spring-core/src/main/java/com/baeldung/lombok/ApologizeService.java b/spring-core/src/main/java/com/baeldung/lombok/ApologizeService.java index 25ef65cad2..76c3df8217 100644 --- a/spring-core/src/main/java/com/baeldung/lombok/ApologizeService.java +++ b/spring-core/src/main/java/com/baeldung/lombok/ApologizeService.java @@ -1,11 +1,11 @@ package com.baeldung.lombok; -import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component -@AllArgsConstructor +@RequiredArgsConstructor public class ApologizeService { private final Translator translator; diff --git a/spring-core/src/main/java/com/baeldung/lombok/ThankingService.java b/spring-core/src/main/java/com/baeldung/lombok/ThankingService.java index f3bdf8bb7f..2e0c398d2d 100644 --- a/spring-core/src/main/java/com/baeldung/lombok/ThankingService.java +++ b/spring-core/src/main/java/com/baeldung/lombok/ThankingService.java @@ -1,10 +1,10 @@ package com.baeldung.lombok; -import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @Component -@AllArgsConstructor +@RequiredArgsConstructor public class ThankingService { private final Translator translator; diff --git a/spring-core/src/main/resources/beaninjectiontypes-context.xml b/spring-core/src/main/resources/beaninjectiontypes-context.xml new file mode 100644 index 0000000000..dfdea41cdc --- /dev/null +++ b/spring-core/src/main/resources/beaninjectiontypes-context.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-core/src/test/java/com/baeldung/test/beaninjection/BeanInjectionJavaConfigTest.java b/spring-core/src/test/java/com/baeldung/test/beaninjection/BeanInjectionJavaConfigTest.java new file mode 100644 index 0000000000..4befd884eb --- /dev/null +++ b/spring-core/src/test/java/com/baeldung/test/beaninjection/BeanInjectionJavaConfigTest.java @@ -0,0 +1,50 @@ +package com.baeldung.test.beaninjection; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.beaninjection.AnotherSampleDAOBean; +import com.baeldung.beaninjection.ExampleDAOBean; +import com.baeldung.beaninjection.ExampleServiceBean; +import com.baeldung.configuration.ApplicationContextTestBeanInjectionTypes; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = ApplicationContextTestBeanInjectionTypes.class) +public class BeanInjectionJavaConfigTest implements ApplicationContextAware { + + private ApplicationContext beanInjectedContext; + + @Test + public void testDAOInjectionByJava() { + ExampleServiceBean serviceBean = beanInjectedContext.getBean(ExampleServiceBean.class); + assertNotNull("Failed: Constructor Injection,Bean Reference Injection,Java Config, ExampleServiceBean", serviceBean.getExampleDAO()); + assertNotNull("Failed: Constructor Injection,Bean Reference Injection,Java Config, ExampleServiceBean", serviceBean.getAnotherSampleDAO()); + assertTrue("Failed: Constructor Injection,String Property , Java Config", serviceBean.getPropertyX() + .equals("Some Service Property X")); + } + + @Test + public void testPropertyInjectioninDAOByJava() { + ExampleDAOBean daoBean = beanInjectedContext.getBean(ExampleDAOBean.class); + assertTrue("Failed: Constructor Injection,String Property , Java Config", daoBean.getPropertyX() + .equals("Mandatory DAO Property X")); + + AnotherSampleDAOBean anotherDAOBean = beanInjectedContext.getBean(AnotherSampleDAOBean.class); + assertTrue("Failed: Constructor Injection,String Property , XML Config", anotherDAOBean.getPropertyY() + .equals("Mandatory DAO Property Y")); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + // TODO Auto-generated method stub + this.beanInjectedContext = applicationContext; + } +} diff --git a/spring-core/src/test/java/com/baeldung/test/beaninjection/BeanInjectionXMLConfigTest.java b/spring-core/src/test/java/com/baeldung/test/beaninjection/BeanInjectionXMLConfigTest.java new file mode 100644 index 0000000000..d19a099aad --- /dev/null +++ b/spring-core/src/test/java/com/baeldung/test/beaninjection/BeanInjectionXMLConfigTest.java @@ -0,0 +1,49 @@ +package com.baeldung.test.beaninjection; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.beaninjection.AnotherSampleDAOBean; +import com.baeldung.beaninjection.ExampleDAOBean; +import com.baeldung.beaninjection.ExampleServiceBean; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(locations = "classpath:beaninjectiontypes-context.xml") +public class BeanInjectionXMLConfigTest implements ApplicationContextAware { + + private ApplicationContext beanInjectedContext; + + @Test + public void testDAOInjectionByXML() { + ExampleServiceBean serviceBean = beanInjectedContext.getBean(ExampleServiceBean.class); + assertNotNull("Failed: Constructor Injection,Bean Reference Injection,XML Config, ExampleServiceBean", serviceBean.getExampleDAO()); + assertNotNull("Failed: Constructor Injection,Bean Reference Injection,XML Config, ExampleServiceBean", serviceBean.getAnotherSampleDAO()); + assertTrue("Failed: Constructor Injection,String Property , XML Config", serviceBean.getPropertyX() + .equals("Some Service Property X")); + } + + @Test + public void testPropertyInjectioninDAOByXML() { + ExampleDAOBean daoBean = beanInjectedContext.getBean(ExampleDAOBean.class); + assertTrue("Failed: Constructor Injection,String Property , XML Config", daoBean.getPropertyX() + .equals("Mandatory DAO Property X")); + + AnotherSampleDAOBean anotherDAOBean = beanInjectedContext.getBean(AnotherSampleDAOBean.class); + assertTrue("Failed: Constructor Injection,String Property , XML Config", anotherDAOBean.getPropertyY() + .equals("Mandatory DAO Property Y")); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + // TODO Auto-generated method stub + this.beanInjectedContext = applicationContext; + } +} diff --git a/spring-data-javaslang/.gitignore b/spring-data-javaslang/.gitignore new file mode 100644 index 0000000000..7ee5423d14 --- /dev/null +++ b/spring-data-javaslang/.gitignore @@ -0,0 +1,5 @@ +/target/ +/project/ +.idea +.classpath +.eclipse diff --git a/spring-data-javaslang/pom.xml b/spring-data-javaslang/pom.xml new file mode 100644 index 0000000000..c265e893cc --- /dev/null +++ b/spring-data-javaslang/pom.xml @@ -0,0 +1,133 @@ + + + 4.0.0 + spring-data-javaslangb + spring-data-javaslangb + 0.0.1-SNAPSHOT + + UTF-8 + 2.19.1 + 3.1 + 2.9.1-01 + 2.3.7-01 + 2.4.8 + 2.0.5 + 4.12 + 1.5.1.RELEASE + 4.3.6.RELEASE + 4.3.6.RELEASE + 4.3.6.RELEASE + ${basedir}/src/test/java + + + org.springframework.boot + spring-boot-starter-parent + 1.5.1.RELEASE + + + + test-app + + verify + + + org.springframework.boot + spring-boot-maven-plugin + + + spring-boot-run + verify + + run + + false + + + + + + + + + + + maven-compiler-plugin + 3.5.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + ${project.build.testSourceDirectory} + + + + + + + org.springframework.boot + spring-boot-devtools + true + + + + com.h2database + h2 + 1.4.193 + + + + io.javaslang + javaslang + ${javaslang.version} + + + + org.springframework.data + spring-data-jpa + 1.11.0.RELEASE + + + + org.springframework.boot + spring-boot + ${spring-boot.version} + + + + org.springframework.boot + spring-boot-starter-data-jpa + ${spring-boot.version} + + + + org.springframework.boot + spring-boot-starter-test + ${spring-boot.version} + + + + org.springframework + spring-context + ${spring-context.version} + + + + org.springframework + spring-core + ${spring-core.version} + + + + junit + junit + ${junit.version} + test + + + \ No newline at end of file diff --git a/spring-data-javaslang/src/main/java/com/baeldung/spring_data/model/Book.java b/spring-data-javaslang/src/main/java/com/baeldung/spring_data/model/Book.java new file mode 100644 index 0000000000..95653abb6c --- /dev/null +++ b/spring-data-javaslang/src/main/java/com/baeldung/spring_data/model/Book.java @@ -0,0 +1,45 @@ +package com.baeldung.spring_data.model; + +import javaslang.collection.Seq; + +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import javax.persistence.CollectionTable; +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; + +@Entity +@Table(name = "book") +public class Book { + + @GeneratedValue + @Id + private Long id; + + private String title; + + private Seq authors; + + + public void setTitle(String title){ + this.title = title; + } + + public String getTitle(){ + return this.title; + } + + public Long getId(){ + return this.id; + } + + public void setAuthors(Seq authors){ + this.authors = authors; + } + + public Seq getAuthors(){ + return this.authors; + } +} diff --git a/spring-data-javaslang/src/main/java/com/baeldung/spring_data/model/JavaBook.java b/spring-data-javaslang/src/main/java/com/baeldung/spring_data/model/JavaBook.java new file mode 100644 index 0000000000..ab99b0d929 --- /dev/null +++ b/spring-data-javaslang/src/main/java/com/baeldung/spring_data/model/JavaBook.java @@ -0,0 +1,41 @@ +package com.baeldung.spring_data.model; + +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; + +import java.util.List; + +@Entity +@Table(name = "java_book") +public class JavaBook { + + @GeneratedValue + @Id + private Long id; + + private String title; + + @ElementCollection + private List authors; + + + public void setAuthors(List authors){ + this.authors = authors; + } + + public void setTitle(String title){ + this.title = title; + } + + public String getTitle(){ + return this.title; + } + + public Long getId(){ + return this.id; + } +} + diff --git a/spring-data-javaslang/src/main/java/com/baeldung/spring_data/repository/BookRepository.java b/spring-data-javaslang/src/main/java/com/baeldung/spring_data/repository/BookRepository.java new file mode 100644 index 0000000000..75b6d0b426 --- /dev/null +++ b/spring-data-javaslang/src/main/java/com/baeldung/spring_data/repository/BookRepository.java @@ -0,0 +1,19 @@ +package com.baeldung.spring_data.repository; + +import com.baeldung.spring_data.model.Book; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import javaslang.collection.Seq; +import javaslang.control.Option; + +@Repository +public interface BookRepository extends JpaRepository{ + Book save(Book book); + + Option findById(Long id); + + Option> findByTitleContaining(String title); + +} diff --git a/spring-data-javaslang/src/main/java/com/baeldung/spring_data/repository/JavaBookRepository.java b/spring-data-javaslang/src/main/java/com/baeldung/spring_data/repository/JavaBookRepository.java new file mode 100644 index 0000000000..a4aeab85ee --- /dev/null +++ b/spring-data-javaslang/src/main/java/com/baeldung/spring_data/repository/JavaBookRepository.java @@ -0,0 +1,17 @@ +package com.baeldung.spring_data.repository; + +import com.baeldung.spring_data.model.JavaBook; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface JavaBookRepository extends JpaRepository{ + JavaBook save(JavaBook book); + + JavaBook findById(Long id); + + List findByTitleContaining(String title); +} \ No newline at end of file diff --git a/spring-data-javaslang/src/main/java/com/baeldung/spring_data_app/MainApp.java b/spring-data-javaslang/src/main/java/com/baeldung/spring_data_app/MainApp.java new file mode 100644 index 0000000000..d8a194e92e --- /dev/null +++ b/spring-data-javaslang/src/main/java/com/baeldung/spring_data_app/MainApp.java @@ -0,0 +1,21 @@ +package com.baeldung.spring_data_app; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableJpaRepositories("com.baeldung.spring_data.repository") +@EnableTransactionManagement +@EntityScan("com.baeldung.spring_data.model") +@SpringBootApplication +public class MainApp { + public static void main(String[] args){ + SpringApplication.run(MainApp.class, args); + } +} diff --git a/spring-data-javaslang/src/test/java/com/baeldung/spring_data_tests/SpringTests.java b/spring-data-javaslang/src/test/java/com/baeldung/spring_data_tests/SpringTests.java new file mode 100644 index 0000000000..59a6c120fa --- /dev/null +++ b/spring-data-javaslang/src/test/java/com/baeldung/spring_data_tests/SpringTests.java @@ -0,0 +1,86 @@ +package com.baeldung.spring_data_tests; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.baeldung.spring_data_app.MainApp; +import com.baeldung.spring_data.model.Book; +import com.baeldung.spring_data.model.JavaBook; +import com.baeldung.spring_data.repository.BookRepository; +import com.baeldung.spring_data.repository.JavaBookRepository; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.test.context.junit4.SpringRunner; + +import javaslang.collection.Seq; +import javaslang.collection.List; +import javaslang.control.Option; + +import java.util.ArrayList; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = MainApp.class,webEnvironment = WebEnvironment.NONE) +public class SpringTests { + + @Autowired + JavaBookRepository javaRepository; + + @Autowired + BookRepository repository; + + @Test + public void should_return_seq(){ + Seq authors = List.of("author1","author2"); + Book testBook = new Book(); + testBook.setTitle("Javaslang in Spring Data Seq Test Return"); + testBook.setAuthors(authors); + Book book = repository.save(testBook); + Option> books = repository.findByTitleContaining("Seq Test"); + assert(!books.isEmpty()); + } + + + @Test + public void should_return_option_with_book(){ + Seq authors = List.of("author1","author2"); + Book testBook = new Book(); + testBook.setTitle("Javaslang in Spring Data"); + testBook.setAuthors(authors); + Book book = repository.save(testBook); + Option retBook = repository.findById(1L); + assert(retBook.isDefined() && !retBook.isEmpty()); + assert(retBook.get() != null); + } + + @Test + public void should_return_list(){ + ArrayList authors = new ArrayList(); + authors.add("author1"); + authors.add("author2"); + JavaBook testBook = new JavaBook(); + testBook.setTitle("Javaslang in Spring Data Seq Return"); + testBook.setAuthors(authors); + JavaBook book = javaRepository.save(testBook); + java.util.List books = javaRepository.findByTitleContaining("Seq"); + assert(!books.isEmpty()); + assert(books.size() == 1); + assert(books.get(0).getTitle().equals("Javaslang in Spring Data Seq Return")); + } + + @Test + public void should_return_book(){ + ArrayList authors = new ArrayList(); + authors.add("author1"); + authors.add("author2"); + JavaBook testBook = new JavaBook(); + testBook.setTitle("Javaslang in Spring Data"); + testBook.setAuthors(authors); + JavaBook book = javaRepository.save(testBook); + JavaBook retBook = javaRepository.findById(1L); + assert(retBook != null); + assert(retBook.getId() == 1L); + assert(retBook.getTitle().contains("Data")); + } +} \ No newline at end of file diff --git a/spring-data-rest/README.md b/spring-data-rest/README.md index f77c4dc202..241f2e3bcf 100644 --- a/spring-data-rest/README.md +++ b/spring-data-rest/README.md @@ -16,3 +16,4 @@ To view the running application, visit [http://localhost:8080](http://localhost: ###Relevant Articles: - [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) diff --git a/spring-groovy/.gitignore b/spring-groovy/.gitignore new file mode 100644 index 0000000000..c17c227305 --- /dev/null +++ b/spring-groovy/.gitignore @@ -0,0 +1,7 @@ +/target/ +/project/ +.classpath +.settings +.eclipse +.idea +.project diff --git a/spring-groovy/pom.xml b/spring-groovy/pom.xml new file mode 100644 index 0000000000..686633da27 --- /dev/null +++ b/spring-groovy/pom.xml @@ -0,0 +1,35 @@ + + 4.0.0 + + com.baeldug + spring-groovy + 0.0.1-SNAPSHOT + jar + + spring-groovy + http://maven.apache.org + + + UTF-8 + + + + + junit + junit + 3.8.1 + test + + + org.springframework + spring-core + 4.3.6.RELEASE + + + org.springframework.integration + spring-integration-groovy + 4.3.7.RELEASE + + + diff --git a/spring-groovy/src/main/java/com/baeldug/spring_groovy/App.java b/spring-groovy/src/main/java/com/baeldug/spring_groovy/App.java new file mode 100644 index 0000000000..1df6681c42 --- /dev/null +++ b/spring-groovy/src/main/java/com/baeldug/spring_groovy/App.java @@ -0,0 +1,13 @@ +package com.baeldug.spring_groovy; + +/** + * Hello world! + * + */ +public class App +{ + public static void main( String[] args ) + { + System.out.println( "Hello World!" ); + } +} diff --git a/spring-groovy/src/main/java/com/baeldug/spring_groovy/TestConfig.java b/spring-groovy/src/main/java/com/baeldug/spring_groovy/TestConfig.java new file mode 100644 index 0000000000..474216de4e --- /dev/null +++ b/spring-groovy/src/main/java/com/baeldug/spring_groovy/TestConfig.java @@ -0,0 +1,8 @@ +package com.baeldug.spring_groovy; + +import org.springframework.stereotype.Component; + +@Component +public class TestConfig { + +} diff --git a/spring-groovy/src/main/resources/groovyContextConfig.groovy b/spring-groovy/src/main/resources/groovyContextConfig.groovy new file mode 100644 index 0000000000..3ac7366876 --- /dev/null +++ b/spring-groovy/src/main/resources/groovyContextConfig.groovy @@ -0,0 +1,5 @@ +beans{ + testString String, 'test' + testNum int, 100 + testObj(i:101,s:'objVal') +} \ No newline at end of file diff --git a/spring-groovy/src/test/java/com/baeldug/spring_groovy/AppTest.java b/spring-groovy/src/test/java/com/baeldug/spring_groovy/AppTest.java new file mode 100644 index 0000000000..19eefb6c0f --- /dev/null +++ b/spring-groovy/src/test/java/com/baeldug/spring_groovy/AppTest.java @@ -0,0 +1,38 @@ +package com.baeldug.spring_groovy; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +} diff --git a/spring-hibernate4/src/main/resources/immutable.cfg.xml b/spring-hibernate4/src/main/resources/immutable.cfg.xml new file mode 100644 index 0000000000..fe1e3cb723 --- /dev/null +++ b/spring-hibernate4/src/main/resources/immutable.cfg.xml @@ -0,0 +1,38 @@ + + + + + + + + + org.hsqldb.jdbcDriver + jdbc:hsqldb:hsql:mem://localhost/xdb + sa + + + + 1 + + + org.hibernate.dialect.HSQLDialect + + + thread + + + org.hibernate.cache.NoCacheProvider + + + true + + + update + + + + + + \ No newline at end of file diff --git a/spring-hibernate5/README.md b/spring-hibernate5/README.md new file mode 100644 index 0000000000..fd539fdcb6 --- /dev/null +++ b/spring-hibernate5/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [Guide to @Immutable Annotation in Hibernate](http://www.baeldung.com/hibernate-immutable) diff --git a/spring-hibernate5/pom.xml b/spring-hibernate5/pom.xml index 81f8084d74..752cbdba1d 100644 --- a/spring-hibernate5/pom.xml +++ b/spring-hibernate5/pom.xml @@ -148,7 +148,6 @@ org.hsqldb hsqldb ${hsqldb.version} - test
diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java index a854b51753..7b53a5f752 100644 --- a/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java +++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/criteria/view/ApplicationView.java @@ -27,11 +27,7 @@ import com.baeldung.hibernate.criteria.model.Item; import com.baeldung.hibernate.criteria.util.HibernateUtil; public class ApplicationView { - - public ApplicationView() { - - } - + @SuppressWarnings("unchecked") public boolean checkIfCriteriaTimeLower() { final Session session = HibernateUtil.getHibernateSession(); @@ -181,8 +177,7 @@ public class ApplicationView { CriteriaBuilder builder = session.getCriteriaBuilder(); CriteriaQuery criteriaItem = builder.createQuery(Item.class); Root rootItem = criteriaItem.from(Item.class); - criteriaItem.select(rootItem).where(builder.isNull(rootItem.get("itemDescription"))) - .where(builder.like(rootItem.get("itemName"), "chair%")); + criteriaItem.select(rootItem).where(builder.isNull(rootItem.get("itemDescription"))).where(builder.like(rootItem.get("itemName"), "chair%")); final List notNullItemsList = session.createQuery(criteriaItem).getResultList(); final String notNullDescItems[] = new String[notNullItemsList.size()]; for (int i = 0; i < notNullItemsList.size(); i++) { diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/immutable/entities/Event.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/immutable/entities/Event.java new file mode 100644 index 0000000000..2928ffe981 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/immutable/entities/Event.java @@ -0,0 +1,58 @@ +package com.baeldung.hibernate.immutable.entities; + +import org.hibernate.annotations.Cascade; +import org.hibernate.annotations.CascadeType; +import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Immutable; + +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import java.util.Set; + +@Entity +@Immutable +@Table(name = "events") +public class Event { + + @Id + @Column(name = "event_id") + @GeneratedValue(generator = "increment") + @GenericGenerator(name = "increment", strategy = "increment") + private Long id; + + @Column(name = "title") + private String title; + + @ElementCollection + @Immutable + private Set guestList; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + @Cascade({ CascadeType.SAVE_UPDATE, CascadeType.DELETE }) + public Set getGuestList() { + return guestList; + } + + public void setGuestList(Set guestList) { + this.guestList = guestList; + } +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/hibernate/immutable/util/HibernateUtil.java b/spring-hibernate5/src/main/java/com/baeldung/hibernate/immutable/util/HibernateUtil.java new file mode 100644 index 0000000000..e4a2319c37 --- /dev/null +++ b/spring-hibernate5/src/main/java/com/baeldung/hibernate/immutable/util/HibernateUtil.java @@ -0,0 +1,29 @@ +package com.baeldung.hibernate.immutable.util; + +import com.baeldung.hibernate.immutable.entities.Event; +import org.hibernate.SessionFactory; +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.Configuration; +import org.hibernate.service.ServiceRegistry; + +public class HibernateUtil { + private static final SessionFactory sessionFactory = buildSessionFactory(); + + private static SessionFactory buildSessionFactory() { + try { + // Create a session factory from immutable.cfg.xml + Configuration configuration = new Configuration(); + configuration.addAnnotatedClass(Event.class); + configuration.configure("immutable.cfg.xml"); + ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); + return configuration.buildSessionFactory(serviceRegistry); + } catch (Throwable ex) { + System.out.println("Initial SessionFactory creation failed." + ex); + throw new ExceptionInInitializerError(ex); + } + } + + public static SessionFactory getSessionFactory() { + return sessionFactory; + } +} diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java index 8e2df15519..2695d7760a 100644 --- a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateAuditableService.java @@ -8,8 +8,7 @@ import com.baeldung.persistence.dao.common.IOperations; import org.springframework.transaction.annotation.Transactional; @Transactional(value = "hibernateTransactionManager") -public abstract class AbstractHibernateAuditableService extends AbstractHibernateService - implements IOperations, IAuditOperations { +public abstract class AbstractHibernateAuditableService extends AbstractHibernateService implements IOperations, IAuditOperations { @Override public List getEntitiesAtRevision(final Number revision) { diff --git a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java index 5da2f299f1..02b8ccf48b 100644 --- a/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java +++ b/spring-hibernate5/src/main/java/com/baeldung/persistence/service/common/AbstractHibernateService.java @@ -7,8 +7,7 @@ import com.baeldung.persistence.dao.common.IOperations; import org.springframework.transaction.annotation.Transactional; @Transactional(value = "hibernateTransactionManager") -public abstract class AbstractHibernateService extends AbstractService implements - IOperations { +public abstract class AbstractHibernateService extends AbstractService implements IOperations { @Override public T findOne(final long id) { diff --git a/spring-hibernate5/src/main/resources/immutable.cfg.xml b/spring-hibernate5/src/main/resources/immutable.cfg.xml new file mode 100644 index 0000000000..a572ebeac2 --- /dev/null +++ b/spring-hibernate5/src/main/resources/immutable.cfg.xml @@ -0,0 +1,32 @@ + + + + + + + + + org.hsqldb.jdbcDriver + jdbc:hsqldb:mem:test + sa + + + + 1 + + + org.hibernate.dialect.HSQLDialect + + + thread + + + true + + + update + + + \ No newline at end of file diff --git a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java index 7caa02f156..c7d59e3b00 100644 --- a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java +++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaIntegrationTest.java @@ -24,8 +24,7 @@ public class HibernateCriteriaIntegrationTest { @Test public void testLikeCriteriaQuery() { final Session session = HibernateUtil.getHibernateSession(); - final List expectedLikeList = session.createQuery("From Item where itemName like '%chair%'") - .getResultList(); + final List expectedLikeList = session.createQuery("From Item where itemName like '%chair%'").getResultList(); final String expectedLikeItems[] = new String[expectedLikeList.size()]; for (int i = 0; i < expectedLikeList.size(); i++) { expectedLikeItems[i] = expectedLikeList.get(i).getItemName(); @@ -37,8 +36,7 @@ public class HibernateCriteriaIntegrationTest { @Test public void testILikeCriteriaQuery() { final Session session = HibernateUtil.getHibernateSession(); - final List expectedChairCaseList = session.createQuery("From Item where itemName like '%Chair%'") - .getResultList(); + final List expectedChairCaseList = session.createQuery("From Item where itemName like '%Chair%'").getResultList(); final String expectedChairCaseItems[] = new String[expectedChairCaseList.size()]; for (int i = 0; i < expectedChairCaseList.size(); i++) { expectedChairCaseItems[i] = expectedChairCaseList.get(i).getItemName(); @@ -51,8 +49,7 @@ public class HibernateCriteriaIntegrationTest { @Test public void testNullCriteriaQuery() { final Session session = HibernateUtil.getHibernateSession(); - final List expectedIsNullDescItemsList = session.createQuery("From Item where itemDescription is null") - .getResultList(); + final List expectedIsNullDescItemsList = session.createQuery("From Item where itemDescription is null").getResultList(); final String expectedIsNullDescItems[] = new String[expectedIsNullDescItemsList.size()]; for (int i = 0; i < expectedIsNullDescItemsList.size(); i++) { expectedIsNullDescItems[i] = expectedIsNullDescItemsList.get(i).getItemName(); @@ -64,8 +61,7 @@ public class HibernateCriteriaIntegrationTest { @Test public void testIsNotNullCriteriaQuery() { final Session session = HibernateUtil.getHibernateSession(); - final List expectedIsNotNullDescItemsList = session.createQuery( - "From Item where itemDescription is not null").getResultList(); + final List expectedIsNotNullDescItemsList = session.createQuery("From Item where itemDescription is not null").getResultList(); final String expectedIsNotNullDescItems[] = new String[expectedIsNotNullDescItemsList.size()]; for (int i = 0; i < expectedIsNotNullDescItemsList.size(); i++) { expectedIsNotNullDescItems[i] = expectedIsNotNullDescItemsList.get(i).getItemName(); @@ -78,8 +74,7 @@ public class HibernateCriteriaIntegrationTest { @Test public void testAverageProjection() { final Session session = HibernateUtil.getHibernateSession(); - final List expectedAvgProjItemsList = session.createQuery("Select avg(itemPrice) from Item item") - .getResultList(); + final List expectedAvgProjItemsList = session.createQuery("Select avg(itemPrice) from Item item").getResultList(); final Double expectedAvgProjItems[] = new Double[expectedAvgProjItemsList.size()]; for (int i = 0; i < expectedAvgProjItemsList.size(); i++) { @@ -105,8 +100,7 @@ public class HibernateCriteriaIntegrationTest { @Test public void testOrCriteriaQuery() { final Session session = HibernateUtil.getHibernateSession(); - final List expectedOrCritItemsList = session.createQuery( - "From Item where itemPrice>1000 or itemName like 'Chair%'").getResultList(); + final List expectedOrCritItemsList = session.createQuery("From Item where itemPrice>1000 or itemName like 'Chair%'").getResultList(); final String expectedOrCritItems[] = new String[expectedOrCritItemsList.size()]; for (int i = 0; i < expectedOrCritItemsList.size(); i++) { expectedOrCritItems[i] = expectedOrCritItemsList.get(i).getItemName(); @@ -118,8 +112,7 @@ public class HibernateCriteriaIntegrationTest { @Test public void testAndCriteriaQuery() { final Session session = HibernateUtil.getHibernateSession(); - final List expectedAndCritItemsList = session.createQuery( - "From Item where itemPrice>1000 and itemName like 'Chair%'").getResultList(); + final List expectedAndCritItemsList = session.createQuery("From Item where itemPrice>1000 and itemName like 'Chair%'").getResultList(); final String expectedAndCritItems[] = new String[expectedAndCritItemsList.size()]; for (int i = 0; i < expectedAndCritItemsList.size(); i++) { expectedAndCritItems[i] = expectedAndCritItemsList.get(i).getItemName(); @@ -131,8 +124,7 @@ public class HibernateCriteriaIntegrationTest { @Test public void testMultiCriteriaQuery() { final Session session = HibernateUtil.getHibernateSession(); - final List expectedMultiCritItemsList = session.createQuery( - "From Item where itemDescription is null and itemName like'chair%'").getResultList(); + final List expectedMultiCritItemsList = session.createQuery("From Item where itemDescription is null and itemName like'chair%'").getResultList(); final String expectedMultiCritItems[] = new String[expectedMultiCritItemsList.size()]; for (int i = 0; i < expectedMultiCritItemsList.size(); i++) { expectedMultiCritItems[i] = expectedMultiCritItemsList.get(i).getItemName(); @@ -144,8 +136,7 @@ public class HibernateCriteriaIntegrationTest { @Test public void testSortCriteriaQuery() { final Session session = HibernateUtil.getHibernateSession(); - final List expectedSortCritItemsList = session.createQuery( - "From Item order by itemName asc, itemPrice desc").getResultList(); + final List expectedSortCritItemsList = session.createQuery("From Item order by itemName asc, itemPrice desc").getResultList(); final String expectedSortCritItems[] = new String[expectedSortCritItemsList.size()]; for (int i = 0; i < expectedSortCritItemsList.size(); i++) { expectedSortCritItems[i] = expectedSortCritItemsList.get(i).getItemName(); @@ -157,8 +148,7 @@ public class HibernateCriteriaIntegrationTest { @Test public void testGreaterThanCriteriaQuery() { final Session session = HibernateUtil.getHibernateSession(); - final List expectedGreaterThanList = session.createQuery("From Item where itemPrice>1000") - .getResultList(); + final List expectedGreaterThanList = session.createQuery("From Item where itemPrice>1000").getResultList(); final String expectedGreaterThanItems[] = new String[expectedGreaterThanList.size()]; for (int i = 0; i < expectedGreaterThanList.size(); i++) { expectedGreaterThanItems[i] = expectedGreaterThanList.get(i).getItemName(); @@ -182,8 +172,7 @@ public class HibernateCriteriaIntegrationTest { @Test public void betweenCriteriaQuery() { final Session session = HibernateUtil.getHibernateSession(); - final List expectedBetweenList = session.createQuery("From Item where itemPrice between 100 and 200") - .getResultList(); + final List expectedBetweenList = session.createQuery("From Item where itemPrice between 100 and 200").getResultList(); final String expectedPriceBetweenItems[] = new String[expectedBetweenList.size()]; for (int i = 0; i < expectedBetweenList.size(); i++) { expectedPriceBetweenItems[i] = expectedBetweenList.get(i).getItemName(); 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 index 99164efb7a..3228f917fd 100644 --- a/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java +++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/criteria/HibernateCriteriaTestRunner.java @@ -9,7 +9,7 @@ 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/immutable/HibernateImmutableIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/hibernate/immutable/HibernateImmutableIntegrationTest.java new file mode 100644 index 0000000000..801ddcdb45 --- /dev/null +++ b/spring-hibernate5/src/test/java/com/baeldung/hibernate/immutable/HibernateImmutableIntegrationTest.java @@ -0,0 +1,89 @@ +package com.baeldung.hibernate.immutable; + +import com.baeldung.hibernate.immutable.entities.Event; +import com.baeldung.hibernate.immutable.util.HibernateUtil; +import com.google.common.collect.Sets; +import org.hibernate.CacheMode; +import org.hibernate.Session; +import org.junit.*; +import org.junit.rules.ExpectedException; + +import javax.persistence.PersistenceException; + +public class HibernateImmutableIntegrationTest { + + private static Session session; + + @Rule + public final ExpectedException exception = ExpectedException.none(); + + @Before + public void before() { + session = HibernateUtil.getSessionFactory().getCurrentSession(); + session.beginTransaction(); + createEvent(); + session.setCacheMode(CacheMode.REFRESH); + } + + @BeforeClass + public static void setup() { + session = HibernateUtil.getSessionFactory().getCurrentSession(); + } + + @AfterClass + public static void teardown() { + HibernateUtil.getSessionFactory().close(); + } + + @Test + public void addEvent() { + Event event = new Event(); + event.setTitle("Public Event"); + session.save(event); + session.getTransaction().commit(); + } + + @Test + public void updateEvent() { + Event event = (Event) session.createQuery("FROM Event WHERE title='New Event'").list().get(0); + event.setTitle("Private Event"); + session.saveOrUpdate(event); + session.getTransaction().commit(); + } + + @Test + public void deleteEvent() { + Event event = (Event) session.createQuery("FROM Event WHERE title='New Event'").list().get(0); + session.delete(event); + session.getTransaction().commit(); + } + + @Test + public void addGuest() { + Event event = (Event) session.createQuery("FROM Event WHERE title='New Event'").list().get(0); + String newGuest = "Sara"; + event.getGuestList().add(newGuest); + + exception.expect(PersistenceException.class); + session.save(event); + session.getTransaction().commit(); + } + + @Test + public void deleteCascade() { + Event event = (Event) session.createQuery("FROM Event WHERE title='New Event'").list().get(0); + String guest = event.getGuestList().iterator().next(); + event.getGuestList().remove(guest); + + exception.expect(PersistenceException.class); + session.saveOrUpdate(event); + session.getTransaction().commit(); + } + + public static void createEvent() { + Event event = new Event(); + event.setTitle("New Event"); + event.setGuestList(Sets.newHashSet("guest")); + session.save(event); + } +} diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java index c9152b4d85..e6548ce5e7 100644 --- a/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooPaginationPersistenceIntegrationTest.java @@ -73,8 +73,7 @@ public class FooPaginationPersistenceIntegrationTest { public final void whenRetrievingPaginatedEntities_thenCorrectSize() { final int pageNumber = 1; final int pageSize = 10; - final List fooList = session.createQuery("From Foo").setFirstResult((pageNumber - 1) * pageSize) - .setMaxResults(pageSize).getResultList(); + final List fooList = session.createQuery("From Foo").setFirstResult((pageNumber - 1) * pageSize).setMaxResults(pageSize).getResultList(); assertThat(fooList, hasSize(pageSize)); } @@ -90,8 +89,7 @@ public class FooPaginationPersistenceIntegrationTest { final List fooList = Lists.newArrayList(); int totalEntities = 0; while (totalEntities < countResult) { - fooList.addAll(session.createQuery("From Foo").setFirstResult((pageNumber - 1) * pageSize) - .setMaxResults(pageSize).getResultList()); + fooList.addAll(session.createQuery("From Foo").setFirstResult((pageNumber - 1) * pageSize).setMaxResults(pageSize).getResultList()); totalEntities = fooList.size(); pageNumber++; } @@ -106,8 +104,7 @@ public class FooPaginationPersistenceIntegrationTest { final Long countResults = (Long) session.createQuery(countQ).uniqueResult(); final int lastPageNumber = (int) ((countResults / pageSize) + 1); - final List lastPage = session.createQuery("From Foo").setFirstResult((lastPageNumber - 1) * pageSize) - .setMaxResults(pageSize).getResultList(); + final List lastPage = session.createQuery("From Foo").setFirstResult((lastPageNumber - 1) * pageSize).setMaxResults(pageSize).getResultList(); assertThat(lastPage, hasSize(lessThan(pageSize + 1))); } @@ -147,8 +144,7 @@ public class FooPaginationPersistenceIntegrationTest { CriteriaQuery criteriaItem = builder.createQuery(Foo.class); Root rootItem = criteriaItem.from(Foo.class); criteriaItem.select(rootItem); - final List firstPage = session.createQuery(criteriaItem).setFirstResult(0).setMaxResults(pageSize) - .getResultList(); + final List firstPage = session.createQuery(criteriaItem).setFirstResult(0).setMaxResults(pageSize).getResultList(); assertThat(firstPage, hasSize(pageSize)); } @@ -175,8 +171,7 @@ public class FooPaginationPersistenceIntegrationTest { int totalEntities = 0; while (totalEntities < count.intValue()) { - fooList.addAll(session.createQuery(criteriaFoo).setFirstResult((pageNumber - 1) * pageSize) - .setMaxResults(pageSize).getResultList()); + fooList.addAll(session.createQuery(criteriaFoo).setFirstResult((pageNumber - 1) * pageSize).setMaxResults(pageSize).getResultList()); totalEntities = fooList.size(); pageNumber++; } diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java index 813fb65641..9bd20e745c 100644 --- a/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/hibernate/FooSortingPersistenceIntegrationTest.java @@ -11,8 +11,6 @@ import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Order; import javax.persistence.criteria.Root; -import org.hibernate.Criteria; -import org.hibernate.NullPrecedence; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.junit.After; @@ -151,7 +149,7 @@ public class FooSortingPersistenceIntegrationTest { System.out.println("Id: " + foo.getId() + ", FirstName: " + foo.getName()); } } - + @Test public final void whenCriteriaSortingStringNullsFirstDesc_thenNullsFirst() { final Criteria criteria = session.createCriteria(Foo.class, "FOO"); diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java index b6cde868d3..d3e90a568a 100644 --- a/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/save/SaveMethodsTest.java @@ -37,14 +37,9 @@ public class SaveMethodsTest { @BeforeClass public static void beforeTests() { - Configuration configuration = new Configuration().addAnnotatedClass(Person.class) - .setProperty("hibernate.dialect", HSQLDialect.class.getName()) - .setProperty("hibernate.connection.driver_class", org.hsqldb.jdbcDriver.class.getName()) - .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test") - .setProperty("hibernate.connection.username", "sa").setProperty("hibernate.connection.password", "") - .setProperty("hibernate.hbm2ddl.auto", "update"); - ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings( - configuration.getProperties()).build(); + Configuration configuration = new Configuration().addAnnotatedClass(Person.class).setProperty("hibernate.dialect", HSQLDialect.class.getName()).setProperty("hibernate.connection.driver_class", org.hsqldb.jdbcDriver.class.getName()) + .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test").setProperty("hibernate.connection.username", "sa").setProperty("hibernate.connection.password", "").setProperty("hibernate.hbm2ddl.auto", "update"); + ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); } @@ -269,10 +264,10 @@ public class SaveMethodsTest { @After public void tearDown() { - try{ - session.getTransaction().commit(); - session.close(); - }catch(TransactionException ex){ + try { + session.getTransaction().commit(); + session.close(); + } catch (TransactionException ex) { ex.printStackTrace(); } } diff --git a/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java index cfd3844079..8ab1b86809 100644 --- a/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java +++ b/spring-hibernate5/src/test/java/com/baeldung/persistence/service/FooStoredProceduresIntegrationTest.java @@ -96,16 +96,14 @@ public class FooStoredProceduresIntegrationTest { fooService.create(new Foo("NewFooName")); // Stored procedure getFoosByName using createSQLQuery() - List allFoosByName = session.createQuery("CALL GetFoosByName(:fooName)", Foo.class) - .setParameter("fooName", "NewFooName").getResultList(); + List allFoosByName = session.createQuery("CALL GetFoosByName(:fooName)", Foo.class).setParameter("fooName", "NewFooName").getResultList(); for (Foo foo : allFoosByName) { LOGGER.info("getFoosByName() using SQL Query : found => {}", foo.toString()); } // Stored procedure getFoosByName using getNamedQuery() @SuppressWarnings("unchecked") - List allFoosByName2 = session.getNamedQuery("callGetFoosByName").setParameter("fooName", "NewFooName") - .getResultList(); + List allFoosByName2 = session.getNamedQuery("callGetFoosByName").setParameter("fooName", "NewFooName").getResultList(); for (Foo foo : allFoosByName2) { LOGGER.info("getFoosByName() using Native Query : found => {}", foo.toString()); } diff --git a/spring-kafka/README.md b/spring-kafka/README.md new file mode 100644 index 0000000000..2731eca042 --- /dev/null +++ b/spring-kafka/README.md @@ -0,0 +1,9 @@ +# Spring Kakfa + +This is a simple Spring Boot app to demonstrate sending and receiving of messages in Kafka using spring-kafka. + +As Kafka topics are not created automatically by default, this application requires that a topic named 'baeldung' is created manually. + +`$ bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic baeldung` + +Two listeners with group Ids **foo** and **bar** are configured. When run successfully, the *Hello World!* message will be received by both the listeners and logged on console. diff --git a/spring-kafka/pom.xml b/spring-kafka/pom.xml new file mode 100644 index 0000000000..73eaf3acff --- /dev/null +++ b/spring-kafka/pom.xml @@ -0,0 +1,46 @@ + + 4.0.0 + + com.baeldung + spring-kafka + 0.0.1-SNAPSHOT + + spring-kafka + Intro to Kafka with Spring + + + 1.8 + 1.1.3.RELEASE + + + + org.springframework.boot + spring-boot-starter-parent + 1.5.2.RELEASE + + + + + + org.springframework.boot + spring-boot-starter + + + + org.springframework.kafka + spring-kafka + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + \ No newline at end of file diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java new file mode 100644 index 0000000000..252054a9f1 --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaApplication.java @@ -0,0 +1,72 @@ +package com.baeldung.spring.kafka; + +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.kafka.core.KafkaTemplate; + +@SpringBootApplication +public class KafkaApplication { + + public static void main(String[] args) throws Exception { + ConfigurableApplicationContext context = SpringApplication.run(KafkaApplication.class, args); + MessageProducer producer = context.getBean(MessageProducer.class); + producer.sendMessage("Hello, World!"); + + MessageListener listener = context.getBean(MessageListener.class); + listener.latch.await(20, TimeUnit.SECONDS); + Thread.sleep(60000); + context.close(); + + } + + @Bean + public MessageProducer messageProducer() { + return new MessageProducer(); + } + + @Bean + public MessageListener messageListener() { + return new MessageListener(); + } + + public static class MessageProducer { + + @Autowired + private KafkaTemplate kafkaTemplate; + + @Value(value = "${message.topic.name}") + private String topicName; + + public void sendMessage(String message) { + kafkaTemplate.send(topicName, message); + } + + } + + public static class MessageListener { + + private CountDownLatch latch = new CountDownLatch(2); + + @KafkaListener(topics = "${message.topic.name}", group = "foo", containerFactory = "fooKafkaListenerContainerFactory") + public void listenGroupFoo(String message) { + System.out.println("Received Messasge in group 'foo': " + message); + latch.countDown(); + } + + @KafkaListener(topics = "${message.topic.name}", group = "bar", containerFactory = "barKafkaListenerContainerFactory") + public void listenGroupBar(String message) { + System.out.println("Received Messasge in group 'bar': " + message); + latch.countDown(); + } + + } + +} diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java new file mode 100644 index 0000000000..f9edda2435 --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaConsumerConfig.java @@ -0,0 +1,45 @@ +package com.baeldung.spring.kafka; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.kafka.clients.consumer.ConsumerConfig; +import org.apache.kafka.common.serialization.StringDeserializer; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.annotation.EnableKafka; +import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory; +import org.springframework.kafka.core.ConsumerFactory; +import org.springframework.kafka.core.DefaultKafkaConsumerFactory; + +@EnableKafka +@Configuration +public class KafkaConsumerConfig { + + @Value(value = "${kafka.bootstrapAddress}") + private String bootstrapAddress; + + public ConsumerFactory consumerFactory(String groupId) { + Map props = new HashMap<>(); + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress); + props.put(ConsumerConfig.GROUP_ID_CONFIG, groupId); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); + return new DefaultKafkaConsumerFactory<>(props); + } + + @Bean + public ConcurrentKafkaListenerContainerFactory fooKafkaListenerContainerFactory() { + ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); + factory.setConsumerFactory(consumerFactory("foo")); + return factory; + } + + @Bean + public ConcurrentKafkaListenerContainerFactory barKafkaListenerContainerFactory() { + ConcurrentKafkaListenerContainerFactory factory = new ConcurrentKafkaListenerContainerFactory<>(); + factory.setConsumerFactory(consumerFactory("bar")); + return factory; + } +} diff --git a/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaProducerConfig.java b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaProducerConfig.java new file mode 100644 index 0000000000..4f9f9719ee --- /dev/null +++ b/spring-kafka/src/main/java/com/baeldung/spring/kafka/KafkaProducerConfig.java @@ -0,0 +1,36 @@ +package com.baeldung.spring.kafka; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.kafka.clients.producer.ProducerConfig; +import org.apache.kafka.common.serialization.StringSerializer; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.kafka.core.DefaultKafkaProducerFactory; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.kafka.core.ProducerFactory; + +@Configuration +public class KafkaProducerConfig { + + @Value(value = "${kafka.bootstrapAddress}") + private String bootstrapAddress; + + @Bean + public ProducerFactory producerFactory() { + Map configProps = new HashMap(); + configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapAddress); + configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class); + return new DefaultKafkaProducerFactory(configProps); + } + + @Bean + public KafkaTemplate kafkaTemplate() { + KafkaTemplate template = + new KafkaTemplate(producerFactory()); + return template; + } +} diff --git a/spring-kafka/src/main/resources/application.properties b/spring-kafka/src/main/resources/application.properties new file mode 100644 index 0000000000..a1d73b204c --- /dev/null +++ b/spring-kafka/src/main/resources/application.properties @@ -0,0 +1,2 @@ +kafka.bootstrapAddress=localhost:9092 +message.topic.name=baeldung diff --git a/spring-ldap/.gitignore b/spring-ldap/.gitignore new file mode 100644 index 0000000000..83c05e60c8 --- /dev/null +++ b/spring-ldap/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear \ No newline at end of file diff --git a/spring-ldap/README.md b/spring-ldap/README.md new file mode 100644 index 0000000000..8dffadb685 --- /dev/null +++ b/spring-ldap/README.md @@ -0,0 +1,8 @@ +### Relevant articles + +- [Spring LDAP Overview](http://www.baeldung.com/spring-ldap) + + +## Spring LDAP Example Project +- (http://www.baeldung.com/spring-ldap-overview/) + diff --git a/spring-ldap/pom.xml b/spring-ldap/pom.xml new file mode 100644 index 0000000000..55014897c4 --- /dev/null +++ b/spring-ldap/pom.xml @@ -0,0 +1,181 @@ + + + 4.0.0 + + com.baeldung + spring-ldap + 0.1-SNAPSHOT + jar + + + 4.12 + 2.19.1 + 3.6.1 + 2.3.1.RELEASE + 1.7.22 + 1.1.8 + 4.3.6.RELEASE + 1.5.5 + 0.9.15 + 1.3 + + + + spring-ldap + + + 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 + + + + + + + + + + org.springframework.ldap + spring-ldap-core + ${spring-ldap.version} + + + commons-logging + commons-logging + + + + + + org.slf4j + jcl-over-slf4j + ${jcl.slf4j.version} + + + + ch.qos.logback + logback-classic + ${logback.version} + + + org.springframework + spring-context + ${spring-context.version} + + + + + + + junit + junit + ${junit.version} + test + + + + org.hamcrest + hamcrest-core + ${org.hamcrest.version} + test + + + org.hamcrest + hamcrest-library + ${org.hamcrest.version} + test + + + + + org.springframework.ldap + spring-ldap-test + ${spring-ldap.version} + test + + + + + org.apache.directory.server + apacheds-core + ${apacheds.version} + test + + + org.apache.directory.server + apacheds-core-entry + ${apacheds.version} + test + + + org.apache.directory.server + apacheds-protocol-shared + ${apacheds.version} + test + + + org.apache.directory.server + apacheds-protocol-ldap + ${apacheds.version} + test + + + org.apache.directory.server + apacheds-server-jndi + ${apacheds.version} + test + + + org.apache.directory.shared + shared-ldap + ${shared-ldap.version} + test + + + + + + + live + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*IntegrationTest.java + + + **/*LiveTest.java + + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap/src/main/java/com/baeldung/ldap/client/LdapClient.java b/spring-ldap/src/main/java/com/baeldung/ldap/client/LdapClient.java new file mode 100644 index 0000000000..0c77d0f87d --- /dev/null +++ b/spring-ldap/src/main/java/com/baeldung/ldap/client/LdapClient.java @@ -0,0 +1,83 @@ +package com.baeldung.ldap.client; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.ldap.core.*; +import org.springframework.ldap.support.LdapNameBuilder; + +import javax.naming.Name; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.List; + +public class LdapClient { + + @Autowired + private Environment env; + + @Autowired + private ContextSource contextSource; + + @Autowired + private LdapTemplate ldapTemplate; + + public void authenticate(final String username, final String password) { + contextSource.getContext("cn=" + username + ",ou=users," + env.getRequiredProperty("ldap.partitionSuffix"), password); + } + + public List search(final String username) { + return ldapTemplate.search( + "ou=users", + "cn=" + username, + (AttributesMapper) attrs -> (String) attrs + .get("cn") + .get()); + } + + public void create(final String username, final String password) { + Name dn = LdapNameBuilder + .newInstance() + .add("ou", "users") + .add("cn", username) + .build(); + DirContextAdapter context = new DirContextAdapter(dn); + + context.setAttributeValues("objectclass", new String[] { "top", "person", "organizationalPerson", "inetOrgPerson" }); + context.setAttributeValue("cn", username); + context.setAttributeValue("sn", username); + context.setAttributeValue("userPassword", digestSHA(password)); + + ldapTemplate.bind(context); + } + + public void modify(final String username, final String password) { + Name dn = LdapNameBuilder + .newInstance() + .add("ou", "users") + .add("cn", username) + .build(); + DirContextOperations context = ldapTemplate.lookupContext(dn); + + context.setAttributeValues("objectclass", new String[] { "top", "person", "organizationalPerson", "inetOrgPerson" }); + context.setAttributeValue("cn", username); + context.setAttributeValue("sn", username); + context.setAttributeValue("userPassword", digestSHA(password)); + + ldapTemplate.modifyAttributes(context); + } + + private String digestSHA(final String password) { + String base64; + try { + MessageDigest digest = MessageDigest.getInstance("SHA"); + digest.update(password.getBytes()); + base64 = Base64 + .getEncoder() + .encodeToString(digest.digest()); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + return "{SHA}" + base64; + } +} diff --git a/spring-ldap/src/main/java/com/baeldung/ldap/javaconfig/AppConfig.java b/spring-ldap/src/main/java/com/baeldung/ldap/javaconfig/AppConfig.java new file mode 100644 index 0000000000..8572e5d1be --- /dev/null +++ b/spring-ldap/src/main/java/com/baeldung/ldap/javaconfig/AppConfig.java @@ -0,0 +1,44 @@ +package com.baeldung.ldap.javaconfig; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.ldap.core.LdapTemplate; +import org.springframework.ldap.core.support.LdapContextSource; + +import com.baeldung.ldap.client.LdapClient; + +@Configuration +@PropertySource("classpath:application.properties") +@ComponentScan(basePackages = { "com.baeldung.ldap.*" }) +@Profile("default") +public class AppConfig { + + @Autowired + private Environment env; + + @Bean + public LdapContextSource contextSource() { + LdapContextSource contextSource = new LdapContextSource(); + contextSource.setUrl(env.getRequiredProperty("ldap.url")); + contextSource.setBase(env.getRequiredProperty("ldap.partitionSuffix")); + contextSource.setUserDn(env.getRequiredProperty("ldap.principal")); + contextSource.setPassword(env.getRequiredProperty("ldap.password")); + return contextSource; + } + + @Bean + public LdapTemplate ldapTemplate() { + return new LdapTemplate(contextSource()); + } + + @Bean + public LdapClient ldapClient() { + return new LdapClient(); + } + +} diff --git a/spring-ldap/src/main/resources/application.properties b/spring-ldap/src/main/resources/application.properties new file mode 100644 index 0000000000..670fb79234 --- /dev/null +++ b/spring-ldap/src/main/resources/application.properties @@ -0,0 +1,6 @@ +ldap.partitionSuffix=dc=example,dc=com +ldap.partition=example +ldap.principal=uid=admin,ou=system +ldap.password=secret +ldap.port=18889 +ldap.url=ldap://localhost:18889 \ No newline at end of file diff --git a/spring-ldap/src/main/resources/logback.xml b/spring-ldap/src/main/resources/logback.xml new file mode 100644 index 0000000000..788096686a --- /dev/null +++ b/spring-ldap/src/main/resources/logback.xml @@ -0,0 +1,15 @@ + + + + + web - %date [%thread] %-5level %logger{36} - + %message%n + + + + + + + + + \ No newline at end of file diff --git a/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapClientLiveTest.java b/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapClientLiveTest.java new file mode 100644 index 0000000000..b65588dc38 --- /dev/null +++ b/spring-ldap/src/test/java/com/baeldung/ldap/client/LdapClientLiveTest.java @@ -0,0 +1,63 @@ +package com.baeldung.ldap.client; + +import java.util.List; + +import org.hamcrest.Matchers; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.ldap.AuthenticationException; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; + +import com.baeldung.ldap.javaconfig.TestConfig; + +@RunWith(SpringJUnit4ClassRunner.class) +@ActiveProfiles("testlive") +@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class) +public class LdapClientLiveTest { + + private static final String USER2 = "TEST02"; + private static final String USER3 = "TEST03"; + private static final String USER4 = "TEST04"; + + private static final String USER2_PWD = "TEST02"; + private static final String USER3_PWD = "TEST03"; + private static final String USER4_PWD = "TEST04"; + + private static final String SEARCH_STRING = "TEST*"; + + @Autowired + private LdapClient ldapClient; + + @Test + public void givenLdapClient_whenCorrectCredentials_thenSuccessfulLogin() { + ldapClient.authenticate(USER3, USER3_PWD); + } + + @Test(expected = AuthenticationException.class) + public void givenLdapClient_whenIncorrectCredentials_thenFailedLogin() { + ldapClient.authenticate(USER3, USER2_PWD); + } + + @Test + public void givenLdapClient_whenCorrectSearchFilter_thenEntriesReturned() { + List users = ldapClient.search(SEARCH_STRING); + Assert.assertThat(users, Matchers.containsInAnyOrder(USER2, USER3)); + } + + @Test + public void givenLdapClientNotExists_whenDataProvided_thenNewUserCreated() { + ldapClient.create(USER4, USER4_PWD); + ldapClient.authenticate(USER4, USER4_PWD); + } + + @Test + public void givenLdapClientExists_whenDataProvided_thenExistingUserModified() { + ldapClient.modify(USER2, USER3_PWD); + ldapClient.authenticate(USER2, USER3_PWD); + } +} diff --git a/spring-ldap/src/test/java/com/baeldung/ldap/javaconfig/TestConfig.java b/spring-ldap/src/test/java/com/baeldung/ldap/javaconfig/TestConfig.java new file mode 100644 index 0000000000..e2968e977c --- /dev/null +++ b/spring-ldap/src/test/java/com/baeldung/ldap/javaconfig/TestConfig.java @@ -0,0 +1,59 @@ +package com.baeldung.ldap.javaconfig; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.core.io.ResourceLoader; +import org.springframework.ldap.core.LdapTemplate; +import org.springframework.ldap.core.support.LdapContextSource; +import org.springframework.ldap.test.TestContextSourceFactoryBean; + +import com.baeldung.ldap.client.LdapClient; + +@Configuration +@PropertySource("classpath:test_application.properties") +@ComponentScan(basePackages = { "com.baeldung.ldap.*" }) +@Profile("testlive") +public class TestConfig { + @Autowired + private Environment env; + + @Autowired + private ResourceLoader resourceLoader; + + @Bean + public TestContextSourceFactoryBean testContextSource() { + TestContextSourceFactoryBean contextSource = new TestContextSourceFactoryBean(); + contextSource.setDefaultPartitionName(env.getRequiredProperty("ldap.partition")); + contextSource.setDefaultPartitionSuffix(env.getRequiredProperty("ldap.partitionSuffix")); + contextSource.setPrincipal(env.getRequiredProperty("ldap.principal")); + contextSource.setPassword(env.getRequiredProperty("ldap.password")); + contextSource.setLdifFile(resourceLoader.getResource(env.getRequiredProperty("ldap.ldiffile"))); + contextSource.setPort(Integer.valueOf(env.getRequiredProperty("ldap.port"))); + return contextSource; + } + + @Bean + public LdapContextSource contextSource() { + LdapContextSource contextSource = new LdapContextSource(); + contextSource.setUrl(env.getRequiredProperty("ldap.url")); + contextSource.setBase(env.getRequiredProperty("ldap.partitionSuffix")); + contextSource.setUserDn(env.getRequiredProperty("ldap.principal")); + contextSource.setPassword(env.getRequiredProperty("ldap.password")); + return contextSource; + } + + @Bean + public LdapTemplate ldapTemplate() { + return new LdapTemplate(contextSource()); + } + + @Bean + public LdapClient ldapClient() { + return new LdapClient(); + } +} diff --git a/spring-ldap/src/test/resources/test.ldif b/spring-ldap/src/test/resources/test.ldif new file mode 100644 index 0000000000..2344630204 --- /dev/null +++ b/spring-ldap/src/test/resources/test.ldif @@ -0,0 +1,24 @@ +version: 1 +dn: ou=users,dc=example,dc=com +objectClass: organizationalUnit +objectClass: top +ou: users + +dn: cn=TEST03,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +objectClass: organizationalPerson +objectClass: person +objectClass: top +cn: TEST03 +sn: TEST03 +userPassword:: e1NIQX1JbktFOFY2enBpWWdMY0RYQTYzdXZVNjRGZXc9 + +dn: cn=TEST02,ou=users,dc=example,dc=com +objectClass: inetOrgPerson +objectClass: organizationalPerson +objectClass: person +objectClass: top +cn: TEST02 +sn: TEST02 +userPassword:: e1NIQX1uZERKdWNNYnl5a3hWdEkyQzgyRUFlalN1WTQ9 + diff --git a/spring-ldap/src/test/resources/test_application.properties b/spring-ldap/src/test/resources/test_application.properties new file mode 100644 index 0000000000..40b90cfdcf --- /dev/null +++ b/spring-ldap/src/test/resources/test_application.properties @@ -0,0 +1,7 @@ +ldap.partitionSuffix=dc=example,dc=com +ldap.partition=example +ldap.principal=uid=admin,ou=system +ldap.password=secret +ldap.ldiffile=classpath:/test.ldif +ldap.port=18888 +ldap.url=ldap://localhost:18888 \ No newline at end of file diff --git a/spring-mvc-forms/pom.xml b/spring-mvc-forms/pom.xml index 35ed00c0e9..e5ffb52801 100644 --- a/spring-mvc-forms/pom.xml +++ b/spring-mvc-forms/pom.xml @@ -46,6 +46,12 @@ commons-fileupload ${fileupload.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + @@ -89,16 +95,17 @@ - 4.3.4.RELEASE + 4.3.7.RELEASE 2.6 1.2 2.3.1 3.1.0 3.6.0 1.8 - 5.3.3.Final + 5.4.0.Final enter-location-of-server 1.3.2 + 2.8.7 diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/ApplicationConfiguration.java b/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/ApplicationConfiguration.java index 3f7889422f..7292d95b21 100644 --- a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/ApplicationConfiguration.java +++ b/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/configuration/ApplicationConfiguration.java @@ -27,6 +27,16 @@ class ApplicationConfiguration extends WebMvcConfigurerAdapter { bean.setSuffix(".jsp"); return bean; } + + + @Bean + public InternalResourceViewResolver htmlViewResolver() { + InternalResourceViewResolver bean = new InternalResourceViewResolver(); + bean.setPrefix("/WEB-INF/html/"); + bean.setSuffix(".html"); + bean.setOrder(2); + return bean; + } @Bean public MultipartResolver multipartResolver() { diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/UserController.java b/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/UserController.java new file mode 100644 index 0000000000..880b224dd9 --- /dev/null +++ b/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/controller/UserController.java @@ -0,0 +1,63 @@ +package com.baeldung.springmvcforms.controller; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.validation.Valid; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.validation.ObjectError; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import com.baeldung.springmvcforms.domain.User; + +@Controller +public class UserController { + + List users = new ArrayList() { + { + add(new User("ana@yahoo.com", "pass", "Ana", 20)); + add(new User("bob@yahoo.com", "pass", "Bob", 30)); + add(new User("john@yahoo.com", "pass", "John", 40)); + add(new User("mary@yahoo.com", "pass", "Mary", 30)); + } + }; + + @GetMapping("/userPage") + public String getUserProfilePage() { + return "user"; + } + + @PostMapping(value = "/user", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public ResponseEntity saveUser(@Valid User user, BindingResult result, Model model) { + if (result.hasErrors()) { + List errors = new ArrayList<>(); + result.getAllErrors().forEach(item->{ + errors.add(item.getDefaultMessage()); + }); + return new ResponseEntity<>(errors, HttpStatus.OK); + } else { + if (users.stream().anyMatch(it -> user.getEmail().equals(it.getEmail()))) { + return new ResponseEntity<>(Collections.singletonList("Email already exists!"), HttpStatus.CONFLICT); + } else { + users.add(user); + return new ResponseEntity<>(HttpStatus.CREATED); + } + } + } + + @GetMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public List getUsers() { + return users; + } + +} diff --git a/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/domain/User.java b/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/domain/User.java new file mode 100644 index 0000000000..49f006f422 --- /dev/null +++ b/spring-mvc-forms/src/main/java/com/baeldung/springmvcforms/domain/User.java @@ -0,0 +1,71 @@ +package com.baeldung.springmvcforms.domain; + +import javax.validation.constraints.Digits; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; + +import org.hibernate.validator.constraints.Email; +import org.hibernate.validator.constraints.NotBlank; + +public class User { + + @NotNull + @Email + private String email; + + @NotNull + @Size(min = 4, max = 15) + private String password; + + @NotBlank + private String name; + + @Min(18) + @Digits(integer = 2, fraction = 0) + private int age; + + public User() { + + } + + public User(String email, String password, String name, int age) { + super(); + this.email = email; + this.password = password; + this.name = name; + this.age = age; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/spring-mvc-forms/src/main/webapp/WEB-INF/html/user.html b/spring-mvc-forms/src/main/webapp/WEB-INF/html/user.html new file mode 100644 index 0000000000..a505f51f32 --- /dev/null +++ b/spring-mvc-forms/src/main/webapp/WEB-INF/html/user.html @@ -0,0 +1,68 @@ + + + + +Users + + + + + + + + +
+ + + +
+

Invalid email!

+

Email is required!

+
+
+ + + +
+

Password must be at least 4 characters!

+

Password must not be longer than 15 characters!

+

Password is required!

+
+
+ + + +
+

Name is required!

+
+
+ + + +
+

Age must be greater than 18!

+

Age must be greater than 18!

+
+
+
+ + +
+ +
+
{{errorMessage}}
+
{{message}}
+
+ +All Users:
+ + + + + + + +
EmailNameAge
{{usr.email}} {{usr.name}} {{usr.age}}
+ + \ No newline at end of file diff --git a/spring-mvc-forms/src/main/webapp/css/user.css b/spring-mvc-forms/src/main/webapp/css/user.css new file mode 100644 index 0000000000..bcfb62a33c --- /dev/null +++ b/spring-mvc-forms/src/main/webapp/css/user.css @@ -0,0 +1,77 @@ +.form-label { + display:block; + margin-top:16px; + font-weight:bold; +} + +.form-input { + border-radius:5px; + display:inline; +} + +.form-input p { + margin:0; +} + +.form-button { + margin:5px; +} + +.form-error input.ng-invalid { + border-color:red; +} + +.check { + display:inline; + color:green; + font-weight:bold; +} + +.error-messages { + color:red; +} + +.error-messages p { + margin:0; +} + +#customers { + font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; + border-collapse: collapse; + width: 100%; +} + +#users td, #users th { + border: 1px solid dodgerblue; + border-collapse:collapse; + padding: 4px; + width:200px; +} + +#users tr:nth-child(even){background-color: lavender;} + +#users th { + padding-top: 10px; + padding-bottom: 10px; + text-align: left; + background-color: dodgerblue; +} + +#users { + border-collapse:collapse; +} + +button { + border-radius:5px; + cursor:pointer; + margin:10px; + padding:5px; +} + +.form-button-save { + background-color:lightgreen; +} + +.form-button-reset { + background-color:lightpink; +} \ No newline at end of file diff --git a/spring-mvc-forms/src/main/webapp/js/app.js b/spring-mvc-forms/src/main/webapp/js/app.js new file mode 100644 index 0000000000..6a290b3cf0 --- /dev/null +++ b/spring-mvc-forms/src/main/webapp/js/app.js @@ -0,0 +1,70 @@ +var app = angular.module('app', ['ngMessages']); + +app.controller('UserCtrl', ['$scope','UserService', function ($scope,UserService) { + + $scope.submitted = false; + + $scope.getUsers = function() { + UserService.getUsers().then( function(data){ + $scope.users = data; + }); + } + + $scope.saveUser = function () { + $scope.submitted = true; + if ($scope.userForm.$valid){ + UserService.saveUser($scope.user) + .then (function success(response){ + $scope.message = 'User added!'; + $scope.errorMessage = ''; + $scope.getUsers(); + $scope.user = null; + $scope.submitted = false; + }, + function error(response){ + if (response.status == 409){ + $scope.errorMessage = response.data[0]; + } + else { + $scope.errorMessage = 'Error adding user!'; + } + $scope.message = ''; + }); + } + } + + $scope.getUsers(); + + $scope.resetForm = function () { + $scope.userForm.$setPristine(); + $scope.user=null; + $scope.message=''; + $scope.errorMessage=''; + $scope.submitted = false; + } + +}]); + +app.service('UserService',['$http', function ($http) { + + this.saveUser = function saveUser(user){ + return $http({ + method: 'POST', + url: 'user', + params: {email:user.email, password:user.password, name:user.name, age:user.age}, + headers: 'Accept:application/json' + }); + } + + + this.getUsers = function getUsers(){ + return $http({ + method: 'GET', + url: 'users', + headers:'Accept:application/json' + }).then( function(response){ + return response.data; + } ); + } + +}]); \ No newline at end of file diff --git a/spring-security-basic-auth/README.md b/spring-security-basic-auth/README.md index 54d09dbf32..8aa299f8cc 100644 --- a/spring-security-basic-auth/README.md +++ b/spring-security-basic-auth/README.md @@ -6,7 +6,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com ### Relevant Article: -- [Spring Security - security none, filters none, access permitAll](http://www.baeldung.com/security-none-filters-none-access-permitAll) - [Spring Security Basic Authentication](http://www.baeldung.com/spring-security-basic-authentication) - [Writing a Custom Filter in Spring Security](http://www.baeldung.com/spring-security-custom-filter) diff --git a/spring-security-cache-control/src/test/java/com/baeldung/cachecontrol/ResourceEndpointTest.java b/spring-security-cache-control/src/test/java/com/baeldung/cachecontrol/ResourceEndpointIntegrationTest.java similarity index 50% rename from spring-security-cache-control/src/test/java/com/baeldung/cachecontrol/ResourceEndpointTest.java rename to spring-security-cache-control/src/test/java/com/baeldung/cachecontrol/ResourceEndpointIntegrationTest.java index 6d532f98fc..2c48878917 100644 --- a/spring-security-cache-control/src/test/java/com/baeldung/cachecontrol/ResourceEndpointTest.java +++ b/spring-security-cache-control/src/test/java/com/baeldung/cachecontrol/ResourceEndpointIntegrationTest.java @@ -1,68 +1,45 @@ package com.baeldung.cachecontrol; -import com.jayway.restassured.http.ContentType; +import static com.jayway.restassured.RestAssured.given; + 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.junit4.SpringRunner; -import static com.jayway.restassured.RestAssured.given; +import com.jayway.restassured.http.ContentType; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = AppRunner.class) -public class ResourceEndpointTest { +public class ResourceEndpointIntegrationTest { @LocalServerPort private int serverPort; @Test public void whenGetRequestForUser_shouldRespondWithDefaultCacheHeaders() { - given() - .when() - .get(getBaseUrl() + "/default/users/Michael") - .then() - .headers("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate") - .header("Pragma", "no-cache"); + given().when().get(getBaseUrl() + "/default/users/Michael").then().headers("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate").header("Pragma", "no-cache"); } @Test public void whenGetRequestForUser_shouldRespondMaxAgeCacheControl() { - given() - .when() - .get(getBaseUrl() + "/users/Michael") - .then() - .header("Cache-Control", "max-age=60"); + given().when().get(getBaseUrl() + "/users/Michael").then().header("Cache-Control", "max-age=60"); } @Test public void givenServiceEndpoint_whenGetRequestForUser_shouldResponseWithCacheControlMaxAge() { - given() - .when() - .get(getBaseUrl() + "/users/Michael") - .then() - .contentType(ContentType.JSON).and().statusCode(200).and() - .header("Cache-Control", "max-age=60"); + given().when().get(getBaseUrl() + "/users/Michael").then().contentType(ContentType.JSON).and().statusCode(200).and().header("Cache-Control", "max-age=60"); } @Test public void givenServiceEndpoint_whenGetRequestForNotCacheableContent_shouldResponseWithCacheControlNoCache() { - given() - .when() - .get(getBaseUrl() + "/timestamp") - .then() - .contentType(ContentType.JSON).and().statusCode(200).and() - .header("Cache-Control", "no-store"); + given().when().get(getBaseUrl() + "/timestamp").then().contentType(ContentType.JSON).and().statusCode(200).and().header("Cache-Control", "no-store"); } @Test public void givenServiceEndpoint_whenGetRequestForPrivateUser_shouldResponseWithSecurityDefaultCacheControl() { - given() - .when() - .get(getBaseUrl() + "/private/users/Michael") - .then() - .contentType(ContentType.JSON).and().statusCode(200).and() - .header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate"); + given().when().get(getBaseUrl() + "/private/users/Michael").then().contentType(ContentType.JSON).and().statusCode(200).and().header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate"); } private String getBaseUrl() { diff --git a/spring-security-mvc-boot/README.MD b/spring-security-mvc-boot/README.MD index 3e789dedad..70b0f23cbb 100644 --- a/spring-security-mvc-boot/README.MD +++ b/spring-security-mvc-boot/README.MD @@ -6,3 +6,4 @@ The "REST With Spring" Classes: http://github.learnspringsecurity.com - [Custom AccessDecisionVoters in Spring Security](http://www.baeldung.com/spring-security-custom-voter) - [Spring Security: Authentication with a Database-backed UserDetailsService](http://www.baeldung.com/spring-security-authentication-with-a-database) - [Two Login Pages with Spring Security](http://www.baeldung.com/spring-security-two-login-pages) +- [Multiple Entry Points in Spring Security](http://www.baeldung.com/spring-security-multiple-entry-points) diff --git a/spring-security-mvc-boot/pom.xml b/spring-security-mvc-boot/pom.xml index 591ededccf..0b113f4cbf 100644 --- a/spring-security-mvc-boot/pom.xml +++ b/spring-security-mvc-boot/pom.xml @@ -14,19 +14,19 @@ org.springframework.boot spring-boot-starter-parent - 1.4.4.RELEASE + 1.5.2.RELEASE + org.springframework.boot spring-boot-starter-security - + org.springframework.boot spring-boot-starter-web - org.springframework.boot spring-boot-starter-tomcat @@ -54,13 +54,13 @@ com.h2database h2 - + org.springframework.boot spring-boot-starter-test test - + junit junit @@ -97,6 +97,12 @@ spring-test test + + + org.springframework.security + spring-security-test + test + org.apache.derby @@ -140,7 +146,7 @@ jstl-api ${jstl.version} - + @@ -158,6 +164,7 @@ **/*IntegrationTest.java **/*LiveTest.java + **/*EntryPointsTest.java @@ -279,6 +286,43 @@ + + + entryPoints + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + integration-test + + test + + + + **/*LiveTest.java + **/*IntegrationTest.java + + + **/*EntryPointsTest.java + + + + + + + json + + + + + + + @@ -288,12 +332,16 @@ + + + UTF-8 1.8 10.13.1.1 1.1.2 - 4.2.0.RELEASE - 4.2.0.RELEASE + 4.2.2.RELEASE + 4.2.2.RELEASE + 4.2.2.RELEASE 1.2 2.4.0 diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/Application.java b/spring-security-mvc-boot/src/main/java/org/baeldung/Application.java index 03de5897f5..fa10799caa 100644 --- a/spring-security-mvc-boot/src/main/java/org/baeldung/Application.java +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/Application.java @@ -2,15 +2,15 @@ package org.baeldung; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.context.web.SpringBootServletInitializer; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.FilterType; @Configuration @EnableAutoConfiguration -@ComponentScan(excludeFilters = { @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.voter.*"), @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.multiplelogin.*") }) -public class Application extends SpringBootServletInitializer { +@ComponentScan(excludeFilters = { @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.voter.*"), @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.multiplelogin.*"), + @ComponentScan.Filter(type = FilterType.REGEX, pattern = "org.baeldung.multipleentrypoints.*") }) +public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/MultipleEntryPointsApplication.java b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/MultipleEntryPointsApplication.java new file mode 100644 index 0000000000..4e5fafcd99 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/MultipleEntryPointsApplication.java @@ -0,0 +1,12 @@ +package org.baeldung.multipleentrypoints; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +// @ImportResource({"classpath*:spring-security-multiple-entry.xml"}) +public class MultipleEntryPointsApplication { + public static void main(String[] args) { + SpringApplication.run(MultipleEntryPointsApplication.class, args); + } +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/MultipleEntryPointsSecurityConfig.java b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/MultipleEntryPointsSecurityConfig.java new file mode 100644 index 0000000000..9f2eba0a2e --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/MultipleEntryPointsSecurityConfig.java @@ -0,0 +1,92 @@ +package org.baeldung.multipleentrypoints; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.provisioning.InMemoryUserDetailsManager; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint; +import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; +import org.springframework.security.web.util.matcher.AntPathRequestMatcher; + +@Configuration +@EnableWebSecurity +public class MultipleEntryPointsSecurityConfig { + + @Bean + public UserDetailsService userDetailsService() throws Exception { + InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(); + manager.createUser(User.withUsername("user").password("userPass").roles("USER").build()); + manager.createUser(User.withUsername("admin").password("adminPass").roles("ADMIN").build()); + return manager; + } + + @Configuration + @Order(1) + public static class App1ConfigurationAdapter extends WebSecurityConfigurerAdapter { + + @Override + protected void configure(HttpSecurity http) throws Exception { + //@formatter:off + http.antMatcher("/admin/**") + .authorizeRequests().anyRequest().hasRole("ADMIN") + .and().httpBasic().authenticationEntryPoint(authenticationEntryPoint()) + .and().exceptionHandling().accessDeniedPage("/403"); + //@formatter:on + } + + @Bean + public AuthenticationEntryPoint authenticationEntryPoint(){ + BasicAuthenticationEntryPoint entryPoint = new BasicAuthenticationEntryPoint(); + entryPoint.setRealmName("admin realm"); + return entryPoint; + } + } + + @Configuration + @Order(2) + public static class App2ConfigurationAdapter extends WebSecurityConfigurerAdapter { + + protected void configure(HttpSecurity http) throws Exception { + + //@formatter:off + http.antMatcher("/user/**") + .authorizeRequests().anyRequest().hasRole("USER") + .and().formLogin().loginProcessingUrl("/user/login") + .failureUrl("/userLogin?error=loginError").defaultSuccessUrl("/user/myUserPage") + .and().logout().logoutUrl("/user/logout").logoutSuccessUrl("/multipleHttpLinks") + .deleteCookies("JSESSIONID") + .and().exceptionHandling() + .defaultAuthenticationEntryPointFor(loginUrlauthenticationEntryPointWithWarning(), new AntPathRequestMatcher("/user/private/**")) + .defaultAuthenticationEntryPointFor(loginUrlauthenticationEntryPoint(), new AntPathRequestMatcher("/user/general/**")) + .accessDeniedPage("/403") + .and().csrf().disable(); + //@formatter:on + } + + @Bean + public AuthenticationEntryPoint loginUrlauthenticationEntryPoint(){ + return new LoginUrlAuthenticationEntryPoint("/userLogin"); + } + + @Bean + public AuthenticationEntryPoint loginUrlauthenticationEntryPointWithWarning(){ + return new LoginUrlAuthenticationEntryPoint("/userLoginWithWarning"); + } + } + + @Configuration + @Order(3) + public static class App3ConfigurationAdapter extends WebSecurityConfigurerAdapter { + + protected void configure(HttpSecurity http) throws Exception { + http.antMatcher("/guest/**").authorizeRequests().anyRequest().permitAll(); + } + } + +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/PagesController.java b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/PagesController.java new file mode 100644 index 0000000000..b3462d4061 --- /dev/null +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/multipleentrypoints/PagesController.java @@ -0,0 +1,48 @@ +package org.baeldung.multipleentrypoints; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller +public class PagesController { + + @RequestMapping("/multipleHttpLinks") + public String getMultipleHttpLinksPage() { + return "multipleHttpElems/multipleHttpLinks"; + } + + @RequestMapping("/admin/myAdminPage") + public String getAdminPage() { + return "multipleHttpElems/myAdminPage"; + } + + @RequestMapping("/user/general/myUserPage") + public String getUserPage() { + return "multipleHttpElems/myUserPage"; + } + + @RequestMapping("/user/private/myPrivateUserPage") + public String getPrivateUserPage() { + return "multipleHttpElems/myPrivateUserPage"; + } + + @RequestMapping("/guest/myGuestPage") + public String getGuestPage() { + return "multipleHttpElems/myGuestPage"; + } + + @RequestMapping("/userLogin") + public String getUserLoginPage() { + return "multipleHttpElems/login"; + } + + @RequestMapping("/userLoginWithWarning") + public String getUserLoginPageWithWarning() { + return "multipleHttpElems/loginWithWarning"; + } + + @RequestMapping("/403") + public String getAccessDeniedPage() { + return "403"; + } +} diff --git a/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/MultipleLoginApplication.java b/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/MultipleLoginApplication.java index 836336eb71..e9dc541ad3 100644 --- a/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/MultipleLoginApplication.java +++ b/spring-security-mvc-boot/src/main/java/org/baeldung/multiplelogin/MultipleLoginApplication.java @@ -2,7 +2,6 @@ package org.baeldung.multiplelogin; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.context.web.SpringBootServletInitializer; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -10,13 +9,8 @@ import org.springframework.boot.builder.SpringApplicationBuilder; @SpringBootApplication @ComponentScan("org.baeldung.multiplelogin") -public class MultipleLoginApplication extends SpringBootServletInitializer { +public class MultipleLoginApplication { public static void main(String[] args) { SpringApplication.run(MultipleLoginApplication.class, args); } - - @Override - protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { - return application.sources(MultipleLoginApplication.class); - } } \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/spring-security-multiple-entry.xml b/spring-security-mvc-boot/src/main/resources/spring-security-multiple-entry.xml new file mode 100644 index 0000000000..c026700810 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/spring-security-multiple-entry.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/login.html b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/login.html new file mode 100644 index 0000000000..2119baec66 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/login.html @@ -0,0 +1,27 @@ + + + + +

Login

+ +
+ + + + + + + + + + + + + + +
Username:
Password:
+ +
+ + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/loginWithWarning.html b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/loginWithWarning.html new file mode 100644 index 0000000000..a5b2eaf3dc --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/loginWithWarning.html @@ -0,0 +1,28 @@ + + + + +

Login

+

Warning! You are about to access sensible data!

+ +
+ + + + + + + + + + + + + + +
Username:
Password:
+ +
+ + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/multipleHttpLinks.html b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/multipleHttpLinks.html new file mode 100644 index 0000000000..676badb16f --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/multipleHttpLinks.html @@ -0,0 +1,18 @@ + + + + +Multiple Http Elements Links + + + +Admin page +
+User page +
+Private user page +
+Guest page + + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myAdminPage.html b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myAdminPage.html new file mode 100644 index 0000000000..3003833562 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myAdminPage.html @@ -0,0 +1,13 @@ + + + + +Admin Page + + +Welcome admin! + +

+Back to links + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myGuestPage.html b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myGuestPage.html new file mode 100644 index 0000000000..47a4c9c44a --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myGuestPage.html @@ -0,0 +1,13 @@ + + + + +Guest Page + + +Welcome guest! + +

+Back to links + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myPrivateUserPage.html b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myPrivateUserPage.html new file mode 100644 index 0000000000..52045ec320 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myPrivateUserPage.html @@ -0,0 +1,13 @@ + + + + +Insert title here + + +Welcome user to your private page! Logout + +

+Back to links + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myUserPage.html b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myUserPage.html new file mode 100644 index 0000000000..f6c2def0b8 --- /dev/null +++ b/spring-security-mvc-boot/src/main/resources/templates/multipleHttpElems/myUserPage.html @@ -0,0 +1,13 @@ + + + + +User Page + + +Welcome user! Logout + +

+Back to links + + \ No newline at end of file diff --git a/spring-security-mvc-boot/src/test/java/org/baeldung/web/CustomUserDetailsServiceIntegrationTest.java b/spring-security-mvc-boot/src/test/java/org/baeldung/web/CustomUserDetailsServiceIntegrationTest.java index 616e80e6e9..3dd4b236f9 100644 --- a/spring-security-mvc-boot/src/test/java/org/baeldung/web/CustomUserDetailsServiceIntegrationTest.java +++ b/spring-security-mvc-boot/src/test/java/org/baeldung/web/CustomUserDetailsServiceIntegrationTest.java @@ -11,7 +11,6 @@ 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.SpringApplicationConfiguration; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -19,9 +18,10 @@ import org.springframework.security.core.Authentication; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.boot.test.context.SpringBootTest; @RunWith(SpringJUnit4ClassRunner.class) -@SpringApplicationConfiguration(classes = { MvcConfig.class, SecurityConfig.class, PersistenceConfig.class }) +@SpringBootTest(classes = { MvcConfig.class, SecurityConfig.class, PersistenceConfig.class }) @WebAppConfiguration public class CustomUserDetailsServiceIntegrationTest { diff --git a/spring-security-mvc-boot/src/test/java/org/baeldung/web/MultipleEntryPointsTest.java b/spring-security-mvc-boot/src/test/java/org/baeldung/web/MultipleEntryPointsTest.java new file mode 100644 index 0000000000..050d2363af --- /dev/null +++ b/spring-security-mvc-boot/src/test/java/org/baeldung/web/MultipleEntryPointsTest.java @@ -0,0 +1,64 @@ +package org.baeldung.web; + +import org.baeldung.multipleentrypoints.MultipleEntryPointsApplication; +import org.junit.Before; +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.security.web.FilterChainProxy; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*; + +@RunWith(SpringRunner.class) +@WebAppConfiguration +@SpringBootTest(classes = MultipleEntryPointsApplication.class) +public class MultipleEntryPointsTest { + @Autowired + private WebApplicationContext wac; + + @Autowired + private FilterChainProxy springSecurityFilterChain; + + private MockMvc mockMvc; + + @Before + public void setup() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).addFilter(springSecurityFilterChain).build(); + } + + @Test + public void whenTestAdminCredentials_thenOk() throws Exception { + mockMvc.perform(get("/admin/myAdminPage")).andExpect(status().isUnauthorized()); + + mockMvc.perform(get("/admin/myAdminPage").with(httpBasic("admin", "adminPass"))).andExpect(status().isOk()); + + mockMvc.perform(get("/user/myUserPage").with(user("admin").password("adminPass").roles("ADMIN"))).andExpect(status().isForbidden()); + + } + + @Test + public void whenTestUserCredentials_thenOk() throws Exception { + mockMvc.perform(get("/user/general/myUserPage")).andExpect(status().isFound()); + + mockMvc.perform(get("/user/general/myUserPage").with(user("user").password("userPass").roles("USER"))).andExpect(status().isOk()); + + mockMvc.perform(get("/admin/myAdminPage").with(user("user").password("userPass").roles("USER"))).andExpect(status().isForbidden()); + } + + @Test + public void givenAnyUser_whenGetGuestPage_thenOk() throws Exception { + mockMvc.perform(get("/guest/myGuestPage")).andExpect(status().isOk()); + + mockMvc.perform(get("/guest/myGuestPage").with(user("user").password("userPass").roles("USER"))).andExpect(status().isOk()); + + mockMvc.perform(get("/guest/myGuestPage").with(httpBasic("admin", "adminPass"))).andExpect(status().isOk()); + } +} diff --git a/spring-security-openid/README.md b/spring-security-openid/README.md index 79bf44f374..8c65c09f2f 100644 --- a/spring-security-openid/README.md +++ b/spring-security-openid/README.md @@ -1,4 +1,7 @@ -========= +### Relevant articles + +- [Spring Security and OpenID Connect](http://www.baeldung.com/spring-security-openid-connect) + ## OpenID Connect with Spring Security @@ -13,3 +16,4 @@ mvn spring-boot:run - Make sure you set redirect URI to http://localhost:8081/google-login - Once you have your client id and secret, make sure you add them to the `application.properties` of the project + diff --git a/spring-security-openid/pom.xml b/spring-security-openid/pom.xml index ff0b030bd2..72cc63474b 100644 --- a/spring-security-openid/pom.xml +++ b/spring-security-openid/pom.xml @@ -13,7 +13,7 @@ org.springframework.boot spring-boot-starter-parent - 1.4.4.RELEASE + 1.5.2.RELEASE diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/IEnhancedSpecification.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/IEnhancedSpecification.java new file mode 100644 index 0000000000..58d08a161e --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/IEnhancedSpecification.java @@ -0,0 +1,10 @@ +package org.baeldung.persistence; + +import org.springframework.data.jpa.domain.Specification; + +public interface IEnhancedSpecification extends Specification { + + default boolean isOfLowPrecedence() { + return false; + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/GenericSpecificationsBuilder.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/GenericSpecificationsBuilder.java new file mode 100644 index 0000000000..4936c2e1c1 --- /dev/null +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/GenericSpecificationsBuilder.java @@ -0,0 +1,64 @@ +package org.baeldung.persistence.dao; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.baeldung.web.util.SearchOperation; +import org.baeldung.web.util.SpecSearchCriteria; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.domain.Specifications; + +public class GenericSpecificationsBuilder { + + private final List params; + + public GenericSpecificationsBuilder() { + this.params = new ArrayList<>(); + } + + public final GenericSpecificationsBuilder with(final String key, final String operation, final Object value, + final String prefix, final String suffix) { + return with(null, key, operation, value, prefix, suffix); + } + + public final GenericSpecificationsBuilder with(final String precedenceIndicator, final String key, + final String operation, final Object value, final String prefix, final String suffix) { + SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0)); + if (op != null) { + if (op == SearchOperation.EQUALITY) // the operation may be complex operation + { + final boolean startWithAsterisk = prefix != null && prefix.contains(SearchOperation.ZERO_OR_MORE_REGEX); + final boolean endWithAsterisk = suffix != null && suffix.contains(SearchOperation.ZERO_OR_MORE_REGEX); + + if (startWithAsterisk && endWithAsterisk) { + op = SearchOperation.CONTAINS; + } else if (startWithAsterisk) { + op = SearchOperation.ENDS_WITH; + } else if (endWithAsterisk) { + op = SearchOperation.STARTS_WITH; + } + } + params.add(new SpecSearchCriteria(precedenceIndicator, key, op, value)); + } + return this; + } + + public Specification build(Function> converter) { + + if (params.size() == 0) + return null; + + params.sort((spec0, spec1) -> Boolean.compare(spec0.isLowPrecedence(), spec1.isLowPrecedence())); + + final List> specs = params.stream().map(converter).collect(Collectors.toCollection(ArrayList::new)); + + Specification result = specs.get(0); + + for (int idx = 1; idx < specs.size(); idx++) { + result=params.get(idx).isLowPrecedence()? Specifications.where(result).or(specs.get(idx)): Specifications.where(result).and(specs.get(idx)); + } + return result; + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecification.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecification.java index e41c7ca663..2788c46fde 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecification.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecification.java @@ -11,39 +11,39 @@ import org.springframework.data.jpa.domain.Specification; public class UserSpecification implements Specification { - private SpecSearchCriteria criteria; + private SpecSearchCriteria criteria; - public UserSpecification(final SpecSearchCriteria criteria) { - super(); - this.criteria = criteria; - } + public UserSpecification(final SpecSearchCriteria criteria) { + super(); + this.criteria = criteria; + } - public SpecSearchCriteria getCriteria() { - return criteria; - } + public SpecSearchCriteria getCriteria() { + return criteria; + } - @Override - public Predicate toPredicate(final Root root, final CriteriaQuery query, final CriteriaBuilder builder) { - switch (criteria.getOperation()) { - case EQUALITY: - return builder.equal(root.get(criteria.getKey()), criteria.getValue()); - case NEGATION: - return builder.notEqual(root.get(criteria.getKey()), criteria.getValue()); - case GREATER_THAN: - return builder.greaterThan(root. get(criteria.getKey()), criteria.getValue().toString()); - case LESS_THAN: - return builder.lessThan(root. get(criteria.getKey()), criteria.getValue().toString()); - case LIKE: - return builder.like(root. get(criteria.getKey()), criteria.getValue().toString()); - case STARTS_WITH: - return builder.like(root. get(criteria.getKey()), criteria.getValue() + "%"); - case ENDS_WITH: - return builder.like(root. get(criteria.getKey()), "%" + criteria.getValue()); - case CONTAINS: - return builder.like(root. get(criteria.getKey()), "%" + criteria.getValue() + "%"); - default: - return null; - } - } + @Override + public Predicate toPredicate(final Root root, final CriteriaQuery query, final CriteriaBuilder builder) { + switch (criteria.getOperation()) { + case EQUALITY: + return builder.equal(root.get(criteria.getKey()), criteria.getValue()); + case NEGATION: + return builder.notEqual(root.get(criteria.getKey()), criteria.getValue()); + case GREATER_THAN: + return builder.greaterThan(root. get(criteria.getKey()), criteria.getValue().toString()); + case LESS_THAN: + return builder.lessThan(root. get(criteria.getKey()), criteria.getValue().toString()); + case LIKE: + return builder.like(root. get(criteria.getKey()), criteria.getValue().toString()); + case STARTS_WITH: + return builder.like(root. get(criteria.getKey()), criteria.getValue() + "%"); + case ENDS_WITH: + return builder.like(root. get(criteria.getKey()), "%" + criteria.getValue()); + case CONTAINS: + return builder.like(root. get(criteria.getKey()), "%" + criteria.getValue() + "%"); + default: + return null; + } + } } diff --git a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java index 3db4267ae0..8a10163f51 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/persistence/dao/UserSpecificationsBuilder.java @@ -1,60 +1,74 @@ -package org.baeldung.persistence.dao; - -import java.util.ArrayList; -import java.util.List; - -import org.baeldung.persistence.model.User; -import org.baeldung.web.util.SearchOperation; -import org.baeldung.web.util.SpecSearchCriteria; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.data.jpa.domain.Specifications; - -public final class UserSpecificationsBuilder { - - private final List params; - - public UserSpecificationsBuilder() { - params = new ArrayList(); - } - - // API - - public final UserSpecificationsBuilder with(final String key, final String operation, final Object value, final String prefix, final String suffix) { - SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0)); - if (op != null) { - if (op == SearchOperation.EQUALITY) // the operation may be complex operation - { - final boolean startWithAsterisk = prefix.contains("*"); - final boolean endWithAsterisk = suffix.contains("*"); - - if (startWithAsterisk && endWithAsterisk) { - op = SearchOperation.CONTAINS; - } else if (startWithAsterisk) { - op = SearchOperation.ENDS_WITH; - } else if (endWithAsterisk) { - op = SearchOperation.STARTS_WITH; - } - } - params.add(new SpecSearchCriteria(key, op, value)); - } - return this; - } - - public Specification build() { - if (params.size() == 0) { - return null; - } - - final List> specs = new ArrayList>(); - for (final SpecSearchCriteria param : params) { - specs.add(new UserSpecification(param)); - } - - Specification result = specs.get(0); - for (int i = 1; i < specs.size(); i++) { - result = Specifications.where(result).and(specs.get(i)); - } - return result; - } - -} +package org.baeldung.persistence.dao; + +import org.baeldung.persistence.model.User; +import org.baeldung.web.util.SearchOperation; +import org.baeldung.web.util.SpecSearchCriteria; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.domain.Specifications; + +import java.util.ArrayList; +import java.util.List; + +public final class UserSpecificationsBuilder { + + private final List params; + + public UserSpecificationsBuilder() { + params = new ArrayList(); + } + + // API + + public final UserSpecificationsBuilder with(final String key, final String operation, final Object value, final String prefix, final String suffix) { + return with(null, key, operation, value, prefix, suffix); + } + + public final UserSpecificationsBuilder with(final String precedenceIndicator, final String key, final String operation, final Object value, final String prefix, final String suffix) { + SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0)); + if (op != null) { + if (op == SearchOperation.EQUALITY) { // the operation may be complex operation + final boolean startWithAsterisk = prefix != null && prefix.contains(SearchOperation.ZERO_OR_MORE_REGEX); + final boolean endWithAsterisk = suffix != null && suffix.contains(SearchOperation.ZERO_OR_MORE_REGEX); + + if (startWithAsterisk && endWithAsterisk) { + op = SearchOperation.CONTAINS; + } else if (startWithAsterisk) { + op = SearchOperation.ENDS_WITH; + } else if (endWithAsterisk) { + op = SearchOperation.STARTS_WITH; + } + } + params.add(new SpecSearchCriteria(precedenceIndicator, key, op, value)); + } + return this; + } + + public Specification build() { + + if (params.size() == 0) + return null; + + params.sort((spec0, spec1) -> { + return Boolean.compare(spec0.isLowPrecedence(), spec1.isLowPrecedence()); + }); + + Specification result = new UserSpecification(params.get(0)); + + for (int i = 1; i < params.size(); i++) { + result = params.get(i).isLowPrecedence() ? Specifications.where(result).or(new UserSpecification(params.get(i))) : Specifications.where(result).and(new UserSpecification(params.get(i))); + + } + + return result; + } + + public final UserSpecificationsBuilder with(UserSpecification spec) { + params.add(spec.getCriteria()); + return this; + } + + public final UserSpecificationsBuilder with(SpecSearchCriteria criteria) { + params.add(criteria); + return this; + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java index d20423ddc0..fff089a62b 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/controller/UserController.java @@ -1,15 +1,12 @@ package org.baeldung.web.controller; -import java.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.baeldung.persistence.dao.IUserDAO; -import org.baeldung.persistence.dao.MyUserPredicatesBuilder; -import org.baeldung.persistence.dao.MyUserRepository; -import org.baeldung.persistence.dao.UserRepository; -import org.baeldung.persistence.dao.UserSpecificationsBuilder; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import com.querydsl.core.types.Predicate; +import com.querydsl.core.types.dsl.BooleanExpression; +import cz.jirutka.rsql.parser.RSQLParser; +import cz.jirutka.rsql.parser.ast.Node; +import org.baeldung.persistence.dao.*; import org.baeldung.persistence.dao.rsql.CustomRsqlVisitor; import org.baeldung.persistence.model.MyUser; import org.baeldung.persistence.model.User; @@ -20,20 +17,12 @@ import org.springframework.data.jpa.domain.Specification; import org.springframework.data.querydsl.binding.QuerydslPredicate; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.ResponseBody; -import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.*; -import com.google.common.base.Joiner; -import com.google.common.base.Preconditions; -import com.querydsl.core.types.Predicate; -import com.querydsl.core.types.dsl.BooleanExpression; - -import cz.jirutka.rsql.parser.RSQLParser; -import cz.jirutka.rsql.parser.ast.Node; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; //@EnableSpringDataWebSupport @Controller @@ -84,6 +73,25 @@ public class UserController { return dao.findAll(spec); } + @RequestMapping(method = RequestMethod.GET, value = "/users/espec") + @ResponseBody + public List findAllByOptionalSpecification(@RequestParam(value = "search") final String search) { + final Specification spec = resolveSpecification(search); + return dao.findAll(spec); + } + + protected Specification resolveSpecification(String searchParameters) { + + final UserSpecificationsBuilder builder = new UserSpecificationsBuilder(); + final String operationSetExper = Joiner.on("|").join(SearchOperation.SIMPLE_OPERATION_SET); + final Pattern pattern = Pattern.compile("(\\p{Punct}?)(\\w+?)(" + operationSetExper + ")(\\p{Punct}?)(\\w+?)(\\p{Punct}?),"); + final Matcher matcher = pattern.matcher(searchParameters + ","); + while (matcher.find()) { + builder.with(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(5), matcher.group(4), matcher.group(6)); + } + return builder.build(); + } + @RequestMapping(method = RequestMethod.GET, value = "/myusers") @ResponseBody public Iterable findAllByQuerydsl(@RequestParam(value = "search") final String search) { diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/util/SearchOperation.java b/spring-security-rest-full/src/main/java/org/baeldung/web/util/SearchOperation.java index 703f9b93f6..41a556c18a 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/util/SearchOperation.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/util/SearchOperation.java @@ -1,24 +1,28 @@ -package org.baeldung.web.util; - -public enum SearchOperation { - EQUALITY, NEGATION, GREATER_THAN, LESS_THAN, LIKE, STARTS_WITH, ENDS_WITH, CONTAINS; - - public static final String[] SIMPLE_OPERATION_SET = { ":", "!", ">", "<", "~" }; - - public static SearchOperation getSimpleOperation(final char input) { - switch (input) { - case ':': - return EQUALITY; - case '!': - return NEGATION; - case '>': - return GREATER_THAN; - case '<': - return LESS_THAN; - case '~': - return LIKE; - default: - return null; - } - } -} +package org.baeldung.web.util; + +public enum SearchOperation { + EQUALITY, NEGATION, GREATER_THAN, LESS_THAN, LIKE, STARTS_WITH, ENDS_WITH, CONTAINS; + + public static final String[] SIMPLE_OPERATION_SET = { ":", "!", ">", "<", "~" }; + + public static final String LOW_PRECEDENCE_INDICATOR="'"; + + public static final String ZERO_OR_MORE_REGEX="*"; + + public static SearchOperation getSimpleOperation(final char input) { + switch (input) { + case ':': + return EQUALITY; + case '!': + return NEGATION; + case '>': + return GREATER_THAN; + case '<': + return LESS_THAN; + case '~': + return LIKE; + default: + return null; + } + } +} diff --git a/spring-security-rest-full/src/main/java/org/baeldung/web/util/SpecSearchCriteria.java b/spring-security-rest-full/src/main/java/org/baeldung/web/util/SpecSearchCriteria.java index 4a04d395fa..7dbb66edea 100644 --- a/spring-security-rest-full/src/main/java/org/baeldung/web/util/SpecSearchCriteria.java +++ b/spring-security-rest-full/src/main/java/org/baeldung/web/util/SpecSearchCriteria.java @@ -1,44 +1,61 @@ -package org.baeldung.web.util; - -public class SpecSearchCriteria { - - private String key; - private SearchOperation operation; - private Object value; - - public SpecSearchCriteria() { - - } - - public SpecSearchCriteria(final String key, final SearchOperation operation, final Object value) { - super(); - this.key = key; - this.operation = operation; - this.value = value; - } - - public String getKey() { - return key; - } - - public void setKey(final String key) { - this.key = key; - } - - public SearchOperation getOperation() { - return operation; - } - - public void setOperation(final SearchOperation operation) { - this.operation = operation; - } - - public Object getValue() { - return value; - } - - public void setValue(final Object value) { - this.value = value; - } - -} +package org.baeldung.web.util; + +public class SpecSearchCriteria { + + private String key; + private SearchOperation operation; + private Object value; + private boolean lowPrecedence; + + public SpecSearchCriteria() { + + } + + public SpecSearchCriteria(final String key, final SearchOperation operation, final Object value) { + super(); + this.key = key; + this.operation = operation; + this.value = value; + } + + public SpecSearchCriteria(final String lowPrecedenceIndicator, final String key, final SearchOperation operation, final Object value) { + super(); + this.lowPrecedence = lowPrecedenceIndicator != null && lowPrecedenceIndicator.equals(SearchOperation.LOW_PRECEDENCE_INDICATOR); + this.key = key; + this.operation = operation; + this.value = value; + } + + public String getKey() { + return key; + } + + public void setKey(final String key) { + this.key = key; + } + + public SearchOperation getOperation() { + return operation; + } + + public void setOperation(final SearchOperation operation) { + this.operation = operation; + } + + public Object getValue() { + return value; + } + + public void setValue(final Object value) { + this.value = value; + } + + public boolean isLowPrecedence() { + return lowPrecedence; + } + + public void setLowPrecedence(boolean lowPrecedence) { + this.lowPrecedence = lowPrecedence; + } + +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationIntegrationTest.java b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationIntegrationTest.java index 8bd4857e85..e5c408bfdb 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationIntegrationTest.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationIntegrationTest.java @@ -1,119 +1,160 @@ -package org.baeldung.persistence.query; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.collection.IsIn.isIn; -import static org.hamcrest.core.IsNot.not; - -import java.util.List; - -import org.baeldung.persistence.dao.UserRepository; -import org.baeldung.persistence.dao.UserSpecification; -import org.baeldung.persistence.model.User; -import org.baeldung.spring.PersistenceConfig; -import org.baeldung.web.util.SearchOperation; -import org.baeldung.web.util.SpecSearchCriteria; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.jpa.domain.Specifications; -import org.springframework.test.annotation.Rollback; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.transaction.annotation.Transactional; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = { PersistenceConfig.class }) -@Transactional -@Rollback -public class JPASpecificationIntegrationTest { - - @Autowired - private UserRepository repository; - - private User userJohn; - - private User userTom; - - @Before - public void init() { - userJohn = new User(); - userJohn.setFirstName("john"); - userJohn.setLastName("doe"); - userJohn.setEmail("john@doe.com"); - userJohn.setAge(22); - repository.save(userJohn); - - userTom = new User(); - userTom.setFirstName("tom"); - userTom.setLastName("doe"); - userTom.setEmail("tom@doe.com"); - userTom.setAge(26); - repository.save(userTom); - } - - @Test - public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.EQUALITY, "john")); - final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("lastName", SearchOperation.EQUALITY, "doe")); - final List results = repository.findAll(Specifications.where(spec).and(spec1)); - - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } - - @Test - public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.NEGATION, "john")); - final List results = repository.findAll(Specifications.where(spec)); - - assertThat(userTom, isIn(results)); - assertThat(userJohn, not(isIn(results))); - } - - @Test - public void givenMinAge_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "25")); - final List results = repository.findAll(Specifications.where(spec)); - - assertThat(userTom, isIn(results)); - assertThat(userJohn, not(isIn(results))); - } - - @Test - public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.STARTS_WITH, "jo")); - final List results = repository.findAll(spec); - - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } - - @Test - public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.ENDS_WITH, "n")); - final List results = repository.findAll(spec); - - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } - - @Test - public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.CONTAINS, "oh")); - final List results = repository.findAll(spec); - - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } - - @Test - public void givenAgeRange_whenGettingListOfUsers_thenCorrect() { - final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "20")); - final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.LESS_THAN, "25")); - final List results = repository.findAll(Specifications.where(spec).and(spec1)); - - assertThat(userJohn, isIn(results)); - assertThat(userTom, not(isIn(results))); - } -} +package org.baeldung.persistence.query; + +import org.baeldung.persistence.dao.GenericSpecificationsBuilder; +import org.baeldung.persistence.dao.UserRepository; +import org.baeldung.persistence.dao.UserSpecification; +import org.baeldung.persistence.dao.UserSpecificationsBuilder; +import org.baeldung.persistence.model.User; +import org.baeldung.spring.PersistenceConfig; +import org.baeldung.web.util.SearchOperation; +import org.baeldung.web.util.SpecSearchCriteria; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.data.jpa.domain.Specifications; +import org.springframework.test.annotation.Rollback; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.function.Function; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.collection.IsCollectionWithSize.hasSize; +import static org.hamcrest.collection.IsIn.isIn; +import static org.hamcrest.core.IsNot.not; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { PersistenceConfig.class }) +@Transactional +@Rollback +public class JPASpecificationIntegrationTest { + + @Autowired + private UserRepository repository; + + private User userJohn; + + private User userTom; + + private User userPercy; + + @Before + public void init() { + userJohn = new User(); + userJohn.setFirstName("john"); + userJohn.setLastName("doe"); + userJohn.setEmail("john@doe.com"); + userJohn.setAge(22); + repository.save(userJohn); + + userTom = new User(); + userTom.setFirstName("tom"); + userTom.setLastName("doe"); + userTom.setEmail("tom@doe.com"); + userTom.setAge(26); + repository.save(userTom); + + userPercy = new User(); + userPercy.setFirstName("percy"); + userPercy.setLastName("blackney"); + userPercy.setEmail("percy@blackney.com"); + userPercy.setAge(30); + repository.save(userPercy); + } + + @Test + public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.EQUALITY, "john")); + final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("lastName", SearchOperation.EQUALITY, "doe")); + final List results = repository.findAll(Specifications.where(spec).and(spec1)); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenFirstOrLastName_whenGettingListOfUsers_thenCorrect() { + UserSpecificationsBuilder builder = new UserSpecificationsBuilder(); + + final SpecSearchCriteria spec = new SpecSearchCriteria("'", "firstName", SearchOperation.EQUALITY, "john"); + final SpecSearchCriteria spec1 = new SpecSearchCriteria("lastName", SearchOperation.EQUALITY, "doe"); + + final List results = repository.findAll(builder.with(spec1).with(spec).build()); + + assertThat(results, hasSize(2)); + assertThat(userJohn, isIn(results)); + assertThat(userTom, isIn(results)); + } + + @Test + public void givenFirstOrLastNameGenericBuilder_whenGettingListOfUsers_thenCorrect() { + GenericSpecificationsBuilder builder = new GenericSpecificationsBuilder(); + Function> converter = UserSpecification::new; + builder.with("'", "firstName", ":", "john", null, null); + builder.with(null, "lastName", ":", "doe", null, null); + + final List results = repository.findAll(builder.build(converter)); + assertThat(results, hasSize(2)); + assertThat(userJohn, isIn(results)); + assertThat(userTom, isIn(results)); + } + + @Test + public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.NEGATION, "john")); + final List results = repository.findAll(Specifications.where(spec)); + + assertThat(userTom, isIn(results)); + assertThat(userJohn, not(isIn(results))); + } + + @Test + public void givenMinAge_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "25")); + final List results = repository.findAll(Specifications.where(spec)); + + assertThat(userTom, isIn(results)); + assertThat(userJohn, not(isIn(results))); + } + + @Test + public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.STARTS_WITH, "jo")); + final List results = repository.findAll(spec); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.ENDS_WITH, "n")); + final List results = repository.findAll(spec); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.CONTAINS, "oh")); + final List results = repository.findAll(spec); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } + + @Test + public void givenAgeRange_whenGettingListOfUsers_thenCorrect() { + final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "20")); + final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.LESS_THAN, "25")); + final List results = repository.findAll(Specifications.where(spec).and(spec1)); + + assertThat(userJohn, isIn(results)); + assertThat(userTom, not(isIn(results))); + } +} diff --git a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationLiveTest.java b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationLiveTest.java index 3b85cfb487..55fde80add 100644 --- a/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationLiveTest.java +++ b/spring-security-rest-full/src/test/java/org/baeldung/persistence/query/JPASpecificationLiveTest.java @@ -1,112 +1,122 @@ -package org.baeldung.persistence.query; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import org.baeldung.persistence.model.User; -import org.junit.Before; -import org.junit.Test; -import org.springframework.test.context.ActiveProfiles; - -import com.jayway.restassured.RestAssured; -import com.jayway.restassured.response.Response; -import com.jayway.restassured.specification.RequestSpecification; - -//@RunWith(SpringJUnit4ClassRunner.class) -//@ContextConfiguration(classes = { ConfigTest.class, PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) -@ActiveProfiles("test") -public class JPASpecificationLiveTest { - - // @Autowired - // private UserRepository repository; - - private User userJohn; - - private User userTom; - - private final String URL_PREFIX = "http://localhost:8082/spring-security-rest-full/auth/users/spec?search="; - - @Before - public void init() { - userJohn = new User(); - userJohn.setFirstName("john"); - userJohn.setLastName("doe"); - userJohn.setEmail("john@doe.com"); - userJohn.setAge(22); - // repository.save(userJohn); - - userTom = new User(); - userTom.setFirstName("tom"); - userTom.setLastName("doe"); - userTom.setEmail("tom@doe.com"); - userTom.setAge(26); - // repository.save(userTom); - } - - @Test - public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { - final Response response = givenAuth().get(URL_PREFIX + "firstName:john,lastName:doe"); - final String result = response.body().asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - @Test - public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() { - final Response response = givenAuth().get(URL_PREFIX + "firstName!john"); - final String result = response.body().asString(); - - assertTrue(result.contains(userTom.getEmail())); - assertFalse(result.contains(userJohn.getEmail())); - } - - @Test - public void givenMinAge_whenGettingListOfUsers_thenCorrect() { - final Response response = givenAuth().get(URL_PREFIX + "age>25"); - final String result = response.body().asString(); - - assertTrue(result.contains(userTom.getEmail())); - assertFalse(result.contains(userJohn.getEmail())); - } - - @Test - public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() { - final Response response = givenAuth().get(URL_PREFIX + "firstName:jo*"); - final String result = response.body().asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - @Test - public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() { - final Response response = givenAuth().get(URL_PREFIX + "firstName:*n"); - final String result = response.body().asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - @Test - public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() { - final Response response = givenAuth().get(URL_PREFIX + "firstName:*oh*"); - final String result = response.body().asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - @Test - public void givenAgeRange_whenGettingListOfUsers_thenCorrect() { - final Response response = givenAuth().get(URL_PREFIX + "age>20,age<25"); - final String result = response.body().asString(); - - assertTrue(result.contains(userJohn.getEmail())); - assertFalse(result.contains(userTom.getEmail())); - } - - private final RequestSpecification givenAuth() { - return RestAssured.given().auth().preemptive().basic("user1", "user1Pass"); - } -} +package org.baeldung.persistence.query; + +import com.jayway.restassured.RestAssured; +import com.jayway.restassured.response.Response; +import com.jayway.restassured.specification.RequestSpecification; +import org.baeldung.persistence.model.User; +import org.junit.Before; +import org.junit.Test; +import org.springframework.test.context.ActiveProfiles; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +//@RunWith(SpringJUnit4ClassRunner.class) +//@ContextConfiguration(classes = { ConfigTest.class, +// PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class) +@ActiveProfiles("test") +public class JPASpecificationLiveTest { + + // @Autowired + // private UserRepository repository; + + private User userJohn; + + private User userTom; + + private final String URL_PREFIX = "http://localhost:8082/spring-security-rest-full/auth/users/spec?search="; + + @Before + public void init() { + userJohn = new User(); + userJohn.setFirstName("john"); + userJohn.setLastName("doe"); + userJohn.setEmail("john@doe.com"); + userJohn.setAge(22); + // repository.save(userJohn); + + userTom = new User(); + userTom.setFirstName("tom"); + userTom.setLastName("doe"); + userTom.setEmail("tom@doe.com"); + userTom.setAge(26); + // repository.save(userTom); + } + + private final String EURL_PREFIX = "http://localhost:8082/spring-security-rest-full/auth/users/espec?search="; + + @Test + public void givenFirstOrLastName_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(EURL_PREFIX + "'firstName:john,lastName:doe"); + final String result = response.body().asString(); + assertTrue(result.contains(userJohn.getEmail())); + assertTrue(result.contains(userTom.getEmail())); + } + + @Test + public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(URL_PREFIX + "firstName:john,lastName:doe"); + final String result = response.body().asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + @Test + public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(URL_PREFIX + "firstName!john"); + final String result = response.body().asString(); + + assertTrue(result.contains(userTom.getEmail())); + assertFalse(result.contains(userJohn.getEmail())); + } + + @Test + public void givenMinAge_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(URL_PREFIX + "age>25"); + final String result = response.body().asString(); + + assertTrue(result.contains(userTom.getEmail())); + assertFalse(result.contains(userJohn.getEmail())); + } + + @Test + public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(URL_PREFIX + "firstName:jo*"); + final String result = response.body().asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + @Test + public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(URL_PREFIX + "firstName:*n"); + final String result = response.body().asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + @Test + public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(URL_PREFIX + "firstName:*oh*"); + final String result = response.body().asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + @Test + public void givenAgeRange_whenGettingListOfUsers_thenCorrect() { + final Response response = givenAuth().get(URL_PREFIX + "age>20,age<25"); + final String result = response.body().asString(); + + assertTrue(result.contains(userJohn.getEmail())); + assertFalse(result.contains(userTom.getEmail())); + } + + private final RequestSpecification givenAuth() { + return RestAssured.given().auth().preemptive().basic("user1", "user1Pass"); + } +} diff --git a/spring-security-stormpath/README.md b/spring-security-stormpath/README.md new file mode 100644 index 0000000000..f83882112f --- /dev/null +++ b/spring-security-stormpath/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [Spring Security with Stormpath](http://www.baeldung.com/spring-security-stormpath) diff --git a/struts2/README.md b/struts2/README.md new file mode 100644 index 0000000000..8a1425ccb5 --- /dev/null +++ b/struts2/README.md @@ -0,0 +1,3 @@ +### Relevant articles + +- [A Quick Struts 2 Intro](http://www.baeldung.com/struts-2-intro) diff --git a/struts2/pom.xml b/struts2/pom.xml index 25a374549d..ca5a682f9d 100644 --- a/struts2/pom.xml +++ b/struts2/pom.xml @@ -2,10 +2,11 @@ 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 - MyStrutsApp + struts 0.0.1-SNAPSHOT pom struts + src/main/java @@ -13,6 +14,7 @@ src/main/resources + maven-compiler-plugin diff --git a/xml/pom.xml b/xml/pom.xml index 4230350ed9..38bf6bf42e 100644 --- a/xml/pom.xml +++ b/xml/pom.xml @@ -7,6 +7,32 @@ xml + + + jibx.sf.net + JiBX repository + http://jibx.sf.net/maven2 + + never + + + false + + + + + + jibx.sf.net + JiBX repository + http://jibx.sf.net/maven2 + + never + + + false + + + @@ -46,6 +72,17 @@ ${commons-lang3.version} + + org.jibx + jibx-run + ${jibx-version} + + + commons-lang + commons-lang + ${commons-lang.version} + + @@ -74,8 +111,8 @@ maven-compiler-plugin ${maven-compiler-plugin.version} - 1.8 - 1.8 + ${java-version} + ${java-version} @@ -83,21 +120,206 @@ org.apache.maven.plugins maven-surefire-plugin ${maven-surefire-plugin.version} + + + CustomerTest.java + + + + + schemaGen + + + + org.jibx + maven-jibx-plugin + ${maven-jibx-plugin.version} + + + generate-java-code-from-schema + + schema-codegen + + + src/main/resources + + Order.xsd + + true + + + + compile-binding + + bind + + + target/generated-sources + true + true + + true + + + + generate-test-code-from-schema + generate-test-sources + + test-schema-codegen + + + + compile-test-binding + process-test-classes + + test-bind + + + target/generated-test-sources + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java-version} + ${java-version} + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + + CustomerTest.java + + + + + + + + + + bindGen + + + + + org.jibx + maven-jibx-plugin + + + + + + org.jibx + maven-jibx-plugin + ${maven-jibx-plugin.version} + + src/main/resources + + *-binding.xml + + + template-binding.xml + + true + + + + process-classes + + bind + + + + + + org.jibx + maven-jibx-plugin + 1.3.1 + + src/main/resources + + *-binding.xml + + true + + + + process-test-classes + + test-bind + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java-version} + ${java-version} + + + + + maven-assembly-plugin + + + + jar-with-dependencies + + + + + + com.baeldung.xml.jibx.JiBXDemoApplication + + + + + + + make-assembly + package + + attached + + + + + + + + + + - 1.6.1 - 1.1.6 - 2.0.6 + 1.6.1 + 1.1.6 + 2.0.6 2.5 4.1 + 1.2.4.5 3.5 + 2.4 + 1.8 4.12 @@ -105,6 +327,7 @@ 3.6.0 2.19.1 + 1.3.1 diff --git a/xml/src/main/java/com/baeldung/xml/jibx/Customer.java b/xml/src/main/java/com/baeldung/xml/jibx/Customer.java new file mode 100644 index 0000000000..fabd464663 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xml/jibx/Customer.java @@ -0,0 +1,53 @@ +/* + * Customer.java 06.06.2008 + * + * Copyright 2008 Stefan Jäger + * + */ +package com.baeldung.xml.jibx; + +import org.apache.commons.lang.builder.ToStringBuilder; + +public class Customer { + private Person person; + private String city; + + private Phone homePhone; + private Phone officePhone; + + public Person getPerson() { + return person; + } + + public void setPerson(Person person) { + this.person = person; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public Phone getHomePhone() { + return homePhone; + } + + public void setHomePhone(Phone homePhone) { + this.homePhone = homePhone; + } + + public Phone getOfficePhone() { + return officePhone; + } + + public void setOfficePhone(Phone officePhone) { + this.officePhone = officePhone; + } + + public String toString() { + return ToStringBuilder.reflectionToString(this); + } +} diff --git a/xml/src/main/java/com/baeldung/xml/jibx/Identity.java b/xml/src/main/java/com/baeldung/xml/jibx/Identity.java new file mode 100644 index 0000000000..15aab4e417 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xml/jibx/Identity.java @@ -0,0 +1,14 @@ +package com.baeldung.xml.jibx; + +public class Identity { + + long customerId; + + public long getCustomerId() { + return customerId; + } + + public void setCustomerId(long customerId) { + this.customerId = customerId; + } +} diff --git a/xml/src/main/java/com/baeldung/xml/jibx/Person.java b/xml/src/main/java/com/baeldung/xml/jibx/Person.java new file mode 100644 index 0000000000..fbd7cde0a2 --- /dev/null +++ b/xml/src/main/java/com/baeldung/xml/jibx/Person.java @@ -0,0 +1,25 @@ +/* + * Person.java 06.06.2008 + * + * Copyright 2008 Stefan Jäger + * + */ +package com.baeldung.xml.jibx; + +import org.apache.commons.lang.builder.ToStringBuilder; + +public class Person extends Identity { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String toString() { + return ToStringBuilder.reflectionToString(this); + } +} diff --git a/xml/src/main/java/com/baeldung/xml/jibx/Phone.java b/xml/src/main/java/com/baeldung/xml/jibx/Phone.java new file mode 100644 index 0000000000..783f2ee6fb --- /dev/null +++ b/xml/src/main/java/com/baeldung/xml/jibx/Phone.java @@ -0,0 +1,14 @@ +package com.baeldung.xml.jibx; + +public class Phone { + + private String number; + + public String getNumber() { + return number; + } + + public void setNumber(String number) { + this.number = number; + } +} diff --git a/xml/src/main/resources/Order.xsd b/xml/src/main/resources/Order.xsd new file mode 100644 index 0000000000..cbb5bc7596 --- /dev/null +++ b/xml/src/main/resources/Order.xsd @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xml/src/main/resources/customer-binding.xml b/xml/src/main/resources/customer-binding.xml new file mode 100644 index 0000000000..c1a80366ef --- /dev/null +++ b/xml/src/main/resources/customer-binding.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xml/src/test/java/com/baeldung/xml/jibx/CustomerTest.java b/xml/src/test/java/com/baeldung/xml/jibx/CustomerTest.java new file mode 100644 index 0000000000..8b14277799 --- /dev/null +++ b/xml/src/test/java/com/baeldung/xml/jibx/CustomerTest.java @@ -0,0 +1,52 @@ +package com.baeldung.xml.jibx; + +import org.jibx.runtime.BindingDirectory; +import org.jibx.runtime.IBindingFactory; +import org.jibx.runtime.IUnmarshallingContext; +import org.jibx.runtime.JiBXException; +import org.junit.Test; + +import java.io.FileNotFoundException; +import java.io.InputStream; + +import static junit.framework.Assert.assertEquals; + +public class CustomerTest { + + @Test + public void whenUnmarshalXML_ThenFieldsAreMapped() throws JiBXException, FileNotFoundException { + IBindingFactory bfact = BindingDirectory.getFactory(Customer.class); + IUnmarshallingContext uctx = bfact.createUnmarshallingContext(); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream("Customer1.xml"); + Customer customer = (Customer) uctx.unmarshalDocument(inputStream, null); + + assertEquals("Stefan Jaegar", customer.getPerson().getName()); + assertEquals("Davos Dorf", customer.getCity()); + + } + + @Test + public void WhenUnmarshal_ThenMappingInherited() throws JiBXException, FileNotFoundException { + IBindingFactory bfact = BindingDirectory.getFactory(Customer.class); + IUnmarshallingContext uctx = bfact.createUnmarshallingContext(); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream("Customer1.xml"); + Customer customer = (Customer) uctx.unmarshalDocument(inputStream, null); + + assertEquals(12345, customer.getPerson().getCustomerId()); + + } + + @Test + public void WhenUnmarshal_ThenPhoneMappingRead() throws JiBXException, FileNotFoundException { + IBindingFactory bfact = BindingDirectory.getFactory(Customer.class); + IUnmarshallingContext uctx = bfact.createUnmarshallingContext(); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + InputStream inputStream = classLoader.getResourceAsStream("Customer1.xml"); + Customer customer = (Customer) uctx.unmarshalDocument(inputStream, null); + + assertEquals("234678", customer.getHomePhone().getNumber()); + + } +} diff --git a/xml/src/test/resources/Customer1.xml b/xml/src/test/resources/Customer1.xml new file mode 100644 index 0000000000..7f4fbc79af --- /dev/null +++ b/xml/src/test/resources/Customer1.xml @@ -0,0 +1,16 @@ + + + + 12345 + Stefan Jaeger + + + 234678 + + + + 234678 + + Davos Dorf + + \ No newline at end of file