Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
46b79202f7
@ -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");
|
||||
@ -36,15 +36,65 @@ public class SolrJavaIntegrationTest {
|
||||
assertEquals(docList.getNumFound(), 1);
|
||||
|
||||
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 {
|
||||
|
||||
|
1
pom.xml
1
pom.xml
@ -94,6 +94,7 @@
|
||||
<module>querydsl</module>
|
||||
|
||||
<!-- <module>raml</module> -->
|
||||
<module>reactor-core</module>
|
||||
<module>redis</module>
|
||||
<module>rest-assured</module>
|
||||
<module>rest-testing</module>
|
||||
|
59
reactor-core/pom.xml
Normal file
59
reactor-core/pom.xml
Normal file
@ -0,0 +1,59 @@
|
||||
<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>org.baeldung</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
|
||||
<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>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
<version>${reactor-core.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
<version>${assertj.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${logback.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<reactor-core.version>3.0.4.RELEASE</reactor-core.version>
|
||||
<junit.version>4.12</junit.version>
|
||||
<assertj.version>3.6.1</assertj.version>
|
||||
<logback.version>1.1.3</logback.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
122
reactor-core/src/test/java/com/baeldung/reactor/ReactorTest.java
Normal file
122
reactor-core/src/test/java/com/baeldung/reactor/ReactorTest.java
Normal file
@ -0,0 +1,122 @@
|
||||
package com.baeldung.reactor;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.reactivestreams.Subscriber;
|
||||
import org.reactivestreams.Subscription;
|
||||
import reactor.core.publisher.ConnectableFlux;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.scheduler.Schedulers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class ReactorTest {
|
||||
|
||||
@Test
|
||||
public void givenFlux_whenSubscribing_thenStream() throws InterruptedException {
|
||||
|
||||
List<Integer> elements = new ArrayList<>();
|
||||
|
||||
Flux.just(1, 2, 3, 4)
|
||||
.log()
|
||||
.map(i -> {
|
||||
System.out.println(i + ":" + Thread.currentThread());
|
||||
return i * 2;
|
||||
})
|
||||
.subscribe(elements::add);
|
||||
|
||||
assertThat(elements).containsExactly(2, 4, 6, 8);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFlux_whenZipping_thenCombine() {
|
||||
List<String> elements = new ArrayList<>();
|
||||
|
||||
Flux.just(1, 2, 3, 4)
|
||||
.log()
|
||||
.map(i -> i * 2)
|
||||
.zipWith(Flux.range(0, Integer.MAX_VALUE).log(), (two, one) -> String.format("First Flux: %d, Second Flux: %d", one, two))
|
||||
.subscribe(elements::add);
|
||||
|
||||
assertThat(elements).containsExactly(
|
||||
"First Flux: 0, Second Flux: 2",
|
||||
"First Flux: 1, Second Flux: 4",
|
||||
"First Flux: 2, Second Flux: 6",
|
||||
"First Flux: 3, Second Flux: 8");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFlux_whenApplyingBackPressure_thenPushElementsInBatches() throws InterruptedException {
|
||||
|
||||
List<Integer> elements = new ArrayList<>();
|
||||
|
||||
Flux.just(1, 2, 3, 4)
|
||||
.log()
|
||||
.map(i -> i * 2)
|
||||
.onBackpressureBuffer()
|
||||
.subscribe(new Subscriber<Integer>() {
|
||||
private Subscription s;
|
||||
int onNextAmount;
|
||||
|
||||
@Override
|
||||
public void onSubscribe(final Subscription s) {
|
||||
this.s = s;
|
||||
s.request(2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(final Integer integer) {
|
||||
elements.add(integer);
|
||||
onNextAmount++;
|
||||
if (onNextAmount % 2 == 0) {
|
||||
s.request(2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(final Throwable t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
int ham = 2;
|
||||
}
|
||||
});
|
||||
|
||||
assertThat(elements).containsExactly(2, 4, 6, 8);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFlux_whenInParallel_thenSubscribeInDifferentThreads() throws InterruptedException {
|
||||
List<String> threadNames = new ArrayList<>();
|
||||
|
||||
Flux.just(1, 2, 3, 4)
|
||||
.log()
|
||||
.map(i -> Thread.currentThread().getName())
|
||||
.subscribeOn(Schedulers.parallel())
|
||||
.subscribe(threadNames::add);
|
||||
|
||||
Thread.sleep(1000);
|
||||
|
||||
assertThat(threadNames).containsExactly("parallel-1", "parallel-1", "parallel-1", "parallel-1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenConnectableFlux_whenConnected_thenShouldStream() {
|
||||
|
||||
List<Integer> elements = new ArrayList<>();
|
||||
|
||||
final ConnectableFlux<Integer> publish = Flux.just(1, 2, 3, 4).publish();
|
||||
|
||||
publish.subscribe(elements::add);
|
||||
|
||||
assertThat(elements).isEmpty();
|
||||
|
||||
publish.connect();
|
||||
|
||||
assertThat(elements).containsExactly(1, 2, 3, 4);
|
||||
}
|
||||
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,13 @@
|
||||
package com.baeldung.relationships;
|
||||
|
||||
import com.baeldung.SpringDataRestApplication;
|
||||
import com.baeldung.models.Address;
|
||||
import com.baeldung.models.Author;
|
||||
import com.baeldung.models.Book;
|
||||
import com.baeldung.models.Library;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
@ -11,17 +19,7 @@ import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import com.baeldung.SpringDataRestApplication;
|
||||
import com.baeldung.models.Address;
|
||||
import com.baeldung.models.Author;
|
||||
import com.baeldung.models.Book;
|
||||
import com.baeldung.models.Library;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = SpringDataRestApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT)
|
||||
@ -48,7 +46,7 @@ public class SpringDataRelationshipsTest {
|
||||
|
||||
HttpHeaders requestHeaders = new HttpHeaders();
|
||||
requestHeaders.add("Content-type", "text/uri-list");
|
||||
HttpEntity<String> httpEntity = new HttpEntity<String>(ADDRESS_ENDPOINT + "/1", requestHeaders);
|
||||
HttpEntity<String> httpEntity = new HttpEntity<>(ADDRESS_ENDPOINT + "/1", requestHeaders);
|
||||
template.exchange(LIBRARY_ENDPOINT + "/1/libraryAddress", HttpMethod.PUT, httpEntity, String.class);
|
||||
|
||||
ResponseEntity<Library> libraryGetResponse = template.getForEntity(ADDRESS_ENDPOINT + "/1/library", Library.class);
|
||||
@ -69,7 +67,7 @@ public class SpringDataRelationshipsTest {
|
||||
|
||||
HttpHeaders requestHeaders = new HttpHeaders();
|
||||
requestHeaders.add("Content-type", "text/uri-list");
|
||||
HttpEntity<String> bookHttpEntity = new HttpEntity<String>(LIBRARY_ENDPOINT + "/1", requestHeaders);
|
||||
HttpEntity<String> bookHttpEntity = new HttpEntity<>(LIBRARY_ENDPOINT + "/1", requestHeaders);
|
||||
template.exchange(BOOK_ENDPOINT + "/1/library", HttpMethod.PUT, bookHttpEntity, String.class);
|
||||
template.exchange(BOOK_ENDPOINT + "/2/library", HttpMethod.PUT, bookHttpEntity, String.class);
|
||||
|
||||
@ -91,7 +89,7 @@ public class SpringDataRelationshipsTest {
|
||||
|
||||
HttpHeaders requestHeaders = new HttpHeaders();
|
||||
requestHeaders.add("Content-type", "text/uri-list");
|
||||
HttpEntity<String> httpEntity = new HttpEntity<String>(BOOK_ENDPOINT + "/1\n" + BOOK_ENDPOINT + "/2", requestHeaders);
|
||||
HttpEntity<String> httpEntity = new HttpEntity<>(BOOK_ENDPOINT + "/1\n" + BOOK_ENDPOINT + "/2", requestHeaders);
|
||||
template.exchange(AUTHOR_ENDPOINT + "/1/books", HttpMethod.PUT, httpEntity, String.class);
|
||||
|
||||
String jsonResponse = template.getForObject(BOOK_ENDPOINT + "/1/authors", String.class);
|
||||
|
@ -11,7 +11,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.4.4.RELEASE</version>
|
||||
<version>1.5.1.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
@ -74,6 +74,15 @@
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-rest</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
<version>1.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -0,0 +1,14 @@
|
||||
package org.baeldung.web.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
@Controller
|
||||
public class EmployeeController {
|
||||
|
||||
@RequestMapping(value = "/employeePage")
|
||||
public String getEmployeePage() {
|
||||
return "employee";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package org.baeldung.web.dao;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.baeldung.web.entity.Employee;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
|
||||
|
||||
@RepositoryRestResource(collectionResourceRel = "employee", path = "employees")
|
||||
public interface EmployeeCRUDRepository extends CrudRepository<Employee, Long> {
|
||||
List<Employee> findByName(@Param("name") String name);
|
||||
}
|
@ -3,6 +3,7 @@ package org.baeldung.web.dao;
|
||||
import org.baeldung.web.entity.Student;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface StudentRepository extends JpaRepository<Student, Long> {
|
||||
public interface StudentRepository extends JpaRepository<Student, Long>
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,57 @@
|
||||
package org.baeldung.web.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class Employee implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
private long id;
|
||||
|
||||
@Column(nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column(nullable = false)
|
||||
private Integer age;
|
||||
|
||||
public Employee() {
|
||||
}
|
||||
|
||||
public Employee(long id, String name, Integer age) {
|
||||
super();
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Integer getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(Integer age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package org.baeldung.web.main;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.ViewResolver;
|
||||
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@ComponentScan("org.baeldung.web.controller")
|
||||
public class MvcConfig extends WebMvcConfigurerAdapter{
|
||||
|
||||
public MvcConfig(){
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
|
||||
configurer.enable();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ViewResolver viewResolver() {
|
||||
final InternalResourceViewResolver bean = new InternalResourceViewResolver();
|
||||
|
||||
bean.setPrefix("/WEB-INF/pages/");
|
||||
bean.setSuffix(".html");
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
@ -2,7 +2,7 @@ package org.baeldung.web.main;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.boot.orm.jpa.EntityScan;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@ -26,7 +26,7 @@ public class PersistenceConfig {
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
|
||||
EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.HSQL).addScript("db/sql/data.sql").build();
|
||||
EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.HSQL).addScript("db/sql/data.sql").addScript("db/sql/employees.sql").build();
|
||||
return db;
|
||||
}
|
||||
|
||||
|
16
spring-rest-angular/src/main/resources/db/sql/employees.sql
Normal file
16
spring-rest-angular/src/main/resources/db/sql/employees.sql
Normal file
@ -0,0 +1,16 @@
|
||||
CREATE TABLE employee (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name VARCHAR(30),
|
||||
age INTEGER
|
||||
);
|
||||
|
||||
INSERT INTO employee (id,name,age)
|
||||
VALUES (1,'Bryan',20);
|
||||
INSERT INTO employee (id,name,age)
|
||||
VALUES (2,'Lisa',30);
|
||||
INSERT INTO employee (id,name,age)
|
||||
VALUES (3,'Laura',40);
|
||||
INSERT INTO employee (id,name,age)
|
||||
VALUES (4,'Alex',35);
|
||||
INSERT INTO employee (id,name,age)
|
||||
VALUES (5,'John',47);
|
@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html ng-app="app">
|
||||
<head>
|
||||
<meta charset="ISO-8859-1">
|
||||
<title>Employee CRUD</title>
|
||||
<script
|
||||
src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
|
||||
<script
|
||||
src="//cdn.rawgit.com/angular-ui/bower-ui-grid/master/ui-grid.min.js"></script>
|
||||
<script src="view/app.js"></script>
|
||||
<style>
|
||||
a {
|
||||
cursor: pointer;
|
||||
background-color: lightblue;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div ng-controller="EmployeeCRUDCtrl">
|
||||
<table>
|
||||
<tr>
|
||||
<td width="100">ID:</td>
|
||||
<td><input type="text" id="id" ng-model="employee.id" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100">Name:</td>
|
||||
<td><input type="text" id="name" ng-model="employee.name" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100">Age:</td>
|
||||
<td><input type="text" id="age" ng-model="employee.age" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br /> <br />
|
||||
<a ng-click="getEmployee(employee.id)">Get employee</a>
|
||||
<a ng-click="updateEmployee(employee.id,employee.name,employee.age)">Update employee</a>
|
||||
<a ng-click="addEmployee(employee.id,employee.name,employee.age)">Add employee</a>
|
||||
<a ng-click="deleteEmployee(employee.id)">Delete employee</a>
|
||||
|
||||
<br /> <br />
|
||||
<p style="color: green">{{message}}</p>
|
||||
<p style="color: red">{{errorMessage}}</p>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
<a ng-click="getAllEmployees()">Get all Employees</a><br /> <br />
|
||||
Name: <input type="text" id="name" ng-model="name" />
|
||||
<a ng-click="getEmployeesByName()">Get employees by name</a>
|
||||
<br /> <br />
|
||||
<div ng-repeat="emp in employees">
|
||||
{{emp.name}} {{emp.age}}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,5 +1,5 @@
|
||||
var app = angular.module('app', ['ui.grid','ui.grid.pagination']);
|
||||
|
||||
|
||||
app.controller('StudentCtrl', ['$scope','StudentService', function ($scope,StudentService) {
|
||||
var paginationOptions = {
|
||||
pageNumber: 1,
|
||||
@ -53,4 +53,146 @@ app.service('StudentService',['$http', function ($http) {
|
||||
getStudents:getStudents
|
||||
};
|
||||
|
||||
}]);
|
||||
|
||||
app.controller('EmployeeCRUDCtrl', ['$scope','EmployeeCRUDService', function ($scope,EmployeeCRUDService) {
|
||||
|
||||
$scope.updateEmployee = function () {
|
||||
EmployeeCRUDService.updateEmployee($scope.employee.id,$scope.employee.name,$scope.employee.age)
|
||||
.then(function success(response){
|
||||
$scope.message = 'Employee data updated!';
|
||||
$scope.errorMessage = '';
|
||||
},
|
||||
function error(response){
|
||||
$scope.errorMessage = 'Error updating Employee!';
|
||||
$scope.message = '';
|
||||
});
|
||||
}
|
||||
|
||||
$scope.getEmployee = function () {
|
||||
var id = $scope.employee.id;
|
||||
EmployeeCRUDService.getEmployee($scope.employee.id)
|
||||
.then(function success(response){
|
||||
$scope.employee = response.data;
|
||||
$scope.employee.id = id;
|
||||
$scope.message='';
|
||||
$scope.errorMessage = '';
|
||||
},
|
||||
function error (response ){
|
||||
$scope.message = '';
|
||||
if (response.status === 404){
|
||||
$scope.errorMessage = 'Employee not found!';
|
||||
}
|
||||
else {
|
||||
$scope.errorMessage = "Error getting Employee!";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$scope.addEmployee = function () {
|
||||
if ($scope.employee != null && $scope.employee.id) {
|
||||
EmployeeCRUDService.addEmployee($scope.employee.id, $scope.employee.name, $scope.employee.age)
|
||||
.then (function success(response){
|
||||
$scope.message = 'Employee added!';
|
||||
$scope.errorMessage = '';
|
||||
},
|
||||
function error(response){
|
||||
$scope.errorMessage = 'Error adding Employee!';
|
||||
$scope.message = '';
|
||||
});
|
||||
}
|
||||
else {
|
||||
$scope.errorMessage = 'Please enter an id!';
|
||||
$scope.message = '';
|
||||
}
|
||||
}
|
||||
|
||||
$scope.deleteEmployee = function () {
|
||||
EmployeeCRUDService.deleteEmployee($scope.employee.id)
|
||||
.then (function success(response){
|
||||
$scope.message = 'Employee deleted!';
|
||||
$scope.employee = null;
|
||||
$scope.errorMessage='';
|
||||
},
|
||||
function error(response){
|
||||
$scope.errorMessage = 'Error deleting Employee!';
|
||||
$scope.message='';
|
||||
})
|
||||
}
|
||||
|
||||
$scope.getAllEmployees = function () {
|
||||
EmployeeCRUDService.getAllEmployees()
|
||||
.then(function success(response){
|
||||
$scope.employees = response.data._embedded.employee;
|
||||
$scope.message='';
|
||||
$scope.errorMessage = '';
|
||||
},
|
||||
function error (response ){
|
||||
$scope.message='';
|
||||
$scope.errorMessage = 'Error getting Employees!';
|
||||
});
|
||||
}
|
||||
|
||||
$scope.getEmployeesByName = function () {
|
||||
EmployeeCRUDService.getEmployeesByName($scope.name)
|
||||
.then(function success(response){
|
||||
$scope.employees = response.data._embedded.employee;
|
||||
$scope.message='';
|
||||
$scope.errorMessage = '';
|
||||
},
|
||||
function error (response ){
|
||||
$scope.message='';
|
||||
$scope.errorMessage = 'Error getting Employees!';
|
||||
});
|
||||
}
|
||||
|
||||
}]);
|
||||
|
||||
app.service('EmployeeCRUDService',['$http', function ($http) {
|
||||
|
||||
this.getEmployee = function getEmployee(employeeId){
|
||||
return $http({
|
||||
method: 'GET',
|
||||
url:'employees/'+employeeId
|
||||
});
|
||||
}
|
||||
|
||||
this.addEmployee = function addEmployee(id, name, age, gender){
|
||||
return $http({
|
||||
method: 'POST',
|
||||
url:'employees',
|
||||
data: {id:id, name:name, age:age}
|
||||
});
|
||||
}
|
||||
|
||||
this.deleteEmployee = function deleteEmployee(id){
|
||||
return $http({
|
||||
method: 'DELETE',
|
||||
url: 'employees/'+id
|
||||
})
|
||||
}
|
||||
|
||||
this.updateEmployee = function updateEmployee(id,name,age){
|
||||
return $http({
|
||||
method: 'PATCH',
|
||||
url: 'employees/'+id,
|
||||
data: {name:name, age:age}
|
||||
})
|
||||
}
|
||||
|
||||
this.getAllEmployees = function getAllEmployees(){
|
||||
return $http({
|
||||
method: 'GET',
|
||||
url:'employees'
|
||||
});
|
||||
}
|
||||
|
||||
this.getEmployeesByName = function getEmployeesByName(name){
|
||||
return $http({
|
||||
method: 'GET',
|
||||
url:'employees/search/findByName',
|
||||
params:{name:name}
|
||||
});
|
||||
}
|
||||
|
||||
}]);
|
@ -0,0 +1,47 @@
|
||||
package org.baeldung.web.service;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.baeldung.web.entity.Employee;
|
||||
import org.baeldung.web.main.Application;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.DEFINED_PORT)
|
||||
public class EmployeeCRUDRepositoryIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private TestRestTemplate template;
|
||||
|
||||
private static final String EMPLOYEE_ENDPOINT = "http://localhost:8080/employees/";
|
||||
private static int EMPLOYEE_ID = 1;
|
||||
private static int EMPLOYEE_AGE = 25;
|
||||
|
||||
@Test
|
||||
public void whenEmployeeCRUDOperations_thenCorrect() {
|
||||
Employee Employee = new Employee(EMPLOYEE_ID, "Bryan", 20);
|
||||
ResponseEntity<Employee> postResponse = template.postForEntity(EMPLOYEE_ENDPOINT, Employee, Employee.class, "");
|
||||
assertEquals("status is not 201", HttpStatus.CREATED, postResponse.getStatusCode());
|
||||
|
||||
Employee.setAge(EMPLOYEE_AGE);
|
||||
Employee patchResponse = template.patchForObject(EMPLOYEE_ENDPOINT + "/" + EMPLOYEE_ID, Employee, Employee.class);
|
||||
assertEquals("age is not 25", Integer.valueOf(EMPLOYEE_AGE), patchResponse.getAge());
|
||||
|
||||
ResponseEntity<Employee> getResponse = template.getForEntity(EMPLOYEE_ENDPOINT + "/" + EMPLOYEE_ID, Employee.class, "");
|
||||
assertEquals("status is not 200", HttpStatus.OK, getResponse.getStatusCode());
|
||||
|
||||
template.delete(EMPLOYEE_ENDPOINT + "/" + EMPLOYEE_ID);
|
||||
|
||||
getResponse = template.getForEntity(EMPLOYEE_ENDPOINT + "/" + EMPLOYEE_ID, Employee.class, "");
|
||||
assertEquals("status is not 404", HttpStatus.NOT_FOUND, getResponse.getStatusCode());
|
||||
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user