Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
6d63084fc1
|
@ -0,0 +1,4 @@
|
|||
## Apache Solrj Tutorials Project
|
||||
|
||||
### Relevant Articles
|
||||
- [Guide to Solr in Java with Apache Solrj](http://www.baeldung.com/apache-solrj)
|
|
@ -0,0 +1,44 @@
|
|||
package com.baeldung.solrjava;
|
||||
|
||||
import org.apache.solr.client.solrj.beans.Field;
|
||||
|
||||
public class ProductBean {
|
||||
|
||||
String id;
|
||||
String name;
|
||||
String price;
|
||||
|
||||
public ProductBean(String id, String name, String price) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Field("id")
|
||||
protected void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Field("name")
|
||||
protected void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
@Field("price")
|
||||
protected void setPrice(String price) {
|
||||
this.price = price;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,12 @@ public class SolrJavaIntegration {
|
|||
solrClient.setParser(new XMLResponseParser());
|
||||
}
|
||||
|
||||
public void addProductBean(ProductBean pBean) throws IOException, SolrServerException {
|
||||
|
||||
solrClient.addBean(pBean);
|
||||
solrClient.commit();
|
||||
}
|
||||
|
||||
public void addSolrDocument(String documentId, String itemName, String itemPrice) throws SolrServerException, IOException {
|
||||
|
||||
SolrInputDocument document = new SolrInputDocument();
|
||||
|
@ -27,12 +33,18 @@ public class SolrJavaIntegration {
|
|||
solrClient.commit();
|
||||
}
|
||||
|
||||
public void deleteSolrDocument(String documentId) throws SolrServerException, IOException {
|
||||
public void deleteSolrDocumentById(String documentId) throws SolrServerException, IOException {
|
||||
|
||||
solrClient.deleteById(documentId);
|
||||
solrClient.commit();
|
||||
}
|
||||
|
||||
public void deleteSolrDocumentByQuery(String query) throws SolrServerException, IOException {
|
||||
|
||||
solrClient.deleteByQuery(query);
|
||||
solrClient.commit();
|
||||
}
|
||||
|
||||
protected HttpSolrClient getSolrClient() {
|
||||
return solrClient;
|
||||
}
|
||||
|
@ -40,4 +52,5 @@ public class SolrJavaIntegration {
|
|||
protected void setSolrClient(HttpSolrClient solrClient) {
|
||||
this.solrClient = solrClient;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ public class SolrJavaIntegrationTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void whenAdd_thenVerifyAdded() throws SolrServerException, IOException {
|
||||
public void whenAdd_thenVerifyAddedByQueryOnId() throws SolrServerException, IOException {
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.set("q", "id:123456");
|
||||
|
@ -33,18 +33,68 @@ public class SolrJavaIntegrationTest {
|
|||
response = solrJavaIntegration.getSolrClient().query(query);
|
||||
|
||||
SolrDocumentList docList = response.getResults();
|
||||
assertEquals(docList.getNumFound(), 1);
|
||||
assertEquals(1, docList.getNumFound());
|
||||
|
||||
for (SolrDocument doc : docList) {
|
||||
assertEquals((String) doc.getFieldValue("id"), "123456");
|
||||
assertEquals((Double) doc.getFieldValue("price"), (Double) 599.99);
|
||||
assertEquals("Kenmore Dishwasher", (String) doc.getFieldValue("name"));
|
||||
assertEquals((Double) 599.99, (Double) doc.getFieldValue("price"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDelete_thenVerifyDeleted() throws SolrServerException, IOException {
|
||||
public void whenAdd_thenVerifyAddedByQueryOnPrice() throws SolrServerException, IOException {
|
||||
|
||||
solrJavaIntegration.deleteSolrDocument("123456");
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.set("q", "price:599.99");
|
||||
QueryResponse response = null;
|
||||
|
||||
response = solrJavaIntegration.getSolrClient().query(query);
|
||||
|
||||
SolrDocumentList docList = response.getResults();
|
||||
assertEquals(1, docList.getNumFound());
|
||||
|
||||
for (SolrDocument doc : docList) {
|
||||
assertEquals("123456", (String) doc.getFieldValue("id"));
|
||||
assertEquals((Double) 599.99, (Double) doc.getFieldValue("price"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAdd_thenVerifyAddedByQuery() throws SolrServerException, IOException {
|
||||
|
||||
SolrDocument doc = solrJavaIntegration.getSolrClient().getById("123456");
|
||||
assertEquals("Kenmore Dishwasher", (String) doc.getFieldValue("name"));
|
||||
assertEquals((Double) 599.99, (Double) doc.getFieldValue("price"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenAddBean_thenVerifyAddedByQuery() throws SolrServerException, IOException {
|
||||
|
||||
ProductBean pBean = new ProductBean("888", "Apple iPhone 6s", "299.99");
|
||||
solrJavaIntegration.addProductBean(pBean);
|
||||
|
||||
SolrDocument doc = solrJavaIntegration.getSolrClient().getById("888");
|
||||
assertEquals("Apple iPhone 6s", (String) doc.getFieldValue("name"));
|
||||
assertEquals((Double) 299.99, (Double) doc.getFieldValue("price"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDeleteById_thenVerifyDeleted() throws SolrServerException, IOException {
|
||||
|
||||
solrJavaIntegration.deleteSolrDocumentById("123456");
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.set("q", "id:123456");
|
||||
QueryResponse response = solrJavaIntegration.getSolrClient().query(query);
|
||||
|
||||
SolrDocumentList docList = response.getResults();
|
||||
assertEquals(0, docList.getNumFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDeleteByQuery_thenVerifyDeleted() throws SolrServerException, IOException {
|
||||
|
||||
solrJavaIntegration.deleteSolrDocumentByQuery("name:Kenmore Dishwasher");
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.set("q", "id:123456");
|
||||
|
@ -53,6 +103,6 @@ public class SolrJavaIntegrationTest {
|
|||
response = solrJavaIntegration.getSolrClient().query(query);
|
||||
|
||||
SolrDocumentList docList = response.getResults();
|
||||
assertEquals(docList.getNumFound(), 0);
|
||||
assertEquals(0, docList.getNumFound());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,8 @@ package com.baeldung.algorithms;
|
|||
|
||||
import java.util.Scanner;
|
||||
|
||||
import com.baeldung.algorithms.annealing.SimulatedAnnealing;
|
||||
import com.baeldung.algorithms.ga.annealing.SimulatedAnnealing;
|
||||
import com.baeldung.algorithms.ga.ant_colony.AntColonyOptimization;
|
||||
import com.baeldung.algorithms.ga.binary.SimpleGeneticAlgorithm;
|
||||
import com.baeldung.algorithms.slope_one.SlopeOne;
|
||||
|
||||
|
@ -14,6 +15,7 @@ public class RunAlgorithm {
|
|||
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");
|
||||
int decision = in.nextInt();
|
||||
switch (decision) {
|
||||
case 1:
|
||||
|
@ -27,6 +29,10 @@ public class RunAlgorithm {
|
|||
SimpleGeneticAlgorithm ga = new SimpleGeneticAlgorithm();
|
||||
ga.runAlgorithm(50, "1011000100000100010000100000100111001000000100000100000000001111");
|
||||
break;
|
||||
case 4:
|
||||
AntColonyOptimization antColony = new AntColonyOptimization(21);
|
||||
antColony.startAntOptimization();
|
||||
break;
|
||||
default:
|
||||
System.out.println("Unknown option");
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.algorithms.annealing;
|
||||
package com.baeldung.algorithms.ga.annealing;
|
||||
|
||||
import lombok.Data;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.algorithms.annealing;
|
||||
package com.baeldung.algorithms.ga.annealing;
|
||||
|
||||
public class SimulatedAnnealing {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.algorithms.annealing;
|
||||
package com.baeldung.algorithms.ga.annealing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
|
@ -0,0 +1,37 @@
|
|||
package com.baeldung.algorithms.ga.ant_colony;
|
||||
|
||||
public class Ant {
|
||||
|
||||
protected int trailSize;
|
||||
protected int trail[];
|
||||
protected boolean visited[];
|
||||
|
||||
public Ant(int tourSize) {
|
||||
this.trailSize = tourSize;
|
||||
this.trail = new int[tourSize];
|
||||
this.visited = new boolean[tourSize];
|
||||
}
|
||||
|
||||
protected void visitCity(int currentIndex, int city) {
|
||||
trail[currentIndex + 1] = city;
|
||||
visited[city] = true;
|
||||
}
|
||||
|
||||
protected boolean visited(int i) {
|
||||
return visited[i];
|
||||
}
|
||||
|
||||
protected double trailLength(double graph[][]) {
|
||||
double length = graph[trail[trailSize - 1]][trail[0]];
|
||||
for (int i = 0; i < trailSize - 1; i++) {
|
||||
length += graph[trail[i]][trail[i + 1]];
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
protected void clear() {
|
||||
for (int i = 0; i < trailSize; i++)
|
||||
visited[i] = false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
package com.baeldung.algorithms.ga.ant_colony;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
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 Ant ants[];
|
||||
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];
|
||||
ants = new Ant[numberOfAnts];
|
||||
for (int j = 0; j < numberOfAnts; j++) {
|
||||
ants[j] = new Ant(numberOfCities);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate initial solution
|
||||
* @param n
|
||||
* @return
|
||||
*/
|
||||
public double[][] generateRandomMatrix(int n) {
|
||||
double[][] randomMatrix = new double[n][n];
|
||||
random.setSeed(System.currentTimeMillis());
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
Integer r = random.nextInt(100) + 1;
|
||||
randomMatrix[i][j] = Math.abs(r);
|
||||
}
|
||||
}
|
||||
return randomMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform ant optimization
|
||||
* @return
|
||||
*/
|
||||
public int[] startAntOptimization() {
|
||||
int[] finalResult = null;
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
System.out.println("Attempt #" + i);
|
||||
finalResult = solve();
|
||||
}
|
||||
return finalResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this method to run the main logic
|
||||
* @return
|
||||
*/
|
||||
private int[] solve() {
|
||||
setupAnts();
|
||||
clearTrails();
|
||||
int iteration = 0;
|
||||
while (iteration < maxIterations) {
|
||||
moveAnts();
|
||||
updateTrails();
|
||||
updateBest();
|
||||
iteration++;
|
||||
}
|
||||
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() {
|
||||
currentIndex = -1;
|
||||
for (int i = 0; i < numberOfAnts; i++) {
|
||||
ants[i].clear();
|
||||
ants[i].visitCity(currentIndex, random.nextInt(numberOfCities));
|
||||
}
|
||||
currentIndex++;
|
||||
}
|
||||
|
||||
/**
|
||||
* At each iteration, move ants
|
||||
*/
|
||||
private void moveAnts() {
|
||||
while (currentIndex < numberOfCities - 1) {
|
||||
for (Ant a : ants)
|
||||
a.visitCity(currentIndex, selectNextCity(a));
|
||||
currentIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select next city for each ant
|
||||
* @param ant
|
||||
* @return
|
||||
*/
|
||||
private int selectNextCity(Ant ant) {
|
||||
if (random.nextDouble() < randomFactor) {
|
||||
int t = random.nextInt(numberOfCities - currentIndex);
|
||||
int j = -1;
|
||||
for (int i = 0; i < numberOfCities; i++) {
|
||||
if (!ant.visited(i)) {
|
||||
j++;
|
||||
}
|
||||
if (j == t) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
*/
|
||||
private 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[0].trail;
|
||||
bestTourLength = ants[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() {
|
||||
for (int i = 0; i < numberOfCities; i++)
|
||||
for (int j = 0; j < numberOfCities; j++)
|
||||
trails[i][j] = c;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.baeldung.algorithms;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.algorithms.ga.ant_colony.AntColonyOptimization;
|
||||
|
||||
public class AntColonyOptimizationTest {
|
||||
|
||||
@Test
|
||||
public void testGenerateRandomMatrix() {
|
||||
AntColonyOptimization antTSP = new AntColonyOptimization(5);
|
||||
Assert.assertNotNull(antTSP.generateRandomMatrix(5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartAntOptimization() {
|
||||
AntColonyOptimization antTSP = new AntColonyOptimization(5);
|
||||
Assert.assertNotNull(antTSP.startAntOptimization());
|
||||
}
|
||||
|
||||
}
|
|
@ -3,7 +3,7 @@ package com.baeldung.algorithms;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.algorithms.annealing.SimulatedAnnealing;
|
||||
import com.baeldung.algorithms.ga.annealing.SimulatedAnnealing;
|
||||
|
||||
public class SimulatedAnnealingTest {
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ public class ListOfListsTest {
|
|||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void givenListOfLists_whenRemovingElements_thenCheckNames() {
|
||||
|
||||
((ArrayList<Pencil>) listOfLists.get(1)).remove(0);
|
||||
listOfLists.remove(1);
|
||||
assertEquals("Rubber 1", ((Rubber) listOfLists.get(1)
|
||||
|
@ -47,4 +48,29 @@ public class ListOfListsTest {
|
|||
assertEquals("Rubber 1", ((Rubber) listOfLists.get(0)
|
||||
.get(0)).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenThreeList_whenCombineIntoOneList_thenCheckList() {
|
||||
ArrayList<Pen> pens = new ArrayList<>();
|
||||
pens.add(new Pen("Pen 1"));
|
||||
pens.add(new Pen("Pen 2"));
|
||||
ArrayList<Pencil> pencils = new ArrayList<>();
|
||||
pencils.add(new Pencil("Pencil 1"));
|
||||
pencils.add(new Pencil("Pencil 2"));
|
||||
ArrayList<Rubber> rubbers = new ArrayList<>();
|
||||
rubbers.add(new Rubber("Rubber 1"));
|
||||
rubbers.add(new Rubber("Rubber 2"));
|
||||
|
||||
List<ArrayList<? extends Stationery>> list = new ArrayList<ArrayList<? extends Stationery>>();
|
||||
list.add(pens);
|
||||
list.add(pencils);
|
||||
list.add(rubbers);
|
||||
|
||||
assertEquals("Pen 1", ((Pen) list.get(0)
|
||||
.get(0)).getName());
|
||||
assertEquals("Pencil 1", ((Pencil) list.get(1)
|
||||
.get(0)).getName());
|
||||
assertEquals("Rubber 1", ((Rubber) list.get(2)
|
||||
.get(0)).getName());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
package org.baeldung.guava;
|
||||
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.reflect.Invokable;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class GuavaReflectionUtilsTest {
|
||||
|
||||
@Test
|
||||
public void givenTwoGenericList_whenCheckIsAssignableFrom_thenReturnTrueDueToTypeErasure() {
|
||||
//given
|
||||
ArrayList<String> stringList = Lists.newArrayList();
|
||||
ArrayList<Integer> intList = Lists.newArrayList();
|
||||
|
||||
//when
|
||||
boolean result = stringList.getClass().isAssignableFrom(intList.getClass());
|
||||
|
||||
//then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTypeToken_whenResolveType_thenShouldResolveProperType() {
|
||||
//given
|
||||
TypeToken<List<String>> stringListToken = new TypeToken<List<String>>() {
|
||||
};
|
||||
TypeToken<List<Integer>> integerListToken = new TypeToken<List<Integer>>() {
|
||||
};
|
||||
TypeToken<List<? extends Number>> numberTypeToken = new TypeToken<List<? extends Number>>() {
|
||||
};
|
||||
|
||||
//then
|
||||
assertFalse(stringListToken.isSubtypeOf(integerListToken));
|
||||
assertFalse(numberTypeToken.isSubtypeOf(integerListToken));
|
||||
assertTrue(integerListToken.isSubtypeOf(numberTypeToken));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenCustomClass_whenCaptureGeneric_thenReturnTypeAtRuntime() {
|
||||
//given
|
||||
ParametrizedClass<String> parametrizedClass = new ParametrizedClass<String>() {
|
||||
};
|
||||
|
||||
//then
|
||||
assertEquals(parametrizedClass.type, TypeToken.of(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenComplexType_whenGetTypeArgument_thenShouldReturnTypeAtRuntime() {
|
||||
//given
|
||||
TypeToken<Function<Integer, String>> funToken = new TypeToken<Function<Integer, String>>() {
|
||||
};
|
||||
|
||||
//when
|
||||
TypeToken<?> funResultToken = funToken.resolveType(Function.class.getTypeParameters()[1]);
|
||||
|
||||
//then
|
||||
assertEquals(funResultToken, TypeToken.of(String.class));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void givenMapType_whenGetTypeArgumentOfEntry_thenShouldReturnTypeAtRuntime() throws NoSuchMethodException {
|
||||
//given
|
||||
TypeToken<Map<String, Integer>> mapToken = new TypeToken<Map<String, Integer>>() {
|
||||
};
|
||||
|
||||
//when
|
||||
TypeToken<?> entrySetToken = mapToken.resolveType(Map.class.getMethod("entrySet").getGenericReturnType());
|
||||
|
||||
//then
|
||||
assertEquals(entrySetToken, new TypeToken<Set<Map.Entry<String, Integer>>>() {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInvokable_whenCheckPublicMethod_shouldReturnTrue() throws NoSuchMethodException {
|
||||
//given
|
||||
Method method = CustomClass.class.getMethod("somePublicMethod");
|
||||
Invokable<CustomClass, ?> invokable = new TypeToken<CustomClass>() {
|
||||
}.method(method);
|
||||
|
||||
//when
|
||||
boolean isPublicStandradJava = Modifier.isPublic(method.getModifiers());
|
||||
boolean isPublicGuava = invokable.isPublic();
|
||||
//then
|
||||
assertTrue(isPublicStandradJava);
|
||||
assertTrue(isPublicGuava);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenInvokable_whenCheckFinalMethod_shouldReturnFalseForIsOverridable() throws NoSuchMethodException {
|
||||
//given
|
||||
Method method = CustomClass.class.getMethod("notOverridablePublicMethod");
|
||||
Invokable<CustomClass, ?> invokable = new TypeToken<CustomClass>() {
|
||||
}.method(method);
|
||||
|
||||
//when
|
||||
boolean isOverridableStandardJava = (!(Modifier.isFinal(method.getModifiers()) || Modifier.isPrivate(method.getModifiers())
|
||||
|| Modifier.isStatic(method.getModifiers())
|
||||
|| Modifier.isFinal(method.getDeclaringClass().getModifiers())));
|
||||
boolean isOverridableFinalGauava = invokable.isOverridable();
|
||||
|
||||
//then
|
||||
assertFalse(isOverridableStandardJava);
|
||||
assertFalse(isOverridableFinalGauava);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenListOfType_whenGetReturnRype_shouldCaptureTypeAtRuntime() throws NoSuchMethodException {
|
||||
//given
|
||||
Method getMethod = List.class.getMethod("get", int.class);
|
||||
|
||||
//when
|
||||
Invokable<List<Integer>, ?> invokable = new TypeToken<List<Integer>>() {
|
||||
}.method(getMethod);
|
||||
|
||||
//then
|
||||
assertEquals(TypeToken.of(Integer.class), invokable.getReturnType()); // Not Object.class!
|
||||
}
|
||||
|
||||
|
||||
abstract class ParametrizedClass<T> {
|
||||
TypeToken<T> type = new TypeToken<T>(getClass()) {
|
||||
};
|
||||
}
|
||||
|
||||
class CustomClass {
|
||||
public void somePublicMethod() {
|
||||
}
|
||||
|
||||
public final void notOverridablePublicMethod() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.examples.guice</groupId>
|
||||
<artifactId>guice-intro</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
<version>${guice.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<guice.version>4.1.0</guice.version>
|
||||
</properties>
|
||||
<name>guice-intro</name>
|
||||
</project>
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
|
||||
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<String> 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +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);
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
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.
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
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 {
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
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()
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.examples.guice.marker;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Baeldung
|
||||
*/
|
||||
public interface Communicator {
|
||||
|
||||
public boolean sendMessage(String message);
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>jasypt</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jasypt</groupId>
|
||||
<artifactId>jasypt</artifactId>
|
||||
<version>${jasypt.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<jasypt.version>1.9.2</jasypt.version>
|
||||
<junit.version>4.12</junit.version>
|
||||
</properties>
|
||||
|
||||
|
||||
</project>
|
|
@ -0,0 +1,98 @@
|
|||
package org.baeldung.jasypt;
|
||||
|
||||
|
||||
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
|
||||
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
|
||||
import org.jasypt.util.password.BasicPasswordEncryptor;
|
||||
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.TestCase.assertEquals;
|
||||
|
||||
public class JasyptTest {
|
||||
|
||||
@Test
|
||||
public void givenTextPassword_whenDecrypt_thenCompareToEncrypted() {
|
||||
//given
|
||||
BasicTextEncryptor textEncryptor = new BasicTextEncryptor();
|
||||
String password = "secret-pass";
|
||||
textEncryptor.setPasswordCharArray("some-random-password".toCharArray());
|
||||
|
||||
//when
|
||||
String myEncryptedText = textEncryptor.encrypt(password);
|
||||
assertNotSame(password, myEncryptedText); //myEncryptedText can be save in db
|
||||
|
||||
//then
|
||||
String plainText = textEncryptor.decrypt(myEncryptedText);
|
||||
assertEquals(plainText, password);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTextPassword_whenOneWayEncryption_thenCompareEncryptedPasswordsShouldBeSame(){
|
||||
String password = "secret-pass";
|
||||
BasicPasswordEncryptor passwordEncryptor = new BasicPasswordEncryptor();
|
||||
String encryptedPassword = passwordEncryptor.encryptPassword(password);
|
||||
|
||||
//when
|
||||
boolean result = passwordEncryptor.checkPassword("secret-pass", encryptedPassword);
|
||||
|
||||
//then
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenTextPassword_whenOneWayEncryption_thenCompareEncryptedPasswordsShouldNotBeSame(){
|
||||
String password = "secret-pass";
|
||||
BasicPasswordEncryptor passwordEncryptor = new BasicPasswordEncryptor();
|
||||
String encryptedPassword = passwordEncryptor.encryptPassword(password);
|
||||
|
||||
//when
|
||||
boolean result = passwordEncryptor.checkPassword("secret-pass-not-same", encryptedPassword);
|
||||
|
||||
//then
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
@Ignore("should have installed local_policy.jar")
|
||||
public void givenTextPassword_whenDecrypt_thenCompareToEncryptedWithCustomAlgorithm() {
|
||||
//given
|
||||
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
|
||||
String password = "secret-pass";
|
||||
encryptor.setPassword("secret-pass");
|
||||
encryptor.setAlgorithm("PBEWithMD5AndTripleDES");
|
||||
|
||||
//when
|
||||
String encryptedText = encryptor.encrypt("secret-pass");
|
||||
assertNotSame(password, encryptedText);
|
||||
|
||||
//then
|
||||
String plainText = encryptor.decrypt(encryptedText);
|
||||
assertEquals(plainText, password);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("should have installed local_policy.jar")
|
||||
public void givenTextPassword_whenDecryptOnHighPerformance_thenDecrypt(){
|
||||
//given
|
||||
String password = "secret-pass";
|
||||
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
|
||||
encryptor.setPoolSize(4);
|
||||
encryptor.setPassword(password);
|
||||
encryptor.setAlgorithm("PBEWithMD5AndTripleDES");
|
||||
|
||||
//when
|
||||
String encryptedText = encryptor.encrypt(password);
|
||||
assertNotSame(password, encryptedText);
|
||||
|
||||
//then
|
||||
String plainText = encryptor.decrypt(encryptedText);
|
||||
assertEquals(plainText, password);
|
||||
}
|
||||
}
|
|
@ -31,71 +31,77 @@ public class CustomLoggingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void givenLoggerWithDefaultConfig_shouldLogToConsole() throws Exception {
|
||||
public void givenLoggerWithDefaultConfig_whenLogToConsole_thanOK() throws Exception {
|
||||
Logger logger = LogManager.getLogger(getClass());
|
||||
Exception e = new RuntimeException("This is only a test!");
|
||||
|
||||
logger.info("This is a simple message at INFO level. " + "It will be hidden.");
|
||||
logger.error("This is a simple message at ERROR level. " + "This is the minimum visible level.", e);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLoggerWithConsoleConfig_shouldLogToConsoleInColors() throws Exception {
|
||||
public void givenLoggerWithConsoleConfig_whenLogToConsoleInColors_thanOK() throws Exception {
|
||||
Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_MARKER");
|
||||
Exception e = new RuntimeException("This is only a test!");
|
||||
|
||||
logger.trace("This is a colored message at TRACE level.");
|
||||
logger.debug("This is a colored message at DEBUG level. " + "This is the minimum visible level.");
|
||||
logger.info("This is a colored message at INFO level.");
|
||||
logger.warn("This is a colored message at WARN level.");
|
||||
Exception e = new RuntimeException("This is only a test!");
|
||||
logger.error("This is a colored message at ERROR level.", e);
|
||||
logger.fatal("This is a colored message at FATAL level.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLoggerWithConsoleConfig_shouldFilterByMarker() throws Exception {
|
||||
public void givenLoggerWithConsoleConfig_whenFilterByMarker_thanOK() throws Exception {
|
||||
Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_MARKER");
|
||||
Marker appError = MarkerManager.getMarker("APP_ERROR");
|
||||
logger.error(appError, "This marker message at ERROR level should be hidden.");
|
||||
Marker connectionTrace = MarkerManager.getMarker("CONN_TRACE");
|
||||
|
||||
logger.error(appError, "This marker message at ERROR level should be hidden.");
|
||||
logger.trace(connectionTrace, "This is a marker message at TRACE level.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLoggerWithConsoleConfig_shouldFilterByThreadContext() throws Exception {
|
||||
public void givenLoggerWithConsoleConfig_whenFilterByThreadContext_thanOK() throws Exception {
|
||||
Logger logger = LogManager.getLogger("CONSOLE_PATTERN_APPENDER_THREAD_CONTEXT");
|
||||
ThreadContext.put("userId", "1000");
|
||||
logger.info("This is a log-visible user login. Maybe from an admin account?");
|
||||
ThreadContext.put("userId", "1001");
|
||||
logger.info("This is a log-invisible user login.");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLoggerWithAsyncConfig_shouldLogToJsonFile() throws Exception {
|
||||
public void givenLoggerWithAsyncConfig_whenLogToJsonFile_thanOK() throws Exception {
|
||||
Logger logger = LogManager.getLogger("ASYNC_JSON_FILE_APPENDER");
|
||||
|
||||
final int count = 88;
|
||||
for (int i = 0; i < count; i++) {
|
||||
logger.info("This is async JSON message #{} at INFO level.", count);
|
||||
}
|
||||
|
||||
long logEventsCount = Files.lines(Paths.get("target/logfile.json"))
|
||||
.count();
|
||||
assertTrue(logEventsCount > 0 && logEventsCount <= count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLoggerWithFailoverConfig_shouldLog() throws Exception {
|
||||
public void givenLoggerWithFailoverConfig_whenLog_thanOK() throws Exception {
|
||||
Logger logger = LogManager.getLogger("FAIL_OVER_SYSLOG_APPENDER");
|
||||
Exception e = new RuntimeException("This is only a test!");
|
||||
|
||||
logger.trace("This is a syslog message at TRACE level.");
|
||||
logger.debug("This is a syslog message at DEBUG level.");
|
||||
logger.info("This is a syslog message at INFO level. This is the minimum visible level.");
|
||||
logger.warn("This is a syslog message at WARN level.");
|
||||
Exception e = new RuntimeException("This is only a test!");
|
||||
logger.error("This is a syslog message at ERROR level.", e);
|
||||
logger.fatal("This is a syslog message at FATAL level.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenLoggerWithJdbcConfig_shouldLogToDataSource() throws Exception {
|
||||
public void givenLoggerWithJdbcConfig_whenLogToDataSource_thanOK() throws Exception {
|
||||
Logger logger = LogManager.getLogger("JDBC_APPENDER");
|
||||
|
||||
final int count = 88;
|
||||
for (int i = 0; i < count; i++) {
|
||||
logger.info("This is JDBC message #{} at INFO level.", count);
|
||||
|
@ -103,6 +109,7 @@ public class CustomLoggingTest {
|
|||
Connection connection = ConnectionFactory.getConnection();
|
||||
ResultSet resultSet = connection.createStatement()
|
||||
.executeQuery("SELECT COUNT(*) AS ROW_COUNT FROM logs");
|
||||
|
||||
int logCount = 0;
|
||||
if (resultSet.next()) {
|
||||
logCount = resultSet.getInt("ROW_COUNT");
|
||||
|
@ -111,8 +118,9 @@ public class CustomLoggingTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void givenLoggerWithRollingFileConfig_shouldLogToXMLFile() throws Exception {
|
||||
public void givenLoggerWithRollingFileConfig_whenLogToXMLFile_thanOK() throws Exception {
|
||||
Logger logger = LogManager.getLogger("XML_ROLLING_FILE_APPENDER");
|
||||
|
||||
final int count = 88;
|
||||
for (int i = 0; i < count; i++) {
|
||||
logger.info("This is rolling file XML message #{} at INFO level.", i);
|
||||
|
|
|
@ -19,12 +19,14 @@
|
|||
<Async name="AsyncAppender" bufferSize="80">
|
||||
<AppenderRef ref="JSONLogfileAppender" />
|
||||
</Async>
|
||||
<Syslog name="Syslog" format="RFC5424" host="localhost" port="514" protocol="TCP" facility="local3" connectTimeoutMillis="10000" reconnectionDelayMillis="5000" />
|
||||
<!--
|
||||
<Syslog name="Syslog" format="RFC5424" host="localhost" port="514" protocol="TCP" facility="local3" connectTimeoutMillis="10000" reconnectionDelayMillis="5000" mdcId="mdc" includeMDC="true" />
|
||||
<Failover name="FailoverAppender" primary="Syslog">
|
||||
<Failovers>
|
||||
<AppenderRef ref="ConsoleAppender" />
|
||||
</Failovers>
|
||||
</Failover>
|
||||
-->
|
||||
<JDBC name="JDBCAppender" tableName="logs">
|
||||
<ConnectionFactory class="com.baeldung.logging.log4j2.tests.jdbc.ConnectionFactory" method="getConnection" />
|
||||
<Column name="when" isEventTimestamp="true" />
|
||||
|
@ -53,9 +55,11 @@
|
|||
<Logger name="ASYNC_JSON_FILE_APPENDER" level="INFO" additivity="false">
|
||||
<AppenderRef ref="AsyncAppender" />
|
||||
</Logger>
|
||||
<!--
|
||||
<Logger name="FAIL_OVER_SYSLOG_APPENDER" level="INFO" additivity="false">
|
||||
<AppenderRef ref="FailoverAppender" />
|
||||
</Logger>
|
||||
-->
|
||||
<Logger name="JDBC_APPENDER" level="INFO" additivity="false">
|
||||
<AppenderRef ref="JDBCAppender" />
|
||||
</Logger>
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
*.class
|
||||
|
||||
.settings
|
||||
.project
|
||||
|
||||
#folders#
|
||||
/target
|
||||
/src/main/webapp/WEB-INF/classes
|
||||
*/META-INF/*
|
||||
|
||||
# Packaged files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
|
@ -0,0 +1,5 @@
|
|||
=========
|
||||
|
||||
## Mockito 2 and Java 8 Tips
|
||||
|
||||
Examples on how to leverage Java 8 new features with Mockito version 2
|
|
@ -0,0 +1,98 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>mockito2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>mockito-2-with-java8</name>
|
||||
|
||||
<dependencies>
|
||||
<!-- test scoped -->
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/*IntegrationTest.java</exclude>
|
||||
<exclude>**/*LiveTest.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>integration</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>integration-test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/*LiveTest.java</exclude>
|
||||
</excludes>
|
||||
<includes>
|
||||
<include>**/*IntegrationTest.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<test.mime>json</test.mime>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<!-- testing -->
|
||||
<junit.version>4.12</junit.version>
|
||||
<mockito.version>2.7.5</mockito.version>
|
||||
|
||||
<!-- maven plugins -->
|
||||
<maven-compiler-plugin.version>3.6.0</maven-compiler-plugin.version>
|
||||
<maven-surefire-plugin.version>2.19.1</maven-surefire-plugin.version>
|
||||
</properties>
|
||||
</project>
|
|
@ -0,0 +1,20 @@
|
|||
package com.baeldung.mockito.java8;
|
||||
|
||||
public class JobPosition {
|
||||
private String title;
|
||||
|
||||
public JobPosition() {}
|
||||
|
||||
public JobPosition(String title) {
|
||||
super();
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.baeldung.mockito.java8;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public interface JobService {
|
||||
Optional<JobPosition> findCurrentJobPosition(Person person);
|
||||
|
||||
default boolean assignJobPosition(Person person, JobPosition jobPosition) {
|
||||
if (!findCurrentJobPosition(person).isPresent()) {
|
||||
person.setCurrentJobPosition(jobPosition);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Stream<JobPosition> listJobs(Person person);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.baeldung.mockito.java8;
|
||||
|
||||
public class Person {
|
||||
private String name;
|
||||
private JobPosition currentJobPosition;
|
||||
|
||||
public Person() {}
|
||||
|
||||
public Person(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public JobPosition getCurrentJobPosition() {
|
||||
return currentJobPosition;
|
||||
}
|
||||
|
||||
public void setCurrentJobPosition(JobPosition currentJobPosition) {
|
||||
this.currentJobPosition = currentJobPosition;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.mockito.java8;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface UnemploymentService {
|
||||
|
||||
boolean personIsEntitledToUnemploymentSupport(Person person);
|
||||
|
||||
Optional<JobPosition> searchJob(Person person, String searchString);
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.baeldung.mockito.java8;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class UnemploymentServiceImpl implements UnemploymentService {
|
||||
private final JobService jobService;
|
||||
|
||||
public UnemploymentServiceImpl(JobService jobService) {
|
||||
this.jobService = jobService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean personIsEntitledToUnemploymentSupport(Person person) {
|
||||
Optional<JobPosition> optional = jobService.findCurrentJobPosition(person);
|
||||
|
||||
return !optional.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<JobPosition> searchJob(Person person, String searchString) {
|
||||
Stream<JobPosition> stream = jobService.listJobs(person);
|
||||
|
||||
return stream.filter((j) -> j.getTitle().contains(searchString)).findFirst();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.baeldung.mockito.java8;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
|
||||
public class ArgumentMatcherWithLambdaUnitTest {
|
||||
|
||||
@InjectMocks
|
||||
private UnemploymentServiceImpl unemploymentService;
|
||||
|
||||
@Mock
|
||||
private JobService jobService;
|
||||
|
||||
@Test
|
||||
public void whenPersonWithJob_thenIsNotEntitled() {
|
||||
Person peter = new Person("Peter");
|
||||
Person linda = new Person("Linda");
|
||||
|
||||
JobPosition teacher = new JobPosition("Teacher");
|
||||
|
||||
when(jobService.findCurrentJobPosition(
|
||||
ArgumentMatchers.argThat((p) -> p.getName().equals("Peter")))
|
||||
).thenReturn(Optional.of(teacher));
|
||||
|
||||
assertTrue(unemploymentService.personIsEntitledToUnemploymentSupport(linda));
|
||||
assertFalse(unemploymentService.personIsEntitledToUnemploymentSupport(peter));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.baeldung.mockito.java8;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.ArgumentMatcher;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
|
||||
public class ArgumentMatcherWithoutLambdaUnitTest {
|
||||
@InjectMocks
|
||||
private UnemploymentServiceImpl unemploymentService;
|
||||
|
||||
@Mock
|
||||
private JobService jobService;
|
||||
|
||||
@Test
|
||||
public void whenPersonWithJob_thenIsNotEntitled() {
|
||||
Person peter = new Person("Peter");
|
||||
Person linda = new Person("Linda");
|
||||
|
||||
JobPosition teacher = new JobPosition("Teacher");
|
||||
|
||||
when(jobService.findCurrentJobPosition(
|
||||
ArgumentMatchers.argThat(new PeterArgumentMatcher()))
|
||||
).thenReturn(Optional.of(teacher));
|
||||
|
||||
assertTrue(unemploymentService.personIsEntitledToUnemploymentSupport(linda));
|
||||
assertFalse(unemploymentService.personIsEntitledToUnemploymentSupport(peter));
|
||||
}
|
||||
|
||||
private class PeterArgumentMatcher implements ArgumentMatcher<Person> {
|
||||
@Override
|
||||
public boolean matches(Person p) {
|
||||
|
||||
if (p.getName().equals("Peter")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package com.baeldung.mockito.java8;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
public class CustomAnswerWithLambdaUnitTest {
|
||||
@InjectMocks
|
||||
private UnemploymentServiceImpl unemploymentService;
|
||||
|
||||
@Mock
|
||||
private JobService jobService;
|
||||
|
||||
@Test
|
||||
public void whenPersonWithJobHistory_thenSearchReturnsValue() {
|
||||
Person peter = new Person("Peter");
|
||||
|
||||
assertEquals("Teacher", unemploymentService.searchJob(peter, "").get().getTitle());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenPersonWithNoJobHistory_thenSearchReturnsEmpty() {
|
||||
Person linda = new Person("Linda");
|
||||
|
||||
assertFalse(unemploymentService.searchJob(linda, "").isPresent());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
when(jobService.listJobs(any(Person.class))).then((i) -> {
|
||||
return ((Person) i.getArgument(0)).getName().equals("Peter") ? Stream.of(new JobPosition("Teacher")) : Stream.empty();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.baeldung.mockito.java8;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
|
||||
public class CustomAnswerWithoutLambdaUnitTest {
|
||||
@InjectMocks
|
||||
private UnemploymentServiceImpl unemploymentService;
|
||||
|
||||
@Mock
|
||||
private JobService jobService;
|
||||
|
||||
@Test
|
||||
public void whenPersonWithJobHistory_thenSearchReturnsValue() {
|
||||
Person peter = new Person("Peter");
|
||||
|
||||
assertEquals("Teacher", unemploymentService.searchJob(peter, "").get().getTitle());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenPersonWithNoJobHistory_thenSearchReturnsEmpty() {
|
||||
Person linda = new Person("Linda");
|
||||
|
||||
assertFalse(unemploymentService.searchJob(linda, "").isPresent());
|
||||
}
|
||||
|
||||
private class PersonAnswer implements Answer<Stream<JobPosition>> {
|
||||
@Override
|
||||
public Stream<JobPosition> answer(InvocationOnMock invocation) throws Throwable {
|
||||
Person person = invocation.getArgument(0);
|
||||
|
||||
if(person.getName().equals("Peter")) {
|
||||
return Stream.<JobPosition>builder().add(new JobPosition("Teacher")).build();
|
||||
}
|
||||
|
||||
return Stream.empty();
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
when(jobService.listJobs(any(Person.class))).then(new PersonAnswer());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.baeldung.mockito.java8;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.doCallRealMethod;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
public class JobServiceUnitTest {
|
||||
@Mock
|
||||
private JobService jobService;
|
||||
|
||||
@Test
|
||||
public void givenDefaultMethod_whenCallRealMethod_thenNoExceptionIsRaised() {
|
||||
Person person = new Person();
|
||||
|
||||
when(jobService.findCurrentJobPosition(person)).thenReturn(Optional.of(new JobPosition()));
|
||||
doCallRealMethod().when(jobService).assignJobPosition(Mockito.any(Person.class), Mockito.any(JobPosition.class));
|
||||
|
||||
assertFalse(jobService.assignJobPosition(person, new JobPosition()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenReturnIsOfTypeOptional_whenDefaultValueIsReturned_thenValueIsEmpty() {
|
||||
Person person = new Person();
|
||||
|
||||
when(jobService.findCurrentJobPosition(person)).thenReturn(Optional.empty());
|
||||
doCallRealMethod().when(jobService).assignJobPosition(Mockito.any(Person.class), Mockito.any(JobPosition.class));
|
||||
|
||||
assertTrue(jobService.assignJobPosition(person, new JobPosition()));
|
||||
}
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package com.baeldung.mockito.java8;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
public class UnemploymentServiceImplUnitTest {
|
||||
@Mock
|
||||
private JobService jobService;
|
||||
|
||||
@InjectMocks
|
||||
private UnemploymentServiceImpl unemploymentService;
|
||||
|
||||
@Test
|
||||
public void givenReturnIsOfTypeOptional_whenMocked_thenValueIsEmpty() {
|
||||
Person person = new Person();
|
||||
|
||||
when(jobService.findCurrentJobPosition(any(Person.class))).thenReturn(Optional.empty());
|
||||
|
||||
assertTrue(unemploymentService.personIsEntitledToUnemploymentSupport(person));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenReturnIsOfTypeOptional_whenDefaultValueIsReturned_thenValueIsEmpty() {
|
||||
Person person = new Person();
|
||||
|
||||
// This will fail when Mockito 1 is used
|
||||
assertTrue(unemploymentService.personIsEntitledToUnemploymentSupport(person));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenReturnIsOfTypeStream_whenMocked_thenValueIsEmpty() {
|
||||
Person person = new Person();
|
||||
|
||||
when(jobService.listJobs(any(Person.class))).thenReturn(Stream.empty());
|
||||
|
||||
assertFalse(unemploymentService.searchJob(person, "").isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenReturnIsOfTypeStream_whenDefaultValueIsReturned_thenValueIsEmpty() {
|
||||
Person person = new Person();
|
||||
|
||||
// This will fail when Mockito 1 is used
|
||||
assertFalse(unemploymentService.searchJob(person, "").isPresent());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
}
|
4
pom.xml
4
pom.xml
|
@ -46,6 +46,7 @@
|
|||
<module>guava</module>
|
||||
<module>guava18</module>
|
||||
<module>guava19</module>
|
||||
<module>guice-intro</module>
|
||||
<module>disruptor</module>
|
||||
|
||||
<module>handling-spring-static-resources</module>
|
||||
|
@ -61,6 +62,7 @@
|
|||
<module>javaslang</module>
|
||||
<module>javax-servlets</module>
|
||||
<module>javaxval</module>
|
||||
<module>jasypt</module>
|
||||
<module>jaxb</module>
|
||||
<module>jee7</module>
|
||||
<module>jjwt</module>
|
||||
|
@ -84,6 +86,7 @@
|
|||
<module>metrics</module>
|
||||
<module>mesos-marathon</module>
|
||||
<module>mockito</module>
|
||||
<module>mockito2</module>
|
||||
<module>mocks</module>
|
||||
|
||||
<module>orika</module>
|
||||
|
@ -111,7 +114,6 @@
|
|||
<module>spring-autowire</module>
|
||||
<module>spring-batch</module>
|
||||
<module>spring-boot</module>
|
||||
<module>spring-boot-servlet</module>
|
||||
<module>spring-cloud-data-flow</module>
|
||||
<module>spring-cloud</module>
|
||||
<module>spring-core</module>
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<reactor-core.version>3.0.4.RELEASE</reactor-core.version>
|
||||
<reactor-core.version>3.0.5.RELEASE</reactor-core.version>
|
||||
<junit.version>4.12</junit.version>
|
||||
<assertj.version>3.6.1</assertj.version>
|
||||
<logback.version>1.1.3</logback.version>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.solr</groupId>
|
||||
<artifactId>solr-solrj</artifactId>
|
||||
<version>6.1.0</version>
|
||||
<version>6.4.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>log4j</groupId>
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
package com.baeldung.solr.fulltext.search.model;
|
||||
|
||||
import org.apache.solr.client.solrj.beans.Field;
|
||||
|
||||
public class Item {
|
||||
|
||||
@Field
|
||||
private String id;
|
||||
|
||||
@Field
|
||||
private String description;
|
||||
|
||||
@Field
|
||||
private String category;
|
||||
|
||||
@Field
|
||||
private float price;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getCategory() {
|
||||
return category;
|
||||
}
|
||||
|
||||
public void setCategory(String category) {
|
||||
this.category = category;
|
||||
}
|
||||
|
||||
public float getPrice() {
|
||||
return price;
|
||||
}
|
||||
|
||||
public void setPrice(float price) {
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.baeldung.solr.fulltext.search.service;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
|
||||
import com.baeldung.solr.fulltext.search.model.Item;
|
||||
|
||||
public interface ItemSearchService {
|
||||
|
||||
public void index(String id, String description, String category, float price) throws SolrServerException, IOException;
|
||||
|
||||
public void indexBean(Item item) throws IOException, SolrServerException;
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.baeldung.solr.fulltext.search.service;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.solr.client.solrj.SolrClient;
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
|
||||
import com.baeldung.solr.fulltext.search.model.Item;
|
||||
|
||||
public class ItemSearchServiceImpl implements ItemSearchService {
|
||||
|
||||
private final SolrClient solrClient;
|
||||
|
||||
public ItemSearchServiceImpl(SolrClient solrClient) {
|
||||
this.solrClient = solrClient;
|
||||
}
|
||||
|
||||
public void index(String id, String description, String category, float price) throws SolrServerException, IOException {
|
||||
SolrInputDocument doc = new SolrInputDocument();
|
||||
doc.addField("id", id);
|
||||
doc.addField("description", description);
|
||||
doc.addField("category", category);
|
||||
doc.addField("price", price);
|
||||
solrClient.add(doc);
|
||||
solrClient.commit();
|
||||
}
|
||||
|
||||
public void indexBean(Item item) throws IOException, SolrServerException {
|
||||
solrClient.addBean(item);
|
||||
solrClient.commit();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,374 @@
|
|||
package com.baeldung.solr.fulltext.search.service;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.solr.client.solrj.SolrClient;
|
||||
import org.apache.solr.client.solrj.SolrQuery;
|
||||
import org.apache.solr.client.solrj.impl.HttpSolrClient;
|
||||
import org.apache.solr.client.solrj.response.FacetField.Count;
|
||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
||||
import org.apache.solr.client.solrj.response.RangeFacet;
|
||||
import org.apache.solr.client.solrj.response.SpellCheckResponse;
|
||||
import org.apache.solr.client.solrj.response.SpellCheckResponse.Suggestion;
|
||||
import org.apache.solr.client.solrj.response.SuggesterResponse;
|
||||
import org.apache.solr.common.SolrDocument;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.baeldung.solr.fulltext.search.model.Item;
|
||||
|
||||
public class ItemSearchServiceIntegrationTest {
|
||||
|
||||
private static SolrClient solrClient;
|
||||
private static ItemSearchService itemSearchService;
|
||||
private static final String solrUrl = "http://localhost:8987/solr/item";
|
||||
|
||||
@BeforeClass
|
||||
public static void initBeans() throws Exception {
|
||||
solrClient = new HttpSolrClient.Builder(solrUrl).build();
|
||||
itemSearchService = new ItemSearchServiceImpl(solrClient);
|
||||
|
||||
solrClient.commit();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void clearSolrData() throws Exception {
|
||||
solrClient.deleteByQuery("*:*");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenIndexing_thenAvailableOnRetrieval() throws Exception {
|
||||
itemSearchService.index("hm0001", "Washing Machine", "Home Appliances", 450f);
|
||||
final SolrDocument indexedDoc = solrClient.getById("hm0001");
|
||||
assertEquals("hm0001", indexedDoc.get("id"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenIndexingBean_thenAvailableOnRetrieval() throws Exception {
|
||||
Item item = new Item();
|
||||
item.setId("hm0002");
|
||||
item.setCategory("Televisions");
|
||||
item.setDescription("LED TV 32");
|
||||
item.setPrice(500);
|
||||
itemSearchService.indexBean(item);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingByBasicQuery_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0003", "LED TV 32", "Brand1 Home Appliances", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("brand1");
|
||||
query.setStart(0);
|
||||
query.setRows(10);
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(3, items.size());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithWildCard_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0003", "LED TV 32", "Brand1 Home Appliances", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("*rand?");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(3, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithLogicalOperators_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0003", "Brand2 LED TV 32", "Washing Appliances", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("brand1 AND (Washing OR Refrigerator)");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(2, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithFields_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("0001", "Brand1 Washing Machine", "Home Appliances", 450f);
|
||||
itemSearchService.index("0002", "Brand1 Refrigerator", "Home Appliances", 450f);
|
||||
itemSearchService.index("0003", "Brand2 LED TV 32", "Brand1 Washing Home Appliances", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("description:Brand* AND category:*Washing*");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(1, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithPhrase_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("washing MachIne");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(2, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithRealPhrase_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("\"washing machine\"");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(1, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingPhraseWithProximity_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 450f);
|
||||
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("\"Washing equipment\"~2");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(1, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithPriceRange_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
|
||||
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Home Appliances", 200f);
|
||||
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("price:[100 TO 300]");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(3, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithPriceRangeInclusiveExclusive_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
|
||||
itemSearchService.index("hm0003", "Brand2 Dishwasher", "Home Appliances", 200f);
|
||||
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing tools and equipment ", 450f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("price:{100 TO 300]");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(2, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithFilterQuery_thenAllMatchingItemsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
|
||||
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f);
|
||||
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing tools and equipment ", 250f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("price:[100 TO 300]");
|
||||
query.addFilterQuery("description:Brand1", "category:Home Appliances");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Item> items = response.getBeans(Item.class);
|
||||
|
||||
assertEquals(2, items.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithFacetFields_thenAllMatchingFacetsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "CategoryA", 100f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "CategoryA", 300f);
|
||||
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "CategoryB", 200f);
|
||||
itemSearchService.index("hm0004", "Brand2 Dishwasher", "CategoryB", 250f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("*:*");
|
||||
query.addFacetField("category");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<Count> facetResults = response.getFacetField("category").getValues();
|
||||
|
||||
assertEquals(2, facetResults.size());
|
||||
|
||||
for (Count count : facetResults) {
|
||||
if ("categorya".equalsIgnoreCase(count.getName())) {
|
||||
assertEquals(2, count.getCount());
|
||||
} else if ("categoryb".equalsIgnoreCase(count.getName())) {
|
||||
assertEquals(2, count.getCount());
|
||||
} else {
|
||||
fail("unexpected category");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithFacetQuery_thenAllMatchingFacetsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "CategoryA", 100f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "CategoryA", 300f);
|
||||
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "CategoryB", 200f);
|
||||
itemSearchService.index("hm0004", "Brand2 Dishwasher", "CategoryB", 250f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("*:*");
|
||||
|
||||
query.addFacetQuery("Washing OR Refrigerator");
|
||||
query.addFacetQuery("Brand2");
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
Map<String, Integer> facetQueryMap = response.getFacetQuery();
|
||||
|
||||
assertEquals(2, facetQueryMap.size());
|
||||
|
||||
for (Map.Entry<String, Integer> entry : facetQueryMap.entrySet()) {
|
||||
String facetQuery = entry.getKey();
|
||||
|
||||
if ("Washing OR Refrigerator".equals(facetQuery)) {
|
||||
assertEquals(Integer.valueOf(2), entry.getValue());
|
||||
} else if ("Brand2".equals(facetQuery)) {
|
||||
assertEquals(Integer.valueOf(2), entry.getValue());
|
||||
} else {
|
||||
fail("unexpected query");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithFacetRange_thenAllMatchingFacetsShouldAvialble() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "CategoryA", 100f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "CategoryA", 125f);
|
||||
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "CategoryB", 150f);
|
||||
itemSearchService.index("hm0004", "Brand2 Dishwasher", "CategoryB", 250f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("*:*");
|
||||
|
||||
query.addNumericRangeFacet("price", 100, 275, 25);
|
||||
|
||||
QueryResponse response = solrClient.query(query);
|
||||
List<RangeFacet> rangeFacets = response.getFacetRanges().get(0).getCounts();
|
||||
|
||||
assertEquals(7, rangeFacets.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithHitHighlighting_thenKeywordsShouldBeHighlighted() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
|
||||
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f);
|
||||
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing equipments", 250f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("Appliances");
|
||||
query.setHighlight(true);
|
||||
query.addHighlightField("category");
|
||||
query.setHighlightSimplePre("<strong>");
|
||||
query.setHighlightSimplePost("</strong>");
|
||||
QueryResponse response = solrClient.query(query);
|
||||
|
||||
Map<String, Map<String, List<String>>> hitHighlightedMap = response.getHighlighting();
|
||||
Map<String, List<String>> highlightedFieldMap = hitHighlightedMap.get("hm0001");
|
||||
List<String> highlightedList = highlightedFieldMap.get("category");
|
||||
String highLightedText = highlightedList.get(0);
|
||||
|
||||
assertEquals("Home <strong>Appliances</strong>", highLightedText);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithKeywordWithMistake_thenSpellingSuggestionsShouldBeReturned() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
|
||||
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f);
|
||||
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Washing equipments", 250f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("hme");
|
||||
query.set("spellcheck", "on");
|
||||
QueryResponse response = solrClient.query(query);
|
||||
|
||||
SpellCheckResponse spellCheckResponse = response.getSpellCheckResponse();
|
||||
|
||||
assertEquals(false, spellCheckResponse.isCorrectlySpelled());
|
||||
|
||||
Suggestion suggestion = spellCheckResponse.getSuggestions().get(0);
|
||||
|
||||
assertEquals("hme", suggestion.getToken());
|
||||
|
||||
List<String> alternatives = suggestion.getAlternatives();
|
||||
String alternative = alternatives.get(0);
|
||||
|
||||
assertEquals("home", alternative);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSearchingWithIncompleteKeyword_thenKeywordSuggestionsShouldBeReturned() throws Exception {
|
||||
itemSearchService.index("hm0001", "Brand1 Washing Machine", "Home Appliances", 100f);
|
||||
itemSearchService.index("hm0002", "Brand1 Refrigerator", "Home Appliances", 300f);
|
||||
itemSearchService.index("hm0003", "Brand2 Ceiling Fan", "Home Appliances", 200f);
|
||||
itemSearchService.index("hm0004", "Brand2 Dishwasher", "Home washing equipments", 250f);
|
||||
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setRequestHandler("/suggest");
|
||||
query.set("suggest", "true");
|
||||
query.set("suggest.build", "true");
|
||||
query.set("suggest.dictionary", "mySuggester");
|
||||
query.set("suggest.q", "Hom");
|
||||
QueryResponse response = solrClient.query(query);
|
||||
|
||||
SuggesterResponse suggesterResponse = response.getSuggesterResponse();
|
||||
Map<String, List<String>> suggestedTerms = suggesterResponse.getSuggestedTerms();
|
||||
List<String> suggestions = suggestedTerms.get("mySuggester");
|
||||
|
||||
assertEquals(2, suggestions.size());
|
||||
|
||||
for (String term : suggestions) {
|
||||
if (!"Home Appliances".equals(term) && !"Home washing equipments".equals(term)) {
|
||||
fail("Unexpected suggestions");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -2,3 +2,5 @@
|
|||
.settings/
|
||||
.classpath
|
||||
.project
|
||||
*.iml
|
||||
.idea
|
|
@ -0,0 +1,198 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-boot-auditing</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
<name>spring-boot-auditing</name>
|
||||
<description>This is simple boot application for Spring boot auditing test</description>
|
||||
|
||||
<!-- Inherit defaults from Spring Boot -->
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.5.1.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.dropwizard.metrics</groupId>
|
||||
<artifactId>metrics-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-mail</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.subethamail</groupId>
|
||||
<artifactId>subethasmtp</artifactId>
|
||||
<version>${subethasmtp.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>bootstrap</artifactId>
|
||||
<version>${bootstrap.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.webjars</groupId>
|
||||
<artifactId>jquery</artifactId>
|
||||
<version>${jquery.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>tomcat-servlet-api</artifactId>
|
||||
<version>${tomee-servlet-api.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>spring-boot</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>pl.project13.maven</groupId>
|
||||
<artifactId>git-commit-id-plugin</artifactId>
|
||||
<version>${git-commit-id-plugin.version}</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/*IntegrationTest.java</exclude>
|
||||
<exclude>**/*LiveTest.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>integration</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>integration-test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/*LiveTest.java</exclude>
|
||||
</excludes>
|
||||
<includes>
|
||||
<include>**/*IntegrationTest.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<test.mime>json</test.mime>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<spring.version>4.3.4.RELEASE</spring.version>
|
||||
<git-commit-id-plugin.version>2.2.1</git-commit-id-plugin.version>
|
||||
<jquery.version>3.1.1</jquery.version>
|
||||
<bootstrap.version>3.3.7-1</bootstrap.version>
|
||||
<subethasmtp.version>3.1.7</subethasmtp.version>
|
||||
<tomee-servlet-api.version>8.5.11</tomee-servlet-api.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,13 @@
|
|||
package org.baeldung;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package org.baeldung;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
|
||||
@Configuration
|
||||
public class MvcConfig extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
registry.addViewController("/home").setViewName("home");
|
||||
registry.addViewController("/").setViewName("home");
|
||||
registry.addViewController("/hello").setViewName("hello");
|
||||
registry.addViewController("/login").setViewName("login");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package org.baeldung;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/", "/home").permitAll()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.formLogin()
|
||||
.loginPage("/login")
|
||||
.permitAll()
|
||||
.and()
|
||||
.logout()
|
||||
.permitAll();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth
|
||||
.inMemoryAuthentication()
|
||||
.withUser("user").password("password").roles("USER");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package org.baeldung.auditing;
|
||||
|
||||
import org.springframework.boot.actuate.audit.AuditEvent;
|
||||
import org.springframework.boot.actuate.security.AbstractAuthorizationAuditListener;
|
||||
import org.springframework.security.access.event.AbstractAuthorizationEvent;
|
||||
import org.springframework.security.access.event.AuthorizationFailureEvent;
|
||||
import org.springframework.security.web.FilterInvocation;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class ExposeAttemptedPathAuthorizationAuditListener extends AbstractAuthorizationAuditListener {
|
||||
|
||||
public static final String AUTHORIZATION_FAILURE = "AUTHORIZATION_FAILURE";
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(AbstractAuthorizationEvent event) {
|
||||
if (event instanceof AuthorizationFailureEvent) {
|
||||
onAuthorizationFailureEvent((AuthorizationFailureEvent) event);
|
||||
}
|
||||
}
|
||||
|
||||
private void onAuthorizationFailureEvent(AuthorizationFailureEvent event) {
|
||||
Map<String, Object> data = new HashMap<>();
|
||||
data.put("type", event.getAccessDeniedException().getClass().getName());
|
||||
data.put("message", event.getAccessDeniedException().getMessage());
|
||||
data.put("requestUrl", ((FilterInvocation)event.getSource()).getRequestUrl() );
|
||||
if (event.getAuthentication().getDetails() != null) {
|
||||
data.put("details", event.getAuthentication().getDetails());
|
||||
}
|
||||
publish(new AuditEvent(event.getAuthentication().getName(), AUTHORIZATION_FAILURE,
|
||||
data));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package org.baeldung.auditing;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.actuate.audit.AuditEvent;
|
||||
import org.springframework.boot.actuate.audit.listener.AuditApplicationEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class LoginAttemptsLogger {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LoginAttemptsLogger.class);
|
||||
|
||||
@EventListener
|
||||
public void auditEventHappened(AuditApplicationEvent auditApplicationEvent) {
|
||||
AuditEvent auditEvent = auditApplicationEvent.getAuditEvent();
|
||||
LOGGER.debug("Principal " + auditEvent.getPrincipal() + " - " + auditEvent.getType());
|
||||
|
||||
WebAuthenticationDetails details = (WebAuthenticationDetails) auditEvent.getData().get("details");
|
||||
LOGGER.debug(" Remote IP address: " + details.getRemoteAddress());
|
||||
LOGGER.debug(" Session Id: " + details.getSessionId());
|
||||
LOGGER.debug(" Request URL: " + auditEvent.getData().get("requestUrl"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
logging.level.org.springframework=INFO
|
|
@ -0,0 +1,14 @@
|
|||
<configuration>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>web - %date [%thread] %-5level %logger{36} - %message%n
|
||||
</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
|
||||
<head>
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
|
||||
<form th:action="@{/logout}" method="post">
|
||||
<input type="submit" value="Sign Out"/>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
|
||||
<head>
|
||||
<title>Spring Security Example</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Welcome!</h1>
|
||||
|
||||
<p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
|
||||
<head>
|
||||
<title>Spring Security Example </title>
|
||||
</head>
|
||||
<body>
|
||||
<div th:if="${param.error}">
|
||||
Invalid username and password.
|
||||
</div>
|
||||
<div th:if="${param.logout}">
|
||||
You have been logged out.
|
||||
</div>
|
||||
<form th:action="@{/login}" method="post">
|
||||
<div><label> User Name : <input type="text" name="username"/> </label></div>
|
||||
<div><label> Password: <input type="password" name="password"/> </label></div>
|
||||
<div><input type="submit" value="Sign In"/></div>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
|
@ -1,2 +0,0 @@
|
|||
###Relevant Articles:
|
||||
- [How to Register a Servlet in a Java Web Application](http://www.baeldung.com/how-to-register-a-servlet-in-a-java-web-application/)
|
|
@ -1,55 +0,0 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-boot-servlet</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
<name>spring-boot-servlet</name>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>1.5.1.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring Boot Dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- Embedded EmbeddedTomcatExample Dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
<version>${tomcat.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-jasper</artifactId>
|
||||
<version>${tomcat.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<tomcat.version>8.5.11</tomcat.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
|
@ -1,2 +0,0 @@
|
|||
Manifest-Version: 1.0
|
||||
Main-Class: com.baeldung.ApplicationMain
|
|
@ -1,10 +0,0 @@
|
|||
#Server Configuration
|
||||
#server.port=8080
|
||||
#server.context-path=/javabootdata
|
||||
#Resource Handling
|
||||
#spring.resources.static-locations=classpath:/WEB-INF/resources
|
||||
#spring.mvc.view.prefix=/WEB-INF/
|
||||
#spring.mvc.view.suffix=.jsp
|
||||
#spring.resources.cache-period=3600
|
||||
servlet.name=dispatcherExample
|
||||
servlet.mapping=/dispatcherExampleURL
|
|
@ -10,3 +10,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
|||
- [The @ServletComponentScan Annotation in Spring Boot](http://www.baeldung.com/spring-servletcomponentscan)
|
||||
- [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/how-to-register-a-servlet-in-a-java-web-application/)
|
||||
|
|
|
@ -41,6 +41,24 @@
|
|||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-core</artifactId>
|
||||
<version>${tomcat.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-jasper</artifactId>
|
||||
<version>${tomcat.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.dropwizard.metrics</groupId>
|
||||
<artifactId>metrics-core</artifactId>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung;
|
||||
package com.baeldung.servlets;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.configuration;
|
||||
package com.baeldung.servlets.configuration;
|
||||
|
||||
import org.springframework.web.WebApplicationInitializer;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.configuration;
|
||||
package com.baeldung.servlets.configuration;
|
||||
|
||||
import org.springframework.boot.web.support.ErrorPageFilter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -37,4 +37,3 @@ public class WebMvcConfigure extends WebMvcConfigurerAdapter {
|
|||
return new ErrorPageFilter();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.props;
|
||||
package com.baeldung.servlets.props;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.props;
|
||||
package com.baeldung.servlets.props;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.props;
|
||||
package com.baeldung.servlets.props;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.servlets;
|
||||
package com.baeldung.servlets.servlets;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.servlets.javaee;
|
||||
package com.baeldung.servlets.servlets.javaee;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.servlets.javaee;
|
||||
package com.baeldung.servlets.servlets.javaee;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
|
@ -1,6 +1,6 @@
|
|||
package com.baeldung.servlets.springboot;
|
||||
package com.baeldung.servlets.servlets.springboot;
|
||||
|
||||
import com.baeldung.servlets.GenericCustomServlet;
|
||||
import com.baeldung.servlets.servlets.GenericCustomServlet;
|
||||
import org.springframework.boot.web.servlet.ServletRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
@ -15,5 +15,3 @@ public class SpringRegistrationBeanServlet {
|
|||
return bean;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.baeldung.servlets.springboot.embedded;
|
||||
package com.baeldung.servlets.servlets.springboot.embedded;
|
||||
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
|
@ -29,3 +29,7 @@ security.user.password=secret1
|
|||
management.security.role=SUPERUSER
|
||||
|
||||
logging.level.org.springframework=INFO
|
||||
|
||||
#Servlet Configuration
|
||||
servlet.name=dispatcherExample
|
||||
servlet.mapping=/dispatcherExampleURL
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
### Relevant Articles:
|
||||
- [Spring Cloud – Bootstrapping](http://www.baeldung.com/spring-cloud-bootstrapping)
|
||||
- [Spring Cloud – Securing Services](http://www.baeldung.com/spring-cloud-securing-services)
|
||||
|
||||
- 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:
|
||||
- git init
|
||||
- git add .
|
||||
- git commit -m "First commit"
|
||||
- start the config server
|
||||
- start the discover server
|
||||
- start all the other servers in any order (gateway, svc-book, svc-rating, zipkin)
|
||||
|
|
|
@ -15,3 +15,6 @@ logging.level.org.springframework.security=debug
|
|||
|
||||
spring.redis.host=localhost
|
||||
spring.redis.port=6379
|
||||
|
||||
spring.sleuth.sampler.percentage=1.0
|
||||
spring.sleuth.web.skipPattern=(^cleanup.*)
|
||||
|
|
|
@ -25,3 +25,6 @@ logging.level.org.springframework.cloud.netflix.zuul=debug
|
|||
|
||||
spring.redis.host=localhost
|
||||
spring.redis.port=6379
|
||||
|
||||
spring.sleuth.sampler.percentage=1.0
|
||||
spring.sleuth.web.skipPattern=(^cleanup.*|.+favicon.*)
|
|
@ -15,3 +15,6 @@ logging.level.org.springframework.security=debug
|
|||
|
||||
spring.redis.host=localhost
|
||||
spring.redis.port=6379
|
||||
|
||||
spring.sleuth.sampler.percentage=1.0
|
||||
spring.sleuth.web.skipPattern=(^cleanup.*)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
spring.application.name=zipkin
|
||||
server.port=9411
|
||||
|
||||
eureka.client.region = default
|
||||
eureka.client.registryFetchIntervalSeconds = 5
|
||||
|
||||
logging.level.org.springframework.web=debug
|
|
@ -41,6 +41,11 @@
|
|||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-zipkin</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package com.baeldung.spring.cloud.bootstrap.gateway;
|
||||
|
||||
import com.netflix.appinfo.InstanceInfo;
|
||||
import com.netflix.discovery.EurekaClient;
|
||||
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.cloud.client.loadbalancer.LoadBalanced;
|
||||
|
@ -8,8 +11,13 @@ import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
|
|||
import org.springframework.cloud.netflix.ribbon.RibbonClientSpecification;
|
||||
import org.springframework.cloud.netflix.ribbon.SpringClientFactory;
|
||||
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
|
||||
import org.springframework.cloud.sleuth.metric.SpanMetricReporter;
|
||||
import org.springframework.cloud.sleuth.zipkin.HttpZipkinSpanReporter;
|
||||
import org.springframework.cloud.sleuth.zipkin.ZipkinProperties;
|
||||
import org.springframework.cloud.sleuth.zipkin.ZipkinSpanReporter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import zipkin.Span;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -24,6 +32,14 @@ public class GatewayApplication {
|
|||
|
||||
@Autowired(required = false)
|
||||
private List<RibbonClientSpecification> configurations = new ArrayList<>();
|
||||
@Autowired
|
||||
private EurekaClient eurekaClient;
|
||||
@Autowired
|
||||
private SpanMetricReporter spanMetricReporter;
|
||||
@Autowired
|
||||
private ZipkinProperties zipkinProperties;
|
||||
@Value("${spring.sleuth.web.skipPattern}")
|
||||
private String skipPattern;
|
||||
|
||||
@Bean
|
||||
@LoadBalanced
|
||||
|
@ -37,4 +53,23 @@ public class GatewayApplication {
|
|||
factory.setConfigurations(this.configurations);
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ZipkinSpanReporter makeZipkinSpanReporter() {
|
||||
return new ZipkinSpanReporter() {
|
||||
private HttpZipkinSpanReporter delegate;
|
||||
private String baseUrl;
|
||||
|
||||
@Override
|
||||
public void report(Span span) {
|
||||
InstanceInfo instance = eurekaClient.getNextServerFromEureka("zipkin", false);
|
||||
if (!(baseUrl != null && instance.getHomePageUrl().equals(baseUrl))) {
|
||||
baseUrl = instance.getHomePageUrl();
|
||||
delegate = new HttpZipkinSpanReporter(baseUrl, zipkinProperties.getFlushInterval(), zipkinProperties.getCompression().isEnabled(), spanMetricReporter);
|
||||
if (!span.name.matches(skipPattern)) delegate.report(span);
|
||||
}
|
||||
if (!span.name.matches(skipPattern)) delegate.report(span);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http.authorizeRequests()
|
||||
.antMatchers("/book-service/books").permitAll()
|
||||
.antMatchers("/zipkin/**").permitAll()
|
||||
.antMatchers("/eureka/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<module>gateway</module>
|
||||
<module>svc-book</module>
|
||||
<module>svc-rating</module>
|
||||
<module>zipkin</module>
|
||||
</modules>
|
||||
|
||||
|
||||
|
|
|
@ -53,6 +53,11 @@
|
|||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-zipkin</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue