Merge branch 'master' of https://github.com/eugenp/tutorials
This commit is contained in:
commit
60ef21fe3e
|
@ -0,0 +1,2 @@
|
|||
## Relevant articles:
|
||||
- [CAS SSO With Spring Security](http://www.baeldung.com/spring-security-cas-sso)
|
|
@ -14,7 +14,7 @@
|
|||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.0.BUILD-SNAPSHOT</version>
|
||||
<version>2.0.0.M7</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
|
@ -87,14 +87,6 @@
|
|||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
|
@ -106,14 +98,6 @@
|
|||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>spring-snapshots</id>
|
||||
<name>Spring Snapshots</name>
|
||||
<url>https://repo.spring.io/snapshot</url>
|
||||
<snapshots>
|
||||
<enabled>true</enabled>
|
||||
</snapshots>
|
||||
</pluginRepository>
|
||||
<pluginRepository>
|
||||
<id>spring-milestones</id>
|
||||
<name>Spring Milestones</name>
|
||||
|
|
|
@ -32,3 +32,4 @@
|
|||
- [“Stream has already been operated upon or closed” Exception in Java](http://www.baeldung.com/java-stream-operated-upon-or-closed-exception)
|
||||
- [Display All Time Zones With GMT And UTC in Java](http://www.baeldung.com/java-time-zones)
|
||||
- [Copy a File with Java](http://www.baeldung.com/java-copy-file)
|
||||
- [Generating Prime Numbers in Java](http://www.baeldung.com/java-generate-prime-numbers)
|
||||
|
|
|
@ -18,3 +18,4 @@
|
|||
- [How to Get All Dates Between Two Dates?](http://www.baeldung.com/java-between-dates)
|
||||
- [Java 9 java.util.Objects Additions](http://www.baeldung.com/java-9-objects-new)
|
||||
- [Compact Strings in Java 9](http://www.baeldung.com/java-9-compact-string)
|
||||
- [Convert Date to LocalDate or LocalDateTime and Back](http://www.baeldung.com/java-date-to-localdate-and-localdatetime)
|
||||
|
|
|
@ -31,3 +31,5 @@
|
|||
- [Overview of the java.util.concurrent](http://www.baeldung.com/java-util-concurrent)
|
||||
- [Semaphores in Java](http://www.baeldung.com/java-semaphore)
|
||||
- [Daemon Threads in Java](http://www.baeldung.com/java-daemon-thread)
|
||||
- [Implementing a Runnable vs Extending a Thread](http://www.baeldung.com/java-runnable-vs-extending-thread)
|
||||
- [How to Kill a Java Thread](http://www.baeldung.com/java-thread-stop)
|
||||
|
|
|
@ -121,4 +121,8 @@
|
|||
- [Copy a File with Java](http://www.baeldung.com/java-copy-file)
|
||||
- [Introduction to Creational Design Patterns](http://www.baeldung.com/creational-design-patterns)
|
||||
- [Quick Example - Comparator vs Comparable in Java](http://www.baeldung.com/java-comparator-comparable)
|
||||
|
||||
- [Quick Guide to Java Stack](http://www.baeldung.com/java-stack)
|
||||
- [The Java continue and break Keywords](http://www.baeldung.com/java-continue-and-break)
|
||||
- [Java – Append Data to a File](http://www.baeldung.com/java-append-to-file)
|
||||
- [Introduction to the Java ArrayDeque](http://www.baeldung.com/java-array-deque)
|
||||
- [Guide to java.util.Formatter](http://www.baeldung.com/java-string-formatter)
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package com.baeldung.array;
|
||||
|
||||
import org.openjdk.jmh.runner.Runner;
|
||||
import org.openjdk.jmh.runner.options.Options;
|
||||
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||
|
||||
public class ArrayBenchmarkRunner {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
Options options = new OptionsBuilder()
|
||||
.include(SearchArrayTest.class.getSimpleName()).threads(1)
|
||||
.forks(1).shouldFailOnError(true).shouldDoGC(true)
|
||||
.jvmArgs("-server").build();
|
||||
|
||||
new Runner(options).run();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.baeldung.array;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
public class ArrayInverter {
|
||||
|
||||
public void invertUsingFor(Object[] array) {
|
||||
for (int i = 0; i < array.length / 2; i++) {
|
||||
Object temp = array[i];
|
||||
array[i] = array[array.length - 1 - i];
|
||||
array[array.length - 1 - i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
public void invertUsingCollectionsReverse(Object[] array) {
|
||||
List<Object> list = Arrays.asList(array);
|
||||
Collections.reverse(list);
|
||||
}
|
||||
|
||||
public Object[] invertUsingStreams(final Object[] array) {
|
||||
return IntStream.range(1, array.length + 1).mapToObj(i -> array[array.length - i]).toArray();
|
||||
}
|
||||
|
||||
public void invertUsingCommonsLang(Object[] array) {
|
||||
ArrayUtils.reverse(array);
|
||||
}
|
||||
|
||||
public Object[] invertUsingGuava(Object[] array) {
|
||||
List<Object> list = Arrays.asList(array);
|
||||
List<Object> reverted = Lists.reverse(list);
|
||||
return reverted.toArray();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,78 +1,77 @@
|
|||
package com.baeldung.array;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.openjdk.jmh.annotations.*;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@BenchmarkMode(Mode.AverageTime)
|
||||
@Warmup(iterations = 5)
|
||||
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||
public class SearchArrayTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void searchArrayAllocNewCollections() {
|
||||
@Benchmark
|
||||
public void searchArrayLoop() {
|
||||
|
||||
int count = 1000;
|
||||
|
||||
String[] strings = seedArray(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
searchLoop(strings, "T");
|
||||
}
|
||||
}
|
||||
|
||||
long startTime = System.nanoTime();
|
||||
@Benchmark
|
||||
public void searchArrayAllocNewList() {
|
||||
|
||||
int count = 1000;
|
||||
String[] strings = seedArray(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
searchList(strings, "W");
|
||||
}
|
||||
long duration = System.nanoTime() - startTime;
|
||||
System.out.println("SearchList: " + duration / 10000);
|
||||
|
||||
startTime = System.nanoTime();
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
public void searchArrayAllocNewSet() {
|
||||
|
||||
int count = 1000;
|
||||
String[] strings = seedArray(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
searchSet(strings, "S");
|
||||
}
|
||||
duration = System.nanoTime() - startTime;
|
||||
System.out.println("SearchSet: " + duration / 10000);
|
||||
|
||||
startTime = System.nanoTime();
|
||||
for (int i = 0; i < count; i++) {
|
||||
searchLoop(strings, "T");
|
||||
}
|
||||
duration = System.nanoTime() - startTime;
|
||||
System.out.println("SearchLoop: " + duration / 10000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void searchArrayReuseCollections() {
|
||||
|
||||
int count = 10000;
|
||||
@Benchmark
|
||||
public void searchArrayReuseList() {
|
||||
|
||||
int count = 1000;
|
||||
String[] strings = seedArray(count);
|
||||
|
||||
List<String> asList = Arrays.asList(strings);
|
||||
Set<String> asSet = new HashSet<>(Arrays.asList(strings));
|
||||
|
||||
long startTime = System.nanoTime();
|
||||
for (int i = 0; i < count; i++) {
|
||||
asList.contains("W");
|
||||
}
|
||||
long duration = System.nanoTime() - startTime;
|
||||
System.out.println("List: " + duration / 10000);
|
||||
}
|
||||
|
||||
startTime = System.nanoTime();
|
||||
|
||||
@Benchmark
|
||||
public void searchArrayReuseSet() {
|
||||
|
||||
int count = 1000;
|
||||
String[] strings = seedArray(count);
|
||||
Set<String> asSet = new HashSet<>(Arrays.asList(strings));
|
||||
for (int i = 0; i < count; i++) {
|
||||
asSet.contains("S");
|
||||
}
|
||||
duration = System.nanoTime() - startTime;
|
||||
System.out.println("Set: " + duration / 10000);
|
||||
|
||||
startTime = System.nanoTime();
|
||||
for (int i = 0; i < count; i++) {
|
||||
searchLoop(strings, "T");
|
||||
}
|
||||
duration = System.nanoTime() - startTime;
|
||||
System.out.println("Loop: " + duration / 10000);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Benchmark
|
||||
public void searchArrayBinarySearch() {
|
||||
|
||||
int count = 10000;
|
||||
int count = 1000;
|
||||
String[] strings = seedArray(count);
|
||||
Arrays.sort(strings);
|
||||
|
||||
|
@ -81,7 +80,7 @@ public class SearchArrayTest {
|
|||
Arrays.binarySearch(strings, "A");
|
||||
}
|
||||
long duration = System.nanoTime() - startTime;
|
||||
System.out.println("Binary search: " + duration / 10000);
|
||||
//System.out.println("Binary search: " + duration / 10000);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.baeldung.interfaces;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class CommaSeparatedCustomers implements Customer.List {
|
||||
|
||||
private List<Customer> customers = new ArrayList<Customer>();
|
||||
|
||||
@Override
|
||||
public void Add(Customer customer) {
|
||||
customers.add(customer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCustomerNames() {
|
||||
return customers.stream().map(customer -> customer.getName()).collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.baeldung.interfaces;
|
||||
|
||||
public class Customer {
|
||||
public interface List {
|
||||
void Add(Customer customer);
|
||||
|
||||
String getCustomerNames();
|
||||
}
|
||||
|
||||
private String name;
|
||||
|
||||
public Customer(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
|
@ -54,7 +54,7 @@ public class GenericFile {
|
|||
}
|
||||
|
||||
public String getFileInfo() {
|
||||
return "File Name: " + this.getName() + "\n" + "Extension: " + this.getExtension() + "\n" + "Date Created: " + this.getDateCreated() + "\n" + "Version: " + this.getVersion() + "\n";
|
||||
return String.format("File Name: %s\n" + " Extension: %s\n" + " Date Created: %s\n" + " Version: %s\n", this.getName(), this.getExtension(), this.getDateCreated(), this.getVersion());
|
||||
}
|
||||
|
||||
public Object read() {
|
||||
|
|
|
@ -30,7 +30,7 @@ public class ImageFile extends GenericFile {
|
|||
}
|
||||
|
||||
public String getFileInfo() {
|
||||
return super.getFileInfo() + "Height: " + this.getHeight() + "\n" + "Width: " + this.getWidth();
|
||||
return String.format(" %s Height: %d\n Width: %d", super.getFileInfo(), this.getHeight(), this.getWidth());
|
||||
}
|
||||
|
||||
public String read() {
|
||||
|
|
|
@ -21,7 +21,7 @@ public class TextFile extends GenericFile {
|
|||
}
|
||||
|
||||
public String getFileInfo() {
|
||||
return super.getFileInfo() + "Word Count: " + wordCount;
|
||||
return String.format(" %s Word Count: %d", super.getFileInfo(), wordCount);
|
||||
}
|
||||
|
||||
public String read() {
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
package com.baeldung.tree;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
public class BinaryTree {
|
||||
|
||||
Node root;
|
||||
|
||||
public void add(int value) {
|
||||
|
||||
Node newNode = new Node(value);
|
||||
|
||||
if (root == null) {
|
||||
root = newNode;
|
||||
return;
|
||||
}
|
||||
|
||||
Node parent = root;
|
||||
Node current = root;
|
||||
|
||||
while (true) {
|
||||
|
||||
if (newNode.value < parent.value) {
|
||||
current = parent.left;
|
||||
|
||||
if (current == null) {
|
||||
parent.left = newNode;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
current = parent.right;
|
||||
|
||||
if (current == null) {
|
||||
parent.right = newNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
parent = current;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return root == null;
|
||||
}
|
||||
|
||||
public boolean containsNode(int value) {
|
||||
|
||||
Node current = root;
|
||||
|
||||
while (current != null) {
|
||||
|
||||
if (value == current.value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (value < current.value) {
|
||||
current = current.left;
|
||||
} else {
|
||||
current = current.right;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void delete(int value) {
|
||||
|
||||
Node current = root;
|
||||
Node parent = root;
|
||||
Node nodeToDelete = null;
|
||||
boolean isLeftChild = false;
|
||||
|
||||
while (nodeToDelete == null && current != null) {
|
||||
|
||||
if (value == current.value) {
|
||||
nodeToDelete = current;
|
||||
} else if (value < current.value) {
|
||||
parent = current;
|
||||
current = current.left;
|
||||
isLeftChild = true;
|
||||
} else {
|
||||
parent = current;
|
||||
current = current.right;
|
||||
isLeftChild = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (nodeToDelete == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Case 1: no children
|
||||
if (nodeToDelete.left == null && nodeToDelete.right == null) {
|
||||
if (nodeToDelete == root) {
|
||||
root = null;
|
||||
} else if (isLeftChild) {
|
||||
parent.left = null;
|
||||
} else {
|
||||
parent.right = null;
|
||||
}
|
||||
}
|
||||
// Case 2: only 1 child
|
||||
else if (nodeToDelete.right == null) {
|
||||
if (nodeToDelete == root) {
|
||||
root = nodeToDelete.left;
|
||||
} else if (isLeftChild) {
|
||||
parent.left = nodeToDelete.left;
|
||||
} else {
|
||||
parent.right = nodeToDelete.left;
|
||||
}
|
||||
} else if (nodeToDelete.left == null) {
|
||||
if (nodeToDelete == root) {
|
||||
root = nodeToDelete.right;
|
||||
} else if (isLeftChild) {
|
||||
parent.left = nodeToDelete.right;
|
||||
} else {
|
||||
parent.right = nodeToDelete.right;
|
||||
}
|
||||
}
|
||||
// Case 3: 2 children
|
||||
else if (nodeToDelete.left != null && nodeToDelete.right != null) {
|
||||
Node replacement = findReplacement(nodeToDelete);
|
||||
if (nodeToDelete == root) {
|
||||
root = replacement;
|
||||
} else if (isLeftChild) {
|
||||
parent.left = replacement;
|
||||
} else {
|
||||
parent.right = replacement;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Node findReplacement(Node nodeToDelete) {
|
||||
|
||||
Node replacement = nodeToDelete;
|
||||
Node parentReplacement = nodeToDelete;
|
||||
Node current = nodeToDelete.right;
|
||||
|
||||
while (current != null) {
|
||||
parentReplacement = replacement;
|
||||
replacement = current;
|
||||
current = current.left;
|
||||
}
|
||||
|
||||
if (replacement != nodeToDelete.right) {
|
||||
parentReplacement.left = replacement.right;
|
||||
replacement.right = nodeToDelete.right;
|
||||
}
|
||||
|
||||
replacement.left = nodeToDelete.left;
|
||||
|
||||
return replacement;
|
||||
}
|
||||
|
||||
public void traverseInOrder(Node node) {
|
||||
if (node != null) {
|
||||
traverseInOrder(node.left);
|
||||
System.out.print(" " + node.value);
|
||||
traverseInOrder(node.right);
|
||||
}
|
||||
}
|
||||
|
||||
public void traversePreOrder(Node node) {
|
||||
if (node != null) {
|
||||
System.out.print(" " + node.value);
|
||||
traversePreOrder(node.left);
|
||||
traversePreOrder(node.right);
|
||||
}
|
||||
}
|
||||
|
||||
public void traversePostOrder(Node node) {
|
||||
if (node != null) {
|
||||
traversePostOrder(node.left);
|
||||
traversePostOrder(node.right);
|
||||
|
||||
System.out.print(" " + node.value);
|
||||
}
|
||||
}
|
||||
|
||||
public void traverseLevelOrder() {
|
||||
Queue<Node> nodes = new LinkedList<>();
|
||||
nodes.add(root);
|
||||
|
||||
while (!nodes.isEmpty()) {
|
||||
|
||||
Node node = nodes.remove();
|
||||
|
||||
System.out.print(" " + node.value);
|
||||
|
||||
if (node.left != null) {
|
||||
nodes.add(node.left);
|
||||
}
|
||||
|
||||
if (node.left != null) {
|
||||
nodes.add(node.right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Node {
|
||||
int value;
|
||||
Node left;
|
||||
Node right;
|
||||
|
||||
Node(int value) {
|
||||
this.value = value;
|
||||
right = null;
|
||||
left = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package com.baeldung.array;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class ArrayInverterUnitTest {
|
||||
|
||||
private String[] fruits = { "apples", "tomatoes", "bananas", "guavas", "pineapples", "oranges" };
|
||||
|
||||
@Test
|
||||
public void invertArrayWithForLoop() {
|
||||
ArrayInverter inverter = new ArrayInverter();
|
||||
inverter.invertUsingFor(fruits);
|
||||
|
||||
assertThat(new String[] { "oranges", "pineapples", "guavas", "bananas", "tomatoes", "apples" }).isEqualTo(fruits);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invertArrayWithCollectionsReverse() {
|
||||
ArrayInverter inverter = new ArrayInverter();
|
||||
inverter.invertUsingCollectionsReverse(fruits);
|
||||
|
||||
assertThat(new String[] { "oranges", "pineapples", "guavas", "bananas", "tomatoes", "apples" }).isEqualTo(fruits);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invertArrayWithStreams() {
|
||||
ArrayInverter inverter = new ArrayInverter();
|
||||
|
||||
assertThat(new String[] { "oranges", "pineapples", "guavas", "bananas", "tomatoes", "apples" }).isEqualTo(inverter.invertUsingStreams(fruits));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invertArrayWithCommonsLang() {
|
||||
ArrayInverter inverter = new ArrayInverter();
|
||||
inverter.invertUsingCommonsLang(fruits);
|
||||
|
||||
assertThat(new String[] { "oranges", "pineapples", "guavas", "bananas", "tomatoes", "apples" }).isEqualTo(fruits);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invertArrayWithGuava() {
|
||||
ArrayInverter inverter = new ArrayInverter();
|
||||
|
||||
assertThat(new String[] { "oranges", "pineapples", "guavas", "bananas", "tomatoes", "apples" }).isEqualTo(inverter.invertUsingGuava(fruits));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.baeldung.interfaces;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.JUnit4;
|
||||
|
||||
@RunWith(JUnit4.class)
|
||||
public class InnerInterfaceTests {
|
||||
@Test
|
||||
public void whenCustomerListJoined_thenReturnsJoinedNames() {
|
||||
Customer.List customerList = new CommaSeparatedCustomers();
|
||||
customerList.Add(new Customer("customer1"));
|
||||
customerList.Add(new Customer("customer2"));
|
||||
assertEquals("customer1,customer2", customerList.getCustomerNames());
|
||||
}
|
||||
}
|
|
@ -14,9 +14,9 @@ public class NewOuter {
|
|||
public void run() {
|
||||
System.out.println("a = " + a);
|
||||
System.out.println("b = " + b);
|
||||
System.out.println("NewOuterTest.this.a = " + NewOuter.this.a);
|
||||
System.out.println("NewOuterTest.b = " + NewOuter.b);
|
||||
System.out.println("NewOuterTest.this.b = " + NewOuter.this.b);
|
||||
System.out.println("NewOuter.this.a = " + NewOuter.this.a);
|
||||
System.out.println("NewOuter.b = " + NewOuter.b);
|
||||
System.out.println("NewOuter.this.b = " + NewOuter.this.b);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@ package com.baeldung.polymorphism;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class PolymorphismUnitTest {
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
package com.baeldung.tree;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class BinaryTreeTest {
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenAddingElements_ThenTreeNotEmpty() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
assertTrue(!bt.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenAddingElements_ThenTreeContainsThoseElements() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
assertTrue(bt.containsNode(6));
|
||||
assertTrue(bt.containsNode(4));
|
||||
|
||||
assertFalse(bt.containsNode(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenDeletingElements_ThenTreeDoesNotContainThoseElements() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
assertTrue(bt.containsNode(9));
|
||||
bt.delete(9);
|
||||
assertFalse(bt.containsNode(9));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenTraversingInOrder_ThenPrintValues() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
bt.traverseInOrder(bt.root);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenTraversingPreOrder_ThenPrintValues() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
bt.traversePreOrder(bt.root);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenTraversingPostOrder_ThenPrintValues() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
bt.traversePostOrder(bt.root);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenABinaryTree_WhenTraversingLevelOrder_ThenPrintValues() {
|
||||
|
||||
BinaryTree bt = createBinaryTree();
|
||||
|
||||
bt.traverseLevelOrder();
|
||||
}
|
||||
|
||||
private BinaryTree createBinaryTree() {
|
||||
BinaryTree bt = new BinaryTree();
|
||||
|
||||
bt.add(6);
|
||||
bt.add(4);
|
||||
bt.add(8);
|
||||
bt.add(3);
|
||||
bt.add(5);
|
||||
bt.add(7);
|
||||
bt.add(9);
|
||||
|
||||
return bt;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
### Relevant Articles:
|
||||
- [Introduction to Drools](http://www.baeldung.com/drools)
|
||||
- [Drools Using Rules from Excel Files](http://www.baeldung.com/drools-excel)
|
||||
- [An Example of Backward Chaining in Drools](http://www.baeldung.com/drools-backward-chaining)
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
## Relevant articles:
|
||||
|
||||
- [Intro to Dubbo](http://www.baeldung.com/dubbo-intro)
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
<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>
|
||||
|
||||
<parent>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>dubbo</artifactId>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<dubbo.version>2.5.7</dubbo.version>
|
||||
<zookeeper.version>3.4.11</zookeeper.version>
|
||||
<zkclient.version>0.10</zkclient.version>
|
||||
<surefire.version>2.19.1</surefire.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>dubbo</artifactId>
|
||||
<version>${dubbo.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.zookeeper</groupId>
|
||||
<artifactId>zookeeper</artifactId>
|
||||
<version>${zookeeper.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.101tec</groupId>
|
||||
<artifactId>zkclient</artifactId>
|
||||
<version>${zkclient.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>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${surefire.version}</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/*LiveTest.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,210 @@
|
|||
/*
|
||||
* Copyright 1999-2011 Alibaba Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.alibaba.dubbo.registry.simple;
|
||||
|
||||
import com.alibaba.dubbo.common.Constants;
|
||||
import com.alibaba.dubbo.common.URL;
|
||||
import com.alibaba.dubbo.common.logger.Logger;
|
||||
import com.alibaba.dubbo.common.logger.LoggerFactory;
|
||||
import com.alibaba.dubbo.common.utils.ConcurrentHashSet;
|
||||
import com.alibaba.dubbo.common.utils.NetUtils;
|
||||
import com.alibaba.dubbo.common.utils.UrlUtils;
|
||||
import com.alibaba.dubbo.registry.NotifyListener;
|
||||
import com.alibaba.dubbo.registry.RegistryService;
|
||||
import com.alibaba.dubbo.registry.support.AbstractRegistry;
|
||||
import com.alibaba.dubbo.rpc.RpcContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* SimpleRegistryService
|
||||
*
|
||||
* @author william.liangf
|
||||
*/
|
||||
public class SimpleRegistryService extends AbstractRegistry {
|
||||
|
||||
private final static Logger logger = LoggerFactory.getLogger(SimpleRegistryService.class);
|
||||
private final ConcurrentMap<String, Set<URL>> remoteRegistered = new ConcurrentHashMap<String, Set<URL>>();
|
||||
private final ConcurrentMap<String, ConcurrentMap<URL, Set<NotifyListener>>> remoteSubscribed = new ConcurrentHashMap<String, ConcurrentMap<URL, Set<NotifyListener>>>();
|
||||
|
||||
public SimpleRegistryService() {
|
||||
super(new URL("dubbo", NetUtils.getLocalHost(), 0, RegistryService.class.getName(), "file", "N/A"));
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<URL> lookup(URL url) {
|
||||
List<URL> urls = new ArrayList<URL>();
|
||||
for (URL u : getRegistered()) {
|
||||
if (UrlUtils.isMatch(url, u)) {
|
||||
urls.add(u);
|
||||
}
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
public void register(URL url) {
|
||||
String client = RpcContext.getContext().getRemoteAddressString();
|
||||
Set<URL> urls = remoteRegistered.get(client);
|
||||
if (urls == null) {
|
||||
remoteRegistered.putIfAbsent(client, new ConcurrentHashSet<URL>());
|
||||
urls = remoteRegistered.get(client);
|
||||
}
|
||||
urls.add(url);
|
||||
super.register(url);
|
||||
registered(url);
|
||||
}
|
||||
|
||||
public void unregister(URL url) {
|
||||
String client = RpcContext.getContext().getRemoteAddressString();
|
||||
Set<URL> urls = remoteRegistered.get(client);
|
||||
if (urls != null && urls.size() > 0) {
|
||||
urls.remove(url);
|
||||
}
|
||||
super.unregister(url);
|
||||
unregistered(url);
|
||||
}
|
||||
|
||||
public void subscribe(URL url, NotifyListener listener) {
|
||||
if (getUrl().getPort() == 0) {
|
||||
URL registryUrl = RpcContext.getContext().getUrl();
|
||||
if (registryUrl != null && registryUrl.getPort() > 0
|
||||
&& RegistryService.class.getName().equals(registryUrl.getPath())) {
|
||||
super.setUrl(registryUrl);
|
||||
super.register(registryUrl);
|
||||
}
|
||||
}
|
||||
String client = RpcContext.getContext().getRemoteAddressString();
|
||||
ConcurrentMap<URL, Set<NotifyListener>> clientListeners = remoteSubscribed.get(client);
|
||||
if (clientListeners == null) {
|
||||
remoteSubscribed.putIfAbsent(client, new ConcurrentHashMap<URL, Set<NotifyListener>>());
|
||||
clientListeners = remoteSubscribed.get(client);
|
||||
}
|
||||
Set<NotifyListener> listeners = clientListeners.get(url);
|
||||
if (listeners == null) {
|
||||
clientListeners.putIfAbsent(url, new ConcurrentHashSet<NotifyListener>());
|
||||
listeners = clientListeners.get(url);
|
||||
}
|
||||
listeners.add(listener);
|
||||
super.subscribe(url, listener);
|
||||
subscribed(url, listener);
|
||||
}
|
||||
|
||||
public void unsubscribe(URL url, NotifyListener listener) {
|
||||
if (!Constants.ANY_VALUE.equals(url.getServiceInterface())
|
||||
&& url.getParameter(Constants.REGISTER_KEY, true)) {
|
||||
unregister(url);
|
||||
}
|
||||
String client = RpcContext.getContext().getRemoteAddressString();
|
||||
Map<URL, Set<NotifyListener>> clientListeners = remoteSubscribed.get(client);
|
||||
if (clientListeners != null && clientListeners.size() > 0) {
|
||||
Set<NotifyListener> listeners = clientListeners.get(url);
|
||||
if (listeners != null && listeners.size() > 0) {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void registered(URL url) {
|
||||
for (Map.Entry<URL, Set<NotifyListener>> entry : getSubscribed().entrySet()) {
|
||||
URL key = entry.getKey();
|
||||
if (UrlUtils.isMatch(key, url)) {
|
||||
List<URL> list = lookup(key);
|
||||
for (NotifyListener listener : entry.getValue()) {
|
||||
listener.notify(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void unregistered(URL url) {
|
||||
for (Map.Entry<URL, Set<NotifyListener>> entry : getSubscribed().entrySet()) {
|
||||
URL key = entry.getKey();
|
||||
if (UrlUtils.isMatch(key, url)) {
|
||||
List<URL> list = lookup(key);
|
||||
for (NotifyListener listener : entry.getValue()) {
|
||||
listener.notify(list);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void subscribed(final URL url, final NotifyListener listener) {
|
||||
if (Constants.ANY_VALUE.equals(url.getServiceInterface())) {
|
||||
new Thread(new Runnable() {
|
||||
public void run() {
|
||||
Map<String, List<URL>> map = new HashMap<String, List<URL>>();
|
||||
for (URL u : getRegistered()) {
|
||||
if (UrlUtils.isMatch(url, u)) {
|
||||
String service = u.getServiceInterface();
|
||||
List<URL> list = map.get(service);
|
||||
if (list == null) {
|
||||
list = new ArrayList<URL>();
|
||||
map.put(service, list);
|
||||
}
|
||||
list.add(u);
|
||||
}
|
||||
}
|
||||
for (List<URL> list : map.values()) {
|
||||
try {
|
||||
listener.notify(list);
|
||||
} catch (Throwable e) {
|
||||
logger.warn("Discard to notify " + url.getServiceKey() + " to listener " + listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, "DubboMonitorNotifier").start();
|
||||
} else {
|
||||
List<URL> list = lookup(url);
|
||||
try {
|
||||
listener.notify(list);
|
||||
} catch (Throwable e) {
|
||||
logger.warn("Discard to notify " + url.getServiceKey() + " to listener " + listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
String client = RpcContext.getContext().getRemoteAddressString();
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("Disconnected " + client);
|
||||
}
|
||||
Set<URL> urls = remoteRegistered.get(client);
|
||||
if (urls != null && urls.size() > 0) {
|
||||
for (URL url : urls) {
|
||||
unregister(url);
|
||||
}
|
||||
}
|
||||
Map<URL, Set<NotifyListener>> listeners = remoteSubscribed.get(client);
|
||||
if (listeners != null && listeners.size() > 0) {
|
||||
for (Map.Entry<URL, Set<NotifyListener>> entry : listeners.entrySet()) {
|
||||
URL url = entry.getKey();
|
||||
for (NotifyListener listener : entry.getValue()) {
|
||||
unsubscribe(url, listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.baeldung.dubbo.remote;
|
||||
|
||||
/**
|
||||
* @author aiet
|
||||
*/
|
||||
public class GreetingsFailoverServiceImpl implements GreetingsService {
|
||||
|
||||
@Override
|
||||
public String sayHi(String name) {
|
||||
System.out.println("failover implementation");
|
||||
return "hi, failover " + name;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.baeldung.dubbo.remote;
|
||||
|
||||
/**
|
||||
* @author aiet
|
||||
*/
|
||||
public interface GreetingsService {
|
||||
|
||||
String sayHi(String name);
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.baeldung.dubbo.remote;
|
||||
|
||||
/**
|
||||
* @author aiet
|
||||
*/
|
||||
public class GreetingsServiceImpl implements GreetingsService {
|
||||
|
||||
@Override
|
||||
public String sayHi(String name) {
|
||||
System.out.println("default implementation");
|
||||
return "hi, " + name;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.baeldung.dubbo.remote;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
/**
|
||||
* @author aiet
|
||||
*/
|
||||
public class GreetingsServiceSpecialImpl implements GreetingsService {
|
||||
|
||||
@Override
|
||||
public String sayHi(String name) {
|
||||
try {
|
||||
System.out.println("specially called");
|
||||
SECONDS.sleep(5);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return "hi, " + name;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package com.baeldung.dubbo;
|
||||
|
||||
import com.alibaba.dubbo.config.ApplicationConfig;
|
||||
import com.alibaba.dubbo.config.ReferenceConfig;
|
||||
import com.alibaba.dubbo.config.RegistryConfig;
|
||||
import com.alibaba.dubbo.config.ServiceConfig;
|
||||
import com.baeldung.dubbo.remote.GreetingsService;
|
||||
import com.baeldung.dubbo.remote.GreetingsServiceImpl;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* @author aiet
|
||||
*/
|
||||
public class APIConfigurationLiveTest {
|
||||
|
||||
@Before
|
||||
public void initProvider() {
|
||||
ApplicationConfig application = new ApplicationConfig();
|
||||
application.setName("demo-provider");
|
||||
application.setVersion("1.0");
|
||||
|
||||
RegistryConfig registryConfig = new RegistryConfig();
|
||||
registryConfig.setAddress("multicast://224.1.1.1:9090");
|
||||
|
||||
ServiceConfig<GreetingsService> service = new ServiceConfig<>();
|
||||
service.setApplication(application);
|
||||
service.setRegistry(registryConfig);
|
||||
service.setInterface(GreetingsService.class);
|
||||
service.setRef(new GreetingsServiceImpl());
|
||||
|
||||
service.export();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenProviderConsumer_whenSayHi_thenGotResponse() {
|
||||
ApplicationConfig application = new ApplicationConfig();
|
||||
application.setName("demo-consumer");
|
||||
application.setVersion("1.0");
|
||||
|
||||
RegistryConfig registryConfig = new RegistryConfig();
|
||||
registryConfig.setAddress("multicast://224.1.1.1:9090");
|
||||
|
||||
ReferenceConfig<GreetingsService> reference = new ReferenceConfig<>();
|
||||
reference.setApplication(application);
|
||||
reference.setRegistry(registryConfig);
|
||||
reference.setInterface(GreetingsService.class);
|
||||
|
||||
GreetingsService greetingsService = reference.get();
|
||||
String hiMessage = greetingsService.sayHi("baeldung");
|
||||
|
||||
assertEquals("hi, baeldung", hiMessage);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package com.baeldung.dubbo;
|
||||
|
||||
import com.baeldung.dubbo.remote.GreetingsService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.OptionalDouble;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author aiet
|
||||
*/
|
||||
public class ClusterDynamicLoadBalanceLiveTest {
|
||||
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Before
|
||||
public void initRemote() {
|
||||
executorService = Executors.newFixedThreadPool(2);
|
||||
executorService.submit(() -> {
|
||||
ClassPathXmlApplicationContext remoteContext = new ClassPathXmlApplicationContext("cluster/provider-app-default.xml");
|
||||
remoteContext.start();
|
||||
});
|
||||
executorService.submit(() -> {
|
||||
SECONDS.sleep(2);
|
||||
ClassPathXmlApplicationContext backupRemoteContext = new ClassPathXmlApplicationContext("cluster/provider-app-special.xml");
|
||||
backupRemoteContext.start();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenProviderCluster_whenConsumerSaysHi_thenResponseBalanced() throws InterruptedException {
|
||||
ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext("cluster/consumer-app-lb.xml");
|
||||
localContext.start();
|
||||
GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
|
||||
List<Long> elapseList = new ArrayList<>(6);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
long current = System.currentTimeMillis();
|
||||
String hiMessage = greetingsService.sayHi("baeldung");
|
||||
assertNotNull(hiMessage);
|
||||
elapseList.add(System.currentTimeMillis() - current);
|
||||
SECONDS.sleep(1);
|
||||
}
|
||||
|
||||
OptionalDouble avgElapse = elapseList
|
||||
.stream()
|
||||
.mapToLong(e -> e)
|
||||
.average();
|
||||
assertTrue(avgElapse.isPresent());
|
||||
assertTrue(avgElapse.getAsDouble() > 1666.0);
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void destroy() {
|
||||
executorService.shutdown();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package com.baeldung.dubbo;
|
||||
|
||||
import com.baeldung.dubbo.remote.GreetingsService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author aiet
|
||||
*/
|
||||
public class ClusterFailoverLiveTest {
|
||||
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Before
|
||||
public void initRemote() {
|
||||
executorService = Executors.newFixedThreadPool(2);
|
||||
executorService.submit(() -> {
|
||||
ClassPathXmlApplicationContext backupRemoteContext = new ClassPathXmlApplicationContext("cluster/provider-app-special.xml");
|
||||
backupRemoteContext.start();
|
||||
});
|
||||
executorService.submit(() -> {
|
||||
ClassPathXmlApplicationContext remoteContext = new ClassPathXmlApplicationContext("cluster/provider-app-failover.xml");
|
||||
remoteContext.start();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenProviderCluster_whenConsumerSaysHi_thenGotFailoverResponse() {
|
||||
ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext("cluster/consumer-app-failtest.xml");
|
||||
localContext.start();
|
||||
GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
|
||||
String hiMessage = greetingsService.sayHi("baeldung");
|
||||
|
||||
assertNotNull(hiMessage);
|
||||
assertEquals("hi, failover baeldung", hiMessage);
|
||||
}
|
||||
|
||||
@After
|
||||
public void destroy() {
|
||||
executorService.shutdown();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.baeldung.dubbo;
|
||||
|
||||
import com.baeldung.dubbo.remote.GreetingsService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* @author aiet
|
||||
*/
|
||||
public class ClusterFailsafeLiveTest {
|
||||
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Before
|
||||
public void initRemote() {
|
||||
executorService = Executors.newFixedThreadPool(1);
|
||||
executorService.submit(() -> {
|
||||
ClassPathXmlApplicationContext remoteContext = new ClassPathXmlApplicationContext("cluster/provider-app-special-failsafe.xml");
|
||||
remoteContext.start();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenProviderCluster_whenConsumerSaysHi_thenGotFailsafeResponse() {
|
||||
ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext("cluster/consumer-app-failtest.xml");
|
||||
localContext.start();
|
||||
GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
|
||||
String hiMessage = greetingsService.sayHi("baeldung");
|
||||
|
||||
assertNull(hiMessage);
|
||||
}
|
||||
|
||||
@After
|
||||
public void destroy() {
|
||||
executorService.shutdown();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package com.baeldung.dubbo;
|
||||
|
||||
import com.baeldung.dubbo.remote.GreetingsService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.OptionalDouble;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author aiet
|
||||
*/
|
||||
public class ClusterLoadBalanceLiveTest {
|
||||
|
||||
private ExecutorService executorService;
|
||||
|
||||
@Before
|
||||
public void initRemote() {
|
||||
executorService = Executors.newFixedThreadPool(2);
|
||||
executorService.submit(() -> {
|
||||
ClassPathXmlApplicationContext remoteContext = new ClassPathXmlApplicationContext("cluster/provider-app-default.xml");
|
||||
remoteContext.start();
|
||||
});
|
||||
executorService.submit(() -> {
|
||||
ClassPathXmlApplicationContext backupRemoteContext = new ClassPathXmlApplicationContext("cluster/provider-app-special.xml");
|
||||
backupRemoteContext.start();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenProviderCluster_whenConsumerSaysHi_thenResponseBalanced() {
|
||||
ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext("cluster/consumer-app-lb.xml");
|
||||
localContext.start();
|
||||
GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
|
||||
List<Long> elapseList = new ArrayList<>(6);
|
||||
for (int i = 0; i < 6; i++) {
|
||||
long current = System.currentTimeMillis();
|
||||
String hiMessage = greetingsService.sayHi("baeldung");
|
||||
assertNotNull(hiMessage);
|
||||
elapseList.add(System.currentTimeMillis() - current);
|
||||
}
|
||||
|
||||
OptionalDouble avgElapse = elapseList
|
||||
.stream()
|
||||
.mapToLong(e -> e)
|
||||
.average();
|
||||
assertTrue(avgElapse.isPresent());
|
||||
System.out.println(avgElapse.getAsDouble());
|
||||
assertTrue(avgElapse.getAsDouble() > 2500.0);
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void destroy() {
|
||||
executorService.shutdown();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.baeldung.dubbo;
|
||||
|
||||
import com.baeldung.dubbo.remote.GreetingsService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author aiet
|
||||
*/
|
||||
public class MulticastRegistryLiveTest {
|
||||
|
||||
private ClassPathXmlApplicationContext remoteContext;
|
||||
|
||||
@Before
|
||||
public void initRemote() {
|
||||
remoteContext = new ClassPathXmlApplicationContext("multicast/provider-app.xml");
|
||||
remoteContext.start();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenProvider_whenConsumerSaysHi_thenGotResponse() {
|
||||
ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext("multicast/consumer-app.xml");
|
||||
localContext.start();
|
||||
GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
|
||||
String hiMessage = greetingsService.sayHi("baeldung");
|
||||
|
||||
assertNotNull(hiMessage);
|
||||
assertEquals("hi, baeldung", hiMessage);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.baeldung.dubbo;
|
||||
|
||||
import com.baeldung.dubbo.remote.GreetingsService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author aiet
|
||||
*/
|
||||
public class ResultCacheLiveTest {
|
||||
|
||||
private ClassPathXmlApplicationContext remoteContext;
|
||||
|
||||
@Before
|
||||
public void initRemote() {
|
||||
remoteContext = new ClassPathXmlApplicationContext("multicast/provider-app-special.xml");
|
||||
remoteContext.start();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenProvider_whenConsumerSaysHi_thenGotResponse() {
|
||||
ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext("multicast/consumer-app.xml");
|
||||
localContext.start();
|
||||
GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
|
||||
|
||||
long before = System.currentTimeMillis();
|
||||
String hiMessage = greetingsService.sayHi("baeldung");
|
||||
|
||||
long timeElapsed = System.currentTimeMillis() - before;
|
||||
assertTrue(timeElapsed > 5000);
|
||||
assertNotNull(hiMessage);
|
||||
assertEquals("hi, baeldung", hiMessage);
|
||||
|
||||
|
||||
before = System.currentTimeMillis();
|
||||
hiMessage = greetingsService.sayHi("baeldung");
|
||||
timeElapsed = System.currentTimeMillis() - before;
|
||||
assertTrue(timeElapsed < 1000);
|
||||
assertNotNull(hiMessage);
|
||||
assertEquals("hi, baeldung", hiMessage);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.baeldung.dubbo;
|
||||
|
||||
import com.baeldung.dubbo.remote.GreetingsService;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author aiet
|
||||
*/
|
||||
public class SimpleRegistryLiveTest {
|
||||
|
||||
private ClassPathXmlApplicationContext remoteContext;
|
||||
private ClassPathXmlApplicationContext registryContext;
|
||||
|
||||
@Before
|
||||
public void initRemote() {
|
||||
registryContext = new ClassPathXmlApplicationContext("simple/registry.xml");
|
||||
registryContext.start();
|
||||
|
||||
remoteContext = new ClassPathXmlApplicationContext("simple/provider-app.xml");
|
||||
remoteContext.start();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenProvider_whenConsumerSaysHi_thenGotResponse() {
|
||||
ClassPathXmlApplicationContext localContext = new ClassPathXmlApplicationContext("simple/consumer-app.xml");
|
||||
localContext.start();
|
||||
GreetingsService greetingsService = (GreetingsService) localContext.getBean("greetingsService");
|
||||
String hiMessage = greetingsService.sayHi("baeldung");
|
||||
|
||||
assertNotNull(hiMessage);
|
||||
assertEquals("hi, baeldung", hiMessage);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
|
||||
|
||||
<!-- provider application meta -->
|
||||
<dubbo:application name="demo-consumer" version="1.0"/>
|
||||
|
||||
<!-- address used to expose provider's service -->
|
||||
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
|
||||
|
||||
<!-- remote service proxy, acting like a local bean while invoking -->
|
||||
<dubbo:reference interface="com.baeldung.dubbo.remote.GreetingsService" id="greetingsService" retries="2" timeout="2000" />
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
|
||||
|
||||
<!-- provider application meta -->
|
||||
<dubbo:application name="demo-consumer" version="1.0"/>
|
||||
|
||||
<!-- address used to expose provider's service -->
|
||||
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
|
||||
|
||||
<!-- remote service proxy, acting like a local bean while invoking -->
|
||||
<dubbo:reference interface="com.baeldung.dubbo.remote.GreetingsService" id="greetingsService" retries="2" timeout="10000" loadbalance="roundrobin" />
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
|
||||
|
||||
<!-- provider application meta -->
|
||||
<dubbo:application name="demo-provider" version="1.0"/>
|
||||
|
||||
<!-- address used to expose provider's service -->
|
||||
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
|
||||
|
||||
<!-- protocol and port used to expose service -->
|
||||
<dubbo:protocol name="dubbo" port="20880"/>
|
||||
|
||||
<!-- the service interface to expose -->
|
||||
<dubbo:service interface="com.baeldung.dubbo.remote.GreetingsService" ref="greetingsService" cluster="failsafe"/>
|
||||
|
||||
<!-- declare the local implementation of exposed service interface -->
|
||||
<bean id="greetingsService" class="com.baeldung.dubbo.remote.GreetingsServiceImpl"/>
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
|
||||
|
||||
<!-- provider application meta -->
|
||||
<dubbo:application name="demo-provider" version="1.0"/>
|
||||
|
||||
<!-- address used to expose provider's service -->
|
||||
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
|
||||
|
||||
<!-- protocol and port used to expose service -->
|
||||
<dubbo:protocol name="dubbo" port="20880"/>
|
||||
|
||||
<!-- the service interface to expose -->
|
||||
<dubbo:service interface="com.baeldung.dubbo.remote.GreetingsService" ref="greetingsService" cluster="failover"/>
|
||||
|
||||
<!-- declare the local implementation of exposed service interface -->
|
||||
<bean id="greetingsService" class="com.baeldung.dubbo.remote.GreetingsFailoverServiceImpl"/>
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
|
||||
|
||||
<!-- provider application meta -->
|
||||
<dubbo:application name="demo-provider" version="1.0"/>
|
||||
|
||||
<!-- address used to expose provider's service -->
|
||||
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
|
||||
|
||||
<!-- protocol and port used to expose service -->
|
||||
<dubbo:protocol name="dubbo" port="20881" />
|
||||
|
||||
<!-- the service interface to expose -->
|
||||
<dubbo:service interface="com.baeldung.dubbo.remote.GreetingsService" ref="greetingsService" cluster="failsafe"/>
|
||||
|
||||
<!-- declare the local implementation of exposed service interface -->
|
||||
<bean id="greetingsService" class="com.baeldung.dubbo.remote.GreetingsServiceSpecialImpl"/>
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
|
||||
|
||||
<!-- provider application meta -->
|
||||
<dubbo:application name="demo-provider" version="1.0"/>
|
||||
|
||||
<!-- address used to expose provider's service -->
|
||||
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
|
||||
|
||||
<!-- protocol and port used to expose service -->
|
||||
<dubbo:protocol name="dubbo" port="20881" />
|
||||
|
||||
<!-- the service interface to expose -->
|
||||
<dubbo:service interface="com.baeldung.dubbo.remote.GreetingsService" ref="greetingsService" cluster="failover"/>
|
||||
|
||||
<!-- declare the local implementation of exposed service interface -->
|
||||
<bean id="greetingsService" class="com.baeldung.dubbo.remote.GreetingsServiceSpecialImpl"/>
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,6 @@
|
|||
log4j.rootLogger=INFO, stdout
|
||||
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.Target=System.out
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
|
||||
|
||||
<!-- provider application meta -->
|
||||
<dubbo:application name="demo-consumer" version="1.0"/>
|
||||
|
||||
<!-- address used to expose provider's service -->
|
||||
<dubbo:registry address="multicast://224.1.1.1:9090"/>
|
||||
|
||||
<!-- remote service proxy, acting like a local bean while invoking -->
|
||||
<dubbo:reference interface="com.baeldung.dubbo.remote.GreetingsService" id="greetingsService" cache="lru" />
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
|
||||
|
||||
<!-- provider application meta -->
|
||||
<dubbo:application name="demo-provider" version="1.0"/>
|
||||
|
||||
<!-- address used to expose provider's service -->
|
||||
<dubbo:registry address="multicast://224.1.1.1:9090"/>
|
||||
|
||||
<!-- protocol and port used to expose service -->
|
||||
<dubbo:protocol name="dubbo" port="20881" />
|
||||
|
||||
<!-- the service interface to expose -->
|
||||
<dubbo:service interface="com.baeldung.dubbo.remote.GreetingsService" ref="greetingsService"/>
|
||||
|
||||
<!-- declare the local implementation of exposed service interface -->
|
||||
<bean id="greetingsService" class="com.baeldung.dubbo.remote.GreetingsServiceSpecialImpl"/>
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
|
||||
|
||||
<!-- provider application meta -->
|
||||
<dubbo:application name="demo-provider" version="1.0"/>
|
||||
|
||||
<!-- address used to expose provider's service -->
|
||||
<dubbo:registry address="multicast://224.1.1.1:9090"/>
|
||||
|
||||
<!-- protocol and port used to expose service -->
|
||||
<dubbo:protocol name="dubbo" port="20880"/>
|
||||
|
||||
<!-- the service interface to expose -->
|
||||
<dubbo:service interface="com.baeldung.dubbo.remote.GreetingsService" ref="greetingsService"/>
|
||||
|
||||
<!-- declare the local implementation of exposed service interface -->
|
||||
<bean id="greetingsService" class="com.baeldung.dubbo.remote.GreetingsServiceImpl"/>
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
|
||||
|
||||
<!-- provider application meta -->
|
||||
<dubbo:application name="demo-consumer" version="1.0"/>
|
||||
|
||||
<!-- address used to expose provider's service -->
|
||||
<dubbo:registry address="127.0.0.1:9090"/>
|
||||
|
||||
<!-- remote service proxy, acting like a local bean while invoking -->
|
||||
<dubbo:reference interface="com.baeldung.dubbo.remote.GreetingsService" id="greetingsService" cluster="failover" retries="2"/>
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
|
||||
|
||||
<!-- provider application meta -->
|
||||
<dubbo:application name="demo-provider" version="1.0"/>
|
||||
|
||||
<!-- address used to expose provider's service -->
|
||||
<dubbo:registry address="127.0.0.1:9090"/>
|
||||
|
||||
<!-- protocol and port used to expose service -->
|
||||
<dubbo:protocol name="dubbo" port="20880"/>
|
||||
|
||||
<!-- the service interface to expose -->
|
||||
<dubbo:service interface="com.baeldung.dubbo.remote.GreetingsService" ref="greetingsService"/>
|
||||
|
||||
<!-- declare the local implementation of exposed service interface -->
|
||||
<bean id="greetingsService" class="com.baeldung.dubbo.remote.GreetingsServiceImpl"/>
|
||||
|
||||
</beans>
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
|
||||
|
||||
<dubbo:application name="simple-registry" />
|
||||
|
||||
<dubbo:protocol port="9090" />
|
||||
|
||||
<dubbo:service interface="com.alibaba.dubbo.registry.RegistryService" ref="registryService" registry="N/A" ondisconnect="disconnect">
|
||||
<dubbo:method name="subscribe"><dubbo:argument index="1" callback="true" /></dubbo:method>
|
||||
<dubbo:method name="unsubscribe"><dubbo:argument index="1" callback="true" /></dubbo:method>
|
||||
</dubbo:service>
|
||||
|
||||
<bean id="registryService" class="com.alibaba.dubbo.registry.simple.SimpleRegistryService" />
|
||||
|
||||
</beans>
|
|
@ -1,10 +1,10 @@
|
|||
<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>flyway</artifactId>
|
||||
<version>1.0</version>
|
||||
<name>flyway</name>
|
||||
<packaging>pom</packaging>
|
||||
<description>A sample project to demonstrate Flyway migrations</description>
|
||||
|
||||
<parent>
|
||||
|
@ -13,6 +13,10 @@
|
|||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modules>
|
||||
<module>spring-flyway</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
|
@ -20,6 +24,17 @@
|
|||
<version>${mysql.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
@ -32,5 +47,6 @@
|
|||
<properties>
|
||||
<mysql.version>6.0.5</mysql.version>
|
||||
<flyway-maven-plugin.version>4.0.3</flyway-maven-plugin.version>
|
||||
<spring.boot.version>1.5.8.RELEASE</spring.boot.version>
|
||||
</properties>
|
||||
</project>
|
|
@ -0,0 +1,24 @@
|
|||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
nbproject/private/
|
||||
build/
|
||||
nbbuild/
|
||||
dist/
|
||||
nbdist/
|
||||
.nb-gradle/
|
|
@ -0,0 +1,57 @@
|
|||
<?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>
|
||||
|
||||
<artifactId>spring-flyway</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>spring-flyway</name>
|
||||
<description>Spring Boot Test Flyway Migrations</description>
|
||||
|
||||
<parent>
|
||||
<artifactId>flyway</artifactId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<version>1.0</version>
|
||||
<relativePath>../../flyway</relativePath>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</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>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,12 @@
|
|||
package com.baeldung.springflyway;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SpringFlywayApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(SpringFlywayApplication.class, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.baeldung.springflyway.entities;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class Customer {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
|
||||
private String email;
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package com.baeldung.springflyway.migration;
|
||||
|
||||
import org.flywaydb.core.api.migration.spring.SpringJdbcMigration;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
public class V2__uk_lastname_customer implements SpringJdbcMigration {
|
||||
|
||||
final String CUSTOMER_LASTNAME_UK = "ALTER TABLE customer ADD CONSTRAINT uk_customer_lastname UNIQUE(last_name);";
|
||||
|
||||
@Override
|
||||
public void migrate(final JdbcTemplate jdbcTemplate) throws Exception {
|
||||
jdbcTemplate.execute(CUSTOMER_LASTNAME_UK);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.baeldung.springflyway.repositories;
|
||||
|
||||
import com.baeldung.springflyway.entities.Customer;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface CustomerRepository extends JpaRepository<Customer, Long> {
|
||||
|
||||
Optional<Customer> findByEmail(String email);
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.baeldung.springflyway;
|
||||
|
||||
import com.baeldung.springflyway.entities.Customer;
|
||||
import com.baeldung.springflyway.repositories.CustomerRepository;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class CustomerRepositoryInitialMigrationTest {
|
||||
|
||||
@Autowired CustomerRepository customerRepository;
|
||||
|
||||
@Test
|
||||
public void givenSchemaCreationMigration_whenTryingToCreateACustomer_thenSuccess() {
|
||||
Customer customer = customerRepository.save(Customer
|
||||
.builder()
|
||||
.email("customer@email.com")
|
||||
.build());
|
||||
assertNotNull(customer.getId());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.baeldung.springflyway;
|
||||
|
||||
import com.baeldung.springflyway.entities.Customer;
|
||||
import com.baeldung.springflyway.repositories.CustomerRepository;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class CustomerRepositoryInsertDataMigrationTest {
|
||||
|
||||
@Autowired CustomerRepository customerRepository;
|
||||
|
||||
@Test
|
||||
public void givenASetInsertData_whenRunningMigrationsWithSuccess_thenASpecificCustomerIsFound() {
|
||||
Optional<Customer> customerOptional = customerRepository.findByEmail("email@email.com");
|
||||
assertTrue(customerOptional.isPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenASetInsertData_whenRunningMigrationsWithSuccess_thenASetOfCustomersIsFound() {
|
||||
List<Customer> customers = customerRepository.findAll();
|
||||
assertNotNull(customers);
|
||||
assertEquals(customers.size(), 6);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.baeldung.springflyway;
|
||||
|
||||
import com.baeldung.springflyway.entities.Customer;
|
||||
import com.baeldung.springflyway.repositories.CustomerRepository;
|
||||
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.dao.DataIntegrityViolationException;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class CustomerRepositoryNotNullConstraintMigrationTest {
|
||||
|
||||
@Autowired CustomerRepository customerRepository;
|
||||
|
||||
@Test(expected = DataIntegrityViolationException.class)
|
||||
public void givenTheNotNullConstraintMigrations_whenInsertingACustomerWithNullEmail_thenThrowException() {
|
||||
customerRepository.save(Customer
|
||||
.builder()
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.baeldung.springflyway;
|
||||
|
||||
import com.baeldung.springflyway.entities.Customer;
|
||||
import com.baeldung.springflyway.repositories.CustomerRepository;
|
||||
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.dao.DataIntegrityViolationException;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(properties = {
|
||||
"flyway.locations[0]=db/migration", "flyway.locations[1]=com/baeldung/springflyway/migration"
|
||||
})
|
||||
public class CustomerRepositoryUniqueConstraintJavaMigrationTest {
|
||||
|
||||
@Autowired CustomerRepository customerRepository;
|
||||
|
||||
@Test(expected = DataIntegrityViolationException.class)
|
||||
public void givenTheUniqueConstraintMigrations_whenInsertingAnExistingLastNameCustomer_thenThrowException() {
|
||||
customerRepository.save(Customer
|
||||
.builder()
|
||||
.lastName("LastName")
|
||||
.build());
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.baeldung.springflyway;
|
||||
|
||||
import com.baeldung.springflyway.entities.Customer;
|
||||
import com.baeldung.springflyway.repositories.CustomerRepository;
|
||||
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.dao.DataIntegrityViolationException;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class CustomerRepositoryUniqueConstraintMigrationTest {
|
||||
|
||||
@Autowired CustomerRepository customerRepository;
|
||||
|
||||
@Test(expected = DataIntegrityViolationException.class)
|
||||
public void givenTheUniqueConstraintMigrations_whenInsertingAnExistingEmailCustomer_thenThrowException() {
|
||||
customerRepository.save(Customer
|
||||
.builder()
|
||||
.email("email@email.com")
|
||||
.build());
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
spring.jpa.hibernate.ddl-auto=validate
|
|
@ -0,0 +1,6 @@
|
|||
create table if not exists customer (
|
||||
id bigint AUTO_INCREMENT not null primary key,
|
||||
first_name varchar(255) ,
|
||||
last_name varchar(255) ,
|
||||
email varchar(255)
|
||||
);
|
|
@ -0,0 +1,6 @@
|
|||
insert into customer (first_name, last_name, email) values ('FirstName', 'LastName', 'email@email.com');
|
||||
insert into customer (first_name, last_name, email) values ('FirstName1', 'LastName1', 'email1@email.com');
|
||||
insert into customer (first_name, last_name, email) values ('FirstName2', 'LastName2', 'email2@email.com');
|
||||
insert into customer (first_name, last_name, email) values ('FirstName3', 'LastName3', 'email3@email.com');
|
||||
insert into customer (first_name, last_name, email) values ('FirstName4', 'LastName4', 'email4@email.com');
|
||||
insert into customer (first_name, last_name, email) values ('FirstName5', 'LastName5', 'email5@email.com');
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE customer ALTER email SET NOT NULL;
|
|
@ -0,0 +1 @@
|
|||
ALTER TABLE customer ADD CONSTRAINT uk_customer_email UNIQUE(email);
|
|
@ -1 +1,2 @@
|
|||
## Relevant articles:
|
||||
- [Introduction to Gradle](http://www.baeldung.com/gradle)
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
repositories{
|
||||
mavenCentral()
|
||||
}
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'maven'
|
||||
apply plugin: com.baeldung.GreetingPlugin
|
||||
dependencies {
|
||||
compile gradleApi()
|
||||
}
|
||||
|
||||
greeting {
|
||||
greeter = "Stranger"
|
||||
message = "Message from the build script!"
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.baeldung;
|
||||
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
|
||||
public class GreetingPlugin implements Plugin<Project> {
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
|
||||
GreetingPluginExtension extension = project.getExtensions().create("greeting", GreetingPluginExtension.class);
|
||||
|
||||
project.task("hello").doLast(task -> {
|
||||
System.out.println("Hello, " + extension.getGreeter());
|
||||
System.out.println("I have a message for You: " + extension.getMessage()); }
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.baeldung;
|
||||
|
||||
public class GreetingPluginExtension {
|
||||
private String greeter = "Baeldung";
|
||||
private String message = "Message from Plugin!";
|
||||
|
||||
public String getGreeter() {
|
||||
return greeter;
|
||||
}
|
||||
|
||||
public void setGreeter(String greeter) {
|
||||
this.greeter = greeter;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
## Building
|
||||
|
||||
To build the module, use Maven's `package` goal:
|
||||
|
||||
```
|
||||
mvn clean package
|
||||
```
|
||||
|
||||
The `war` file will be available at `target/remote-debugging.war`
|
||||
|
||||
## Running
|
||||
|
||||
The `war` application is deployed to Apache Tomcat 8 or any other Java Web or Application server.
|
||||
To deploy it to the Apache Tomcat 8 server, drop it in the `tomcat/webapps` directory.
|
||||
|
||||
The service then will be accessible at http://localhost:8080/remote-debugging/hello?name=John
|
|
@ -0,0 +1,49 @@
|
|||
<?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.stackify</groupId>
|
||||
<artifactId>java-remote-debugging</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>1.5.8.RELEASE</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<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>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>remote-debugging</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,12 @@
|
|||
package com.stackify.debug;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class JavaRemoteDebuggingApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(JavaRemoteDebuggingApplication.class, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.stackify.debug.config;
|
||||
|
||||
import com.stackify.debug.JavaRemoteDebuggingApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.support.SpringBootServletInitializer;
|
||||
|
||||
public class WebInitializer extends SpringBootServletInitializer {
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.sources(JavaRemoteDebuggingApplication.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.stackify.debug.rest;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController("/hello")
|
||||
public class HelloController {
|
||||
|
||||
@GetMapping
|
||||
public String hello(@RequestParam("name") String name) {
|
||||
String message = "Hello, " + name;
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,3 +2,5 @@
|
|||
|
||||
- [Dynamic Mapping with Hibernate](http://www.baeldung.com/hibernate-dynamic-mapping)
|
||||
- [An Overview of Identifiers in Hibernate](http://www.baeldung.com/hibernate-identifiers)
|
||||
- [Hibernate – Mapping Date and Time](http://www.baeldung.com/hibernate-date-time)
|
||||
- [Hibernate Inheritance Mapping](http://www.baeldung.com/hibernate-inheritance)
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.baeldung.hibernate.pojo.OrderEntry;
|
|||
import com.baeldung.hibernate.pojo.OrderEntryIdClass;
|
||||
import com.baeldung.hibernate.pojo.OrderEntryPK;
|
||||
import com.baeldung.hibernate.pojo.PointEntity;
|
||||
import com.baeldung.hibernate.pojo.PolygonEntity;
|
||||
import com.baeldung.hibernate.pojo.Product;
|
||||
import com.baeldung.hibernate.pojo.Phone;
|
||||
import com.baeldung.hibernate.pojo.TemporalValues;
|
||||
|
@ -79,6 +80,7 @@ public class HibernateUtil {
|
|||
metadataSources.addAnnotatedClass(Car.class);
|
||||
metadataSources.addAnnotatedClass(Bag.class);
|
||||
metadataSources.addAnnotatedClass(PointEntity.class);
|
||||
metadataSources.addAnnotatedClass(PolygonEntity.class);
|
||||
|
||||
Metadata metadata = metadataSources.buildMetadata();
|
||||
return metadata.getSessionFactoryBuilder()
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package com.baeldung.hibernate.pojo;
|
||||
|
||||
import com.vividsolutions.jts.geom.Polygon;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class PolygonEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private Polygon polygon;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Polygon getPolygon() {
|
||||
return polygon;
|
||||
}
|
||||
|
||||
public void setPolygon(Polygon polygon) {
|
||||
this.polygon = polygon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PolygonEntity{" + "id=" + id + ", polygon=" + polygon + '}';
|
||||
}
|
||||
}
|
|
@ -1,10 +1,14 @@
|
|||
package com.baeldung.hibernate;
|
||||
|
||||
import com.baeldung.hibernate.pojo.PointEntity;
|
||||
import com.baeldung.hibernate.pojo.PolygonEntity;
|
||||
import com.vividsolutions.jts.geom.Coordinate;
|
||||
import com.vividsolutions.jts.geom.Geometry;
|
||||
import com.vividsolutions.jts.geom.Point;
|
||||
import com.vividsolutions.jts.geom.Polygon;
|
||||
import com.vividsolutions.jts.io.ParseException;
|
||||
import com.vividsolutions.jts.io.WKTReader;
|
||||
import com.vividsolutions.jts.util.GeometricShapeFactory;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.junit.After;
|
||||
|
@ -13,6 +17,7 @@ import org.junit.Test;
|
|||
|
||||
import javax.persistence.Query;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -82,16 +87,58 @@ public class HibernateSpatialTest {
|
|||
.containsOnly("POINT (1 1)", "POINT (1 2)", "POINT (3 4)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSelectAllPointsWithinRadius() throws ParseException {
|
||||
insertPoint("POINT (1 1)");
|
||||
insertPoint("POINT (1 2)");
|
||||
insertPoint("POINT (3 4)");
|
||||
insertPoint("POINT (5 6)");
|
||||
|
||||
Query query = session.createQuery("select p from PointEntity p where within(p.point, :circle) = true",
|
||||
PointEntity.class);
|
||||
query.setParameter("circle", createCircle(0.0, 0.0, 5));
|
||||
|
||||
assertThat(query.getResultList().stream().map(p -> ((PointEntity) p).getPoint().toString()))
|
||||
.containsOnly("POINT (1 1)", "POINT (1 2)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSelectAdjacentPolygons() throws ParseException {
|
||||
insertPolygon("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))");
|
||||
insertPolygon("POLYGON ((3 0, 3 5, 8 5, 8 0, 3 0))");
|
||||
insertPolygon("POLYGON ((2 2, 3 1, 2 5, 4 3, 3 3, 2 2))");
|
||||
|
||||
Query query = session.createQuery("select p from PolygonEntity p where touches(p.polygon, :polygon) = true",
|
||||
PolygonEntity.class);
|
||||
query.setParameter("polygon", wktToGeometry("POLYGON ((5 5, 5 10, 10 10, 10 5, 5 5))"));
|
||||
assertThat(query.getResultList().stream().map(p -> ((PolygonEntity) p).getPolygon().toString()))
|
||||
.containsOnly("POLYGON ((0 0, 0 5, 5 5, 5 0, 0 0))", "POLYGON ((3 0, 3 5, 8 5, 8 0, 3 0))");
|
||||
}
|
||||
|
||||
private void insertPoint(String point) throws ParseException {
|
||||
PointEntity entity = new PointEntity();
|
||||
entity.setPoint((Point) wktToGeometry(point));
|
||||
session.persist(entity);
|
||||
}
|
||||
|
||||
private void insertPolygon(String polygon) throws ParseException {
|
||||
PolygonEntity entity = new PolygonEntity();
|
||||
entity.setPolygon((Polygon) wktToGeometry(polygon));
|
||||
session.persist(entity);
|
||||
}
|
||||
|
||||
private Geometry wktToGeometry(String wellKnownText) throws ParseException {
|
||||
WKTReader fromText = new WKTReader();
|
||||
Geometry geom = null;
|
||||
geom = fromText.read(wellKnownText);
|
||||
return geom;
|
||||
}
|
||||
|
||||
private static Geometry createCircle(double x, double y, double radius) {
|
||||
GeometricShapeFactory shapeFactory = new GeometricShapeFactory();
|
||||
shapeFactory.setNumPoints(32);
|
||||
shapeFactory.setCentre(new Coordinate(x, y));
|
||||
shapeFactory.setSize(radius * 2);
|
||||
return shapeFactory.createCircle();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1,4 @@
|
|||
## JSON B
|
||||
|
||||
## Relevant articles:
|
||||
- [Introduction to the JSON Binding API (JSR 367) in Java](http://www.baeldung.com/java-json-binding-api)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
## Relevant articles:
|
||||
- [The Order of Tests in JUnit](http://www.baeldung.com/junit-5-test-order)
|
|
@ -3,12 +3,14 @@ package com.baeldung.logback;
|
|||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.AppenderBase;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
public class MapAppender extends AppenderBase<ILoggingEvent> {
|
||||
|
||||
private final Map<String, ILoggingEvent> eventMap = new HashMap<>();
|
||||
private final ConcurrentMap<String, ILoggingEvent> eventMap
|
||||
= new ConcurrentHashMap<>();
|
||||
|
||||
private String prefix;
|
||||
|
||||
|
|
|
@ -86,6 +86,9 @@ org.eclipse.osgi_3.12.1.v20170821-1548.jar
|
|||
|
||||
= = NOT GOOD = =
|
||||
|
||||
## Relevant articles:
|
||||
- [Introduction to OSGi](http://www.baeldung.com/osgi)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
###Relevant Articles:
|
||||
- [A Guide to the Front Controller Pattern in Java](http://www.baeldung.com/java-front-controller-pattern)
|
||||
- [Introduction to Intercepting Filter Pattern in Java](http://www.baeldung.com/intercepting-filter-pattern-in-java)
|
||||
- [Implementing the Template Method Pattern in Java](http://www.baeldung.com/template-method-pattern-in-java)
|
||||
- [Implementing the Template Method Pattern in Java](http://www.baeldung.com/java-template-method-pattern)
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
- [Deleting Objects with Hibernate](http://www.baeldung.com/delete-with-hibernate)
|
||||
- [Self-Contained Testing Using an In-Memory Database](http://www.baeldung.com/spring-jpa-test-in-memory-database)
|
||||
- [Spring Data JPA – Adding a Method in All Repositories](http://www.baeldung.com/spring-data-jpa-method-in-all-repositories)
|
||||
- [A Guide to Spring AbstractRoutingDatasource](http://www.baeldung.com/spring-abstract-routing-data-source)
|
||||
|
||||
### Eclipse Config
|
||||
After importing the project into Eclipse, you may see the following error:
|
||||
|
|
1
pom.xml
1
pom.xml
|
@ -203,6 +203,7 @@
|
|||
<module>spring-rest-query-language</module>
|
||||
<module>spring-rest</module>
|
||||
<module>spring-rest-simple</module>
|
||||
<module>spring-security-acl</module>
|
||||
<module>spring-security-cache-control</module>
|
||||
<module>spring-security-client/spring-security-jsp-authentication</module>
|
||||
<module>spring-security-client/spring-security-jsp-authorize</module>
|
||||
|
|
|
@ -11,3 +11,5 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
|||
- [Spring 5 WebClient](http://www.baeldung.com/spring-5-webclient)
|
||||
- [Spring 5 Functional Bean Registration](http://www.baeldung.com/spring-5-functional-beans)
|
||||
- [The SpringJUnitConfig and SpringJUnitWebConfig Annotations in Spring 5](http://www.baeldung.com/spring-5-junit-config)
|
||||
- [Spring Security 5 for Reactive Applications](http://www.baeldung.com/spring-security-5-reactive)
|
||||
- [Spring 5 Testing with @EnabledIf Annotation](https://github.com/eugenp/tutorials/tree/master/spring-5)
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.0.0.M6</version>
|
||||
<version>2.0.0.M7</version>
|
||||
<relativePath /> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -3,3 +3,4 @@
|
|||
- [Implementing a Custom Spring AOP Annotation](http://www.baeldung.com/spring-aop-annotation)
|
||||
- [Intro to AspectJ](http://www.baeldung.com/aspectj)
|
||||
- [Spring Performance Logging](http://www.baeldung.com/spring-performance-logging)
|
||||
- [Introduction to Spring AOP](http://www.baeldung.com/spring-aop)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
## Relevant articles:
|
||||
- [A Quick Guide to Using Keycloak with Spring Boot](http://www.baeldung.com/spring-boot-keycloak)
|
|
@ -28,4 +28,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
|||
- [Spring Boot and Togglz Aspect](http://www.baeldung.com/spring-togglz)
|
||||
- [Getting Started with GraphQL and Spring Boot](http://www.baeldung.com/spring-graphql)
|
||||
- [Guide to Spring Type Conversions](http://www.baeldung.com/spring-type-conversions)
|
||||
|
||||
- [Quick Guide on data.sql and schema.sql Files in Spring Boot](http://www.baeldung.com/spring-boot-data-sql-and-schema-sql)
|
||||
|
|
|
@ -3,4 +3,4 @@
|
|||
## Spring Cloud CLI
|
||||
|
||||
### Relevant Articles:
|
||||
- [Introduction to Spring Cloud CLI](http://www.baeldung.com/introduction-to-spring-cloud-cli/)
|
||||
- [Introduction to Spring Cloud CLI](http://www.baeldung.com/spring-cloud-cli)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
- [Intro to Spring Cloud Netflix - Hystrix](http://www.baeldung.com/spring-cloud-netflix-hystrix)
|
||||
- [Dockerizing a Spring Boot Application](http://www.baeldung.com/dockerizing-spring-boot-application)
|
||||
- [Introduction to Spring Cloud Rest Client with Netflix Ribbon](http://www.baeldung.com/spring-cloud-rest-client-with-netflix-ribbon)
|
||||
- [A Quick Guide to Spring Cloud Consul](http://www.baeldung.com/spring-cloud-consul)
|
||||
|
||||
### Relevant Articles:
|
||||
- [Introduction to Spring Cloud Rest Client with Netflix Ribbon](http://www.baeldung.com/spring-cloud-rest-client-with-netflix-ribbon)
|
||||
|
|
|
@ -8,3 +8,5 @@
|
|||
- [Spring YAML Configuration](http://www.baeldung.com/spring-yaml)
|
||||
- [Introduction to Spring’s StreamUtils](http://www.baeldung.com/spring-stream-utils)
|
||||
- [Using Spring @Value with Defaults](http://www.baeldung.com/spring-value-defaults)
|
||||
- [Groovy Bean Definitions](http://www.baeldung.com/spring-groovy-beans)
|
||||
- [XML-Based Injection in Spring](http://www.baeldung.com/spring-xml-injection)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
## Relevant articles:
|
||||
- [HibernateException: No Hibernate Session Bound to Thread in Hibernate 3](http://www.baeldung.com/no-hibernate-session-bound-to-thread-exception)
|
|
@ -1,2 +1,5 @@
|
|||
### Relevant Articles:
|
||||
- [Introduction to Spring Integration](http://www.baeldung.com/spring-integration)
|
||||
|
||||
### Running the Sample
|
||||
Executing the `mvn exec:java` maven command (either from the command line or from an IDE) will start up the application. Follow the command prompt for further instructions.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<spring-social.version>1.1.4.RELEASE</spring-social.version>
|
||||
<javax-mail.version>1.4.7</javax-mail.version>
|
||||
<javax-activation.version>1.1.1</javax-activation.version>
|
||||
|
||||
<junit.version>4.12</junit.version>
|
||||
<maven-eclipse-plugin.version>2.10</maven-eclipse-plugin.version>
|
||||
<exec-maven-plugin.version>1.5.0</exec-maven-plugin.version>
|
||||
</properties>
|
||||
|
@ -56,7 +56,7 @@
|
|||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>${exec-maven-plugin.version}</version>
|
||||
<configuration>
|
||||
<mainClass>com.baeldung.samples.Main</mainClass>
|
||||
<mainClass>com.baeldung.samples.FileCopyConfig</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
@ -106,6 +106,12 @@
|
|||
<artifactId>spring-integration-file</artifactId>
|
||||
<version>${spring.integration.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
|
|
|
@ -346,7 +346,7 @@
|
|||
</profiles>
|
||||
|
||||
<properties>
|
||||
<commons-fileupload.version>1.3.2</commons-fileupload.version>
|
||||
<commons-fileupload.version>1.3.3</commons-fileupload.version>
|
||||
<kryo.version>4.0.0</kryo.version>
|
||||
<protobuf-java-format.version>1.4</protobuf-java-format.version>
|
||||
<protobuf-java.version>3.1.0</protobuf-java.version>
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
package com.baeldung.apachefileupload;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.apache.commons.fileupload.FileItemIterator;
|
||||
import org.apache.commons.fileupload.FileItemStream;
|
||||
import org.apache.commons.fileupload.FileUploadException;
|
||||
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
|
||||
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||
import org.apache.commons.fileupload.util.Streams;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class UploadController {
|
||||
|
||||
@RequestMapping(value = "/upload", method = RequestMethod.POST)
|
||||
public String handleUpload(HttpServletRequest request) {
|
||||
System.out.println(System.getProperty("java.io.tmpdir"));
|
||||
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
|
||||
// Create a factory for disk-based file items
|
||||
DiskFileItemFactory factory = new DiskFileItemFactory();
|
||||
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
|
||||
factory.setSizeThreshold(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD);
|
||||
factory.setFileCleaningTracker(null);
|
||||
// Configure a repository (to ensure a secure temp location is used)
|
||||
ServletFileUpload upload = new ServletFileUpload(factory);
|
||||
try {
|
||||
// Parse the request
|
||||
List<FileItem> items = upload.parseRequest(request);
|
||||
// Process the uploaded items
|
||||
Iterator<FileItem> iter = items.iterator();
|
||||
while (iter.hasNext()) {
|
||||
FileItem item = iter.next();
|
||||
|
||||
if (!item.isFormField()) {
|
||||
try (InputStream uploadedStream = item.getInputStream();
|
||||
OutputStream out = new FileOutputStream("file.mov");) {
|
||||
IOUtils.copy(uploadedStream, out);
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Parse the request with Streaming API
|
||||
upload = new ServletFileUpload();
|
||||
FileItemIterator iterStream = upload.getItemIterator(request);
|
||||
while (iterStream.hasNext()) {
|
||||
FileItemStream item = iterStream.next();
|
||||
String name = item.getFieldName();
|
||||
InputStream stream = item.openStream();
|
||||
if (!item.isFormField()) {
|
||||
//Process the InputStream
|
||||
} else {
|
||||
//process form fields
|
||||
String formFieldValue = Streams.asString(stream);
|
||||
}
|
||||
}
|
||||
return "success!";
|
||||
} catch (IOException | FileUploadException ex) {
|
||||
return "failed: " + ex.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
## Spring Security ACL Project
|
||||
|
||||
### Relevant Articles
|
||||
- [Introduction to Spring Security ACL](http://www.baeldung.com/spring-security-acl)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue