Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
90c9744746
@ -0,0 +1,59 @@
|
|||||||
|
package com.baeldung.algorithms.prime;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
public class PrimeGenerator {
|
||||||
|
public static List<Integer> sieveOfEratosthenes(int n) {
|
||||||
|
final boolean prime[] = new boolean[n + 1];
|
||||||
|
Arrays.fill(prime, true);
|
||||||
|
|
||||||
|
for (int p = 2; p * p <= n; p++) {
|
||||||
|
if (prime[p]) {
|
||||||
|
for (int i = p * 2; i <= n; i += p)
|
||||||
|
prime[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Integer> primes = new LinkedList<>();
|
||||||
|
for (int i = 2; i <= n; i++) {
|
||||||
|
if (prime[i])
|
||||||
|
primes.add(i);
|
||||||
|
}
|
||||||
|
return primes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Integer> primeNumbersBruteForce(int max) {
|
||||||
|
final List<Integer> primeNumbers = new LinkedList<Integer>();
|
||||||
|
for (int i = 2; i <= max; i++) {
|
||||||
|
if (isPrimeBruteForce(i)) {
|
||||||
|
primeNumbers.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return primeNumbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isPrimeBruteForce(int x) {
|
||||||
|
for (int i = 2; i < x; i++) {
|
||||||
|
if (x % i == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Integer> primeNumbersTill(int max) {
|
||||||
|
return IntStream.rangeClosed(2, max)
|
||||||
|
.filter(x -> isPrime(x))
|
||||||
|
.boxed()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isPrime(int x) {
|
||||||
|
return IntStream.rangeClosed(2, (int) (Math.sqrt(x)))
|
||||||
|
.allMatch(n -> x % n != 0);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.baeldung.algorithms.prime;
|
||||||
|
|
||||||
|
import static com.baeldung.algorithms.prime.PrimeGenerator.*;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.Test;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class PrimeGeneratorTest {
|
||||||
|
@Test
|
||||||
|
public void whenBruteForced_returnsSuccessfully() {
|
||||||
|
final List<Integer> primeNumbers = primeNumbersBruteForce(20);
|
||||||
|
assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenOptimized_returnsSuccessfully() {
|
||||||
|
final List<Integer> primeNumbers = primeNumbersTill(20);
|
||||||
|
assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSieveOfEratosthenes_returnsSuccessfully() {
|
||||||
|
final List<Integer> primeNumbers = sieveOfEratosthenes(20);
|
||||||
|
assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.baeldung.prime;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
public class PrimeGenerator {
|
||||||
|
public static List<Integer> sieveOfEratosthenes(int n) {
|
||||||
|
final boolean prime[] = new boolean[n + 1];
|
||||||
|
Arrays.fill(prime, true);
|
||||||
|
|
||||||
|
for (int p = 2; p * p <= n; p++) {
|
||||||
|
if (prime[p]) {
|
||||||
|
for (int i = p * 2; i <= n; i += p)
|
||||||
|
prime[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<Integer> primes = new LinkedList<>();
|
||||||
|
for (int i = 2; i <= n; i++) {
|
||||||
|
if (prime[i])
|
||||||
|
primes.add(i);
|
||||||
|
}
|
||||||
|
return primes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Integer> primeNumbersBruteForce(int max) {
|
||||||
|
final List<Integer> primeNumbers = new LinkedList<Integer>();
|
||||||
|
for (int i = 2; i <= max; i++) {
|
||||||
|
if (isPrimeBruteForce(i)) {
|
||||||
|
primeNumbers.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return primeNumbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isPrimeBruteForce(int x) {
|
||||||
|
for (int i = 2; i < x; i++) {
|
||||||
|
if (x % i == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Integer> primeNumbersTill(int max) {
|
||||||
|
return IntStream.rangeClosed(2, max)
|
||||||
|
.filter(x -> isPrime(x))
|
||||||
|
.boxed()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isPrime(int x) {
|
||||||
|
return IntStream.rangeClosed(2, (int) (Math.sqrt(x)))
|
||||||
|
.allMatch(n -> x % n != 0);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.baeldung.prime;
|
||||||
|
|
||||||
|
import static com.baeldung.prime.PrimeGenerator.*;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.Test;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class PrimeGeneratorTest {
|
||||||
|
@Test
|
||||||
|
public void whenBruteForced_returnsSuccessfully() {
|
||||||
|
final List<Integer> primeNumbers = primeNumbersBruteForce(20);
|
||||||
|
assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenOptimized_returnsSuccessfully() {
|
||||||
|
final List<Integer> primeNumbers = primeNumbersTill(20);
|
||||||
|
assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSieveOfEratosthenes_returnsSuccessfully() {
|
||||||
|
final List<Integer> primeNumbers = sieveOfEratosthenes(20);
|
||||||
|
assertEquals(Arrays.asList(new Integer[] { 2, 3, 5, 7, 11, 13, 17, 19 }), primeNumbers);
|
||||||
|
}
|
||||||
|
}
|
137
core-java/src/test/java/com/baeldung/stack/StackUnitTest.java
Normal file
137
core-java/src/test/java/com/baeldung/stack/StackUnitTest.java
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
package com.baeldung.stack;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
public class StackUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenStackIsCreated_thenItHasSize0() {
|
||||||
|
Stack intStack = new Stack();
|
||||||
|
assertEquals(0, intStack.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyStack_whenElementIsPushed_thenStackSizeisIncreased() {
|
||||||
|
Stack intStack = new Stack();
|
||||||
|
intStack.push(1);
|
||||||
|
assertEquals(1, intStack.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenEmptyStack_whenMultipleElementsArePushed_thenStackSizeisIncreased() {
|
||||||
|
Stack intStack = new Stack();
|
||||||
|
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
|
||||||
|
boolean result = intStack.addAll(intList);
|
||||||
|
assertTrue(result);
|
||||||
|
assertEquals(7, intList.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenElementIsPoppedFromStack_thenElementIsRemovedAndSizeChanges() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.pop();
|
||||||
|
assertTrue(intStack.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenElementIsPeeked_thenElementIsNotRemovedAndSizeDoesNotChange() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.peek();
|
||||||
|
assertEquals(1, intStack.search(5));
|
||||||
|
assertEquals(1, intStack.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenElementIsOnStack_thenSearchReturnsItsDistanceFromTheTop() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
assertEquals(1, intStack.search(5));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenElementIsOnStack_thenIndexOfReturnsItsIndex() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
int indexOf = intStack.indexOf(5);
|
||||||
|
assertEquals(0, indexOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenMultipleElementsAreOnStack_thenIndexOfReturnsLastElementIndex() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.push(5);
|
||||||
|
int lastIndexOf = intStack.lastIndexOf(5);
|
||||||
|
assertEquals(2, lastIndexOf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenElementOnStack_whenRemoveElementIsInvoked_thenElementIsRemoved() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.removeElement(5);
|
||||||
|
assertEquals(1, intStack.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenElementOnStack_whenRemoveElementAtIsInvoked_thenElementIsRemoved() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.push(7);
|
||||||
|
intStack.removeElementAt(1);
|
||||||
|
assertEquals(-1, intStack.search(7));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenElementsOnStack_whenRemoveAllElementsIsInvoked_thenAllElementsAreRemoved() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
intStack.push(5);
|
||||||
|
intStack.push(7);
|
||||||
|
intStack.removeAllElements();
|
||||||
|
assertTrue(intStack.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenElementsOnStack_whenRemoveAllIsInvoked_thenAllElementsFromCollectionAreRemoved() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
|
||||||
|
intStack.addAll(intList);
|
||||||
|
intStack.add(500);
|
||||||
|
intStack.removeAll(intList);
|
||||||
|
assertEquals(1, intStack.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenElementsOnStack_whenRemoveIfIsInvoked_thenAllElementsSatysfyingConditionAreRemoved() {
|
||||||
|
Stack<Integer> intStack = new Stack();
|
||||||
|
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
|
||||||
|
intStack.addAll(intList);
|
||||||
|
intStack.removeIf(element -> element < 6);
|
||||||
|
assertEquals(2, intStack.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenAnotherStackCreatedWhileTraversingStack_thenStacksAreEqual() {
|
||||||
|
Stack<Integer> intStack = new Stack<>();
|
||||||
|
List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
|
||||||
|
intStack.addAll(intList);
|
||||||
|
ListIterator<Integer> it = intStack.listIterator();
|
||||||
|
Stack<Integer> result = new Stack();
|
||||||
|
while(it.hasNext()) {
|
||||||
|
result.push(it.next());
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(result, equalTo(intStack));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.baeldung.stringpool;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import static org.assertj.core.api.Assertions.*;
|
||||||
|
|
||||||
|
public class StringPoolUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCreatingConstantStrings_thenTheirAddressesAreEqual() {
|
||||||
|
String constantString1 = "Baeldung";
|
||||||
|
String constantString2 = "Baeldung";
|
||||||
|
|
||||||
|
assertThat(constantString1).isSameAs(constantString2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCreatingStringsWithTheNewOperator_thenTheirAddressesAreDifferent() {
|
||||||
|
String newString1 = new String("Baeldung");
|
||||||
|
String newString2 = new String("Baeldung");
|
||||||
|
|
||||||
|
assertThat(newString1).isNotSameAs(newString2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenComparingConstantAndNewStrings_thenTheirAddressesAreDifferent() {
|
||||||
|
String constantString = "Baeldung";
|
||||||
|
String newString = new String("Baeldung");
|
||||||
|
|
||||||
|
assertThat(constantString).isNotSameAs(newString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInterningAStringWithIdenticalValueToAnother_thenTheirAddressesAreEqual() {
|
||||||
|
String constantString = "interned Baeldung";
|
||||||
|
String newString = new String("interned Baeldung");
|
||||||
|
|
||||||
|
assertThat(constantString).isNotSameAs(newString);
|
||||||
|
|
||||||
|
String internedString = newString.intern();
|
||||||
|
|
||||||
|
assertThat(constantString).isSameAs(internedString);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?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"
|
<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">
|
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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<artifactId>drools-backward-chaining</artifactId>
|
<artifactId>drools-backward-chaining</artifactId>
|
||||||
@ -17,7 +16,6 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<runtime.version>6.4.0.Final</runtime.version>
|
<runtime.version>6.4.0.Final</runtime.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.kie</groupId>
|
<groupId>org.kie</groupId>
|
||||||
@ -26,7 +24,6 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.drools</groupId>
|
<groupId>org.drools</groupId>
|
||||||
<artifactId>drools-core</artifactId>
|
|
||||||
<version>${runtime.version}</version>
|
<version>${runtime.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -21,13 +21,11 @@ public class BackwardChaining {
|
|||||||
KieSession ksession = kContainer.newKieSession("ksession-backward-chaining");
|
KieSession ksession = kContainer.newKieSession("ksession-backward-chaining");
|
||||||
ksession.setGlobal("result", result);
|
ksession.setGlobal("result", result);
|
||||||
ksession.insert(new Fact("Asia", "Planet Earth"));
|
ksession.insert(new Fact("Asia", "Planet Earth"));
|
||||||
// ksession.insert(new Fact("China", "Asia"));
|
// ksession.insert(new Fact("China", "Asia"));
|
||||||
ksession.insert(new Fact("Great Wall of China", "China"));
|
ksession.insert(new Fact("Great Wall of China", "China"));
|
||||||
|
|
||||||
ksession.fireAllRules();
|
ksession.fireAllRules();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.baeldung
|
||||||
|
|
||||||
|
import com.baeldung.drools.model.Fact;
|
||||||
|
|
||||||
|
global com.baeldung.drools.model.Result result;
|
||||||
|
|
||||||
|
dialect "mvel"
|
||||||
|
|
||||||
|
query belongsTo(String x, String y)
|
||||||
|
Fact(x, y;)
|
||||||
|
or
|
||||||
|
(Fact(z, y;) and belongsTo(x, z;))
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "Great Wall of China BELONGS TO Planet Earth"
|
||||||
|
when
|
||||||
|
belongsTo("Great Wall of China", "Planet Earth";)
|
||||||
|
then
|
||||||
|
result.setValue("Decision one taken: Great Wall of China BELONGS TO Planet Earth");
|
||||||
|
end
|
||||||
|
|
||||||
|
rule "print all facts"
|
||||||
|
when
|
||||||
|
belongsTo(element, place;)
|
||||||
|
then
|
||||||
|
result.addFact(element + " IS ELEMENT OF " + place);
|
||||||
|
end
|
@ -2,8 +2,6 @@ package com.baeldung.test;
|
|||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.junit.runners.JUnit4;
|
|
||||||
import org.kie.api.KieServices;
|
import org.kie.api.KieServices;
|
||||||
import org.kie.api.runtime.KieContainer;
|
import org.kie.api.runtime.KieContainer;
|
||||||
import org.kie.api.runtime.KieSession;
|
import org.kie.api.runtime.KieSession;
|
||||||
@ -13,7 +11,6 @@ import com.baeldung.drools.model.Result;
|
|||||||
|
|
||||||
import static junit.framework.TestCase.assertEquals;
|
import static junit.framework.TestCase.assertEquals;
|
||||||
|
|
||||||
@RunWith(value = JUnit4.class)
|
|
||||||
public class BackwardChainingTest {
|
public class BackwardChainingTest {
|
||||||
private Result result;
|
private Result result;
|
||||||
private KieServices ks;
|
private KieServices ks;
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
<artifactId>drools</artifactId>
|
<artifactId>drools</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
|
17
guest/spring-security/README.md
Normal file
17
guest/spring-security/README.md
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
## Building
|
||||||
|
|
||||||
|
To build the module, use Maven's `package` goal:
|
||||||
|
|
||||||
|
```
|
||||||
|
mvn clean package
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
To run the application, use Spring Boot's `run` goal:
|
||||||
|
|
||||||
|
```
|
||||||
|
mvn spring-boot:run
|
||||||
|
```
|
||||||
|
|
||||||
|
The application will be accessible at [http://localhost:8080/](http://localhost:8080/)
|
77
guest/spring-security/pom.xml
Normal file
77
guest/spring-security/pom.xml
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?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.guest</groupId>
|
||||||
|
<artifactId>spring-security</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.0.0.M6</version>
|
||||||
|
<relativePath/>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<name>spring-security</name>
|
||||||
|
<description>Spring Security Sample Project</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.thymeleaf</groupId>
|
||||||
|
<artifactId>thymeleaf-spring5</artifactId>
|
||||||
|
<version>3.0.8.RELEASE</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>spring-milestones</id>
|
||||||
|
<name>Spring Milestones</name>
|
||||||
|
<url>https://repo.spring.io/milestone</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>spring-milestones</id>
|
||||||
|
<name>Spring Milestones</name>
|
||||||
|
<url>https://repo.spring.io/milestone</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.stackify.guest.springsecurity;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@ComponentScan(basePackages = {"com.stackify.guest.springsecurity"})
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.stackify.guest.springsecurity.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class WebMvcConfiguration implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addViewControllers(ViewControllerRegistry registry) {
|
||||||
|
registry.addViewController("/customLogin").setViewName("customLogin");
|
||||||
|
registry.addViewController("/loginSuccess").setViewName("index");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.stackify.guest.springsecurity.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.provisioning.JdbcUserDetailsManager;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
@EnableWebSecurity
|
||||||
|
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public UserDetailsService jdbcUserDetailsService(DataSource dataSource) {
|
||||||
|
JdbcUserDetailsManager manager = new JdbcUserDetailsManager();
|
||||||
|
manager.setDataSource(dataSource);
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PasswordEncoder passwordEncoder() {
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
http.authorizeRequests()
|
||||||
|
.antMatchers("/css/**").permitAll()
|
||||||
|
.anyRequest().authenticated()
|
||||||
|
.and().formLogin()
|
||||||
|
.loginPage("/customLogin")
|
||||||
|
.defaultSuccessUrl("/loginSuccess", true)
|
||||||
|
.permitAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
2
guest/spring-security/src/main/resources/data.sql
Normal file
2
guest/spring-security/src/main/resources/data.sql
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
INSERT INTO users VALUES ('jill', '$2a$04$qUlqAEEYF1YvrpJMosodoewgL6aO.qgHytl2k5L7kdXEWnJsFdxvq', TRUE);
|
||||||
|
INSERT INTO authorities VALUES ('jill', 'USERS');
|
10
guest/spring-security/src/main/resources/schema.sql
Normal file
10
guest/spring-security/src/main/resources/schema.sql
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
CREATE TABLE users (
|
||||||
|
username VARCHAR(256) PRIMARY KEY,
|
||||||
|
password VARCHAR(256),
|
||||||
|
enabled BOOLEAN
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE authorities (
|
||||||
|
username VARCHAR(256) REFERENCES users (username),
|
||||||
|
authority VARCHAR(256)
|
||||||
|
);
|
@ -0,0 +1,3 @@
|
|||||||
|
.bad-login {
|
||||||
|
color: red;
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="/css/styles.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<form th:action="@{/customLogin}" method="post">
|
||||||
|
<fieldset>
|
||||||
|
<label for="username">Login:</label>
|
||||||
|
<input id="username" name="username">
|
||||||
|
<label for="password">Password:</label>
|
||||||
|
<input id="password" name="password" type="password">
|
||||||
|
</fieldset>
|
||||||
|
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
|
||||||
|
<input type="submit" value="Login">
|
||||||
|
<div th:if="${param.error}" class="bad-login">Bad login or password.</div>
|
||||||
|
<div th:if="${param.logout}">Log out successful.</div>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,11 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<p>Hello, <span th:text="${
|
||||||
|
T(org.springframework.security.core.context.SecurityContextHolder)
|
||||||
|
.context.authentication.principal.username}"></span>!</p>
|
||||||
|
<form action="/logout" method="post">
|
||||||
|
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}"/>
|
||||||
|
<input type="submit" value="Log Out">
|
||||||
|
</form>
|
||||||
|
</html>
|
@ -2,8 +2,17 @@ package com.baeldung.hibernate;
|
|||||||
|
|
||||||
import com.baeldung.hibernate.pojo.Employee;
|
import com.baeldung.hibernate.pojo.Employee;
|
||||||
import com.baeldung.hibernate.pojo.EntityDescription;
|
import com.baeldung.hibernate.pojo.EntityDescription;
|
||||||
|
import com.baeldung.hibernate.pojo.OrderEntry;
|
||||||
|
import com.baeldung.hibernate.pojo.OrderEntryIdClass;
|
||||||
|
import com.baeldung.hibernate.pojo.OrderEntryPK;
|
||||||
|
import com.baeldung.hibernate.pojo.Product;
|
||||||
import com.baeldung.hibernate.pojo.Phone;
|
import com.baeldung.hibernate.pojo.Phone;
|
||||||
import com.baeldung.hibernate.pojo.TemporalValues;
|
import com.baeldung.hibernate.pojo.TemporalValues;
|
||||||
|
import com.baeldung.hibernate.pojo.Course;
|
||||||
|
import com.baeldung.hibernate.pojo.Student;
|
||||||
|
import com.baeldung.hibernate.pojo.User;
|
||||||
|
import com.baeldung.hibernate.pojo.UserProfile;
|
||||||
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.boot.Metadata;
|
import org.hibernate.boot.Metadata;
|
||||||
import org.hibernate.boot.MetadataSources;
|
import org.hibernate.boot.MetadataSources;
|
||||||
@ -33,6 +42,14 @@ public class HibernateUtil {
|
|||||||
metadataSources.addAnnotatedClass(Phone.class);
|
metadataSources.addAnnotatedClass(Phone.class);
|
||||||
metadataSources.addAnnotatedClass(EntityDescription.class);
|
metadataSources.addAnnotatedClass(EntityDescription.class);
|
||||||
metadataSources.addAnnotatedClass(TemporalValues.class);
|
metadataSources.addAnnotatedClass(TemporalValues.class);
|
||||||
|
metadataSources.addAnnotatedClass(User.class);
|
||||||
|
metadataSources.addAnnotatedClass(Student.class);
|
||||||
|
metadataSources.addAnnotatedClass(Course.class);
|
||||||
|
metadataSources.addAnnotatedClass(Product.class);
|
||||||
|
metadataSources.addAnnotatedClass(OrderEntryPK.class);
|
||||||
|
metadataSources.addAnnotatedClass(OrderEntry.class);
|
||||||
|
metadataSources.addAnnotatedClass(OrderEntryIdClass.class);
|
||||||
|
metadataSources.addAnnotatedClass(UserProfile.class);
|
||||||
|
|
||||||
Metadata metadata = metadataSources.buildMetadata();
|
Metadata metadata = metadataSources.buildMetadata();
|
||||||
return metadata.getSessionFactoryBuilder()
|
return metadata.getSessionFactoryBuilder()
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.baeldung.hibernate.pojo;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Course {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private UUID courseId;
|
||||||
|
|
||||||
|
public UUID getCourseId() {
|
||||||
|
return courseId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCourseId(UUID courseId) {
|
||||||
|
this.courseId = courseId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.baeldung.hibernate.pojo;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.TableGenerator;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Department {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.TABLE, generator="table-generator")
|
||||||
|
@TableGenerator (name="table-generator", table="dep_ids", pkColumnName="seq_id", valueColumnName="seq_value")
|
||||||
|
private long depId;
|
||||||
|
|
||||||
|
public long getDepId() {
|
||||||
|
return depId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDepId(long depId) {
|
||||||
|
this.depId = depId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.baeldung.hibernate.pojo;
|
||||||
|
|
||||||
|
import javax.persistence.EmbeddedId;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class OrderEntry {
|
||||||
|
|
||||||
|
@EmbeddedId
|
||||||
|
private OrderEntryPK entryId;
|
||||||
|
|
||||||
|
public OrderEntryPK getEntryId() {
|
||||||
|
return entryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEntryId(OrderEntryPK entryId) {
|
||||||
|
this.entryId = entryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.baeldung.hibernate.pojo;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.IdClass;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@IdClass(OrderEntryPK.class)
|
||||||
|
public class OrderEntryIdClass {
|
||||||
|
@Id
|
||||||
|
private long orderId;
|
||||||
|
@Id
|
||||||
|
private long productId;
|
||||||
|
|
||||||
|
public long getOrderId() {
|
||||||
|
return orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderId(long orderId) {
|
||||||
|
this.orderId = orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getProductId() {
|
||||||
|
return productId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProductId(long productId) {
|
||||||
|
this.productId = productId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.baeldung.hibernate.pojo;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public class OrderEntryPK implements Serializable {
|
||||||
|
|
||||||
|
private long orderId;
|
||||||
|
private long productId;
|
||||||
|
|
||||||
|
public long getOrderId() {
|
||||||
|
return orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderId(long orderId) {
|
||||||
|
this.orderId = orderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getProductId() {
|
||||||
|
return productId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProductId(long productId) {
|
||||||
|
this.productId = productId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
OrderEntryPK pk = (OrderEntryPK) o;
|
||||||
|
return Objects.equals(orderId, pk.orderId) && Objects.equals(productId, pk.productId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(orderId, productId);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package com.baeldung.hibernate.pojo;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.GenericGenerator;
|
||||||
|
import org.hibernate.annotations.Parameter;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Product {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(generator = "prod-generator")
|
||||||
|
@GenericGenerator(name = "prod-generator", parameters = @Parameter(name = "prefix", value = "prod"), strategy = "com.baeldung.hibernate.pojo.generator.MyGenerator")
|
||||||
|
private String prodId;
|
||||||
|
|
||||||
|
public String getProdId() {
|
||||||
|
return prodId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProdId(String prodId) {
|
||||||
|
this.prodId = prodId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.baeldung.hibernate.pojo;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Student {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue (strategy = GenerationType.SEQUENCE)
|
||||||
|
private long studentId;
|
||||||
|
|
||||||
|
public long getStudentId() {
|
||||||
|
return studentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStudent_id(long studentId) {
|
||||||
|
this.studentId = studentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.baeldung.hibernate.pojo;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.SequenceGenerator;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class User {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequence-generator")
|
||||||
|
@SequenceGenerator(name = "sequence-generator", sequenceName = "user_sequence", initialValue = 4)
|
||||||
|
private long userId;
|
||||||
|
|
||||||
|
public long getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(long userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.baeldung.hibernate.pojo;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.MapsId;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class UserProfile {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private long profileId;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
@MapsId
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
public long getProfileId() {
|
||||||
|
return profileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProfileId(long profileId) {
|
||||||
|
this.profileId = profileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.baeldung.hibernate.pojo.generator;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
import org.hibernate.MappingException;
|
||||||
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.id.Configurable;
|
||||||
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
|
import org.hibernate.service.ServiceRegistry;
|
||||||
|
import org.hibernate.type.Type;
|
||||||
|
|
||||||
|
public class MyGenerator implements IdentifierGenerator, Configurable {
|
||||||
|
|
||||||
|
private String prefix;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Serializable generate(SharedSessionContractImplementor session, Object obj) throws HibernateException {
|
||||||
|
|
||||||
|
String query = String.format("select %s from %s",
|
||||||
|
session.getEntityPersister(obj.getClass().getName(), obj).getIdentifierPropertyName(),
|
||||||
|
obj.getClass().getSimpleName());
|
||||||
|
|
||||||
|
Stream<String> ids = session.createQuery(query).stream();
|
||||||
|
|
||||||
|
Long max = ids.map(o -> o.replace(prefix + "-", ""))
|
||||||
|
.mapToLong(Long::parseLong)
|
||||||
|
.max()
|
||||||
|
.orElse(0L);
|
||||||
|
|
||||||
|
return prefix + "-" + (max + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(Type type, Properties properties, ServiceRegistry serviceRegistry) throws MappingException {
|
||||||
|
prefix = properties.getProperty("prefix");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,100 @@
|
|||||||
|
package com.baeldung.hibernate;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.hibernate.Transaction;
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import com.baeldung.hibernate.pojo.Product;
|
||||||
|
import com.baeldung.hibernate.pojo.Course;
|
||||||
|
import com.baeldung.hibernate.pojo.OrderEntry;
|
||||||
|
import com.baeldung.hibernate.pojo.OrderEntryIdClass;
|
||||||
|
import com.baeldung.hibernate.pojo.OrderEntryPK;
|
||||||
|
import com.baeldung.hibernate.pojo.Student;
|
||||||
|
import com.baeldung.hibernate.pojo.User;
|
||||||
|
import com.baeldung.hibernate.pojo.UserProfile;
|
||||||
|
|
||||||
|
public class IdentifiersIntegrationTest {
|
||||||
|
private Session session;
|
||||||
|
|
||||||
|
private Transaction transaction;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws IOException {
|
||||||
|
session = HibernateUtil.getSessionFactory()
|
||||||
|
.openSession();
|
||||||
|
transaction = session.beginTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
transaction.rollback();
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSaveSimpleIdEntities_thenOk() {
|
||||||
|
Student student = new Student();
|
||||||
|
session.save(student);
|
||||||
|
User user = new User();
|
||||||
|
session.save(user);
|
||||||
|
|
||||||
|
assertThat(student.getStudentId()).isEqualTo(1L);
|
||||||
|
assertThat(user.getUserId()).isEqualTo(4L);
|
||||||
|
|
||||||
|
Course course = new Course();
|
||||||
|
session.save(course);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSaveCustomGeneratedId_thenOk() {
|
||||||
|
Product product = new Product();
|
||||||
|
session.save(product);
|
||||||
|
Product product2 = new Product();
|
||||||
|
session.save(product2);
|
||||||
|
|
||||||
|
assertThat(product2.getProdId()).isEqualTo("prod-2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSaveCompositeIdEntity_thenOk() {
|
||||||
|
OrderEntryPK entryPK = new OrderEntryPK();
|
||||||
|
entryPK.setOrderId(1L);
|
||||||
|
entryPK.setProductId(30L);
|
||||||
|
|
||||||
|
OrderEntry entry = new OrderEntry();
|
||||||
|
entry.setEntryId(entryPK);
|
||||||
|
session.save(entry);
|
||||||
|
|
||||||
|
assertThat(entry.getEntryId()
|
||||||
|
.getOrderId()).isEqualTo(1L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSaveIdClassEntity_thenOk() {
|
||||||
|
OrderEntryIdClass entry = new OrderEntryIdClass();
|
||||||
|
entry.setOrderId(1L);
|
||||||
|
entry.setProductId(30L);
|
||||||
|
session.save(entry);
|
||||||
|
|
||||||
|
assertThat(entry.getOrderId()).isEqualTo(1L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSaveDerivedIdEntity_thenOk() {
|
||||||
|
User user = new User();
|
||||||
|
session.save(user);
|
||||||
|
|
||||||
|
UserProfile profile = new UserProfile();
|
||||||
|
profile.setUser(user);
|
||||||
|
session.save(profile);
|
||||||
|
|
||||||
|
assertThat(profile.getProfileId()).isEqualTo(user.getUserId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
jsonb/.gitignore
vendored
Normal file
12
jsonb/.gitignore
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#folders#
|
||||||
|
.idea
|
||||||
|
/target
|
||||||
|
/neoDb*
|
||||||
|
/data
|
||||||
|
/src/main/webapp/WEB-INF/classes
|
||||||
|
*/META-INF/*
|
||||||
|
|
||||||
|
# Packaged files #
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
*.ear
|
1
jsonb/README.md
Normal file
1
jsonb/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
## JSON B
|
106
jsonb/pom.xml
Normal file
106
jsonb/pom.xml
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>json-b</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>json-b</name>
|
||||||
|
<description>json-b sample project</description>
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>yasson</id>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
<dependencies>
|
||||||
|
<!-- Dependencies for Yasson -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse</groupId>
|
||||||
|
<artifactId>yasson</artifactId>
|
||||||
|
<version>${yasson.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.glassfish</groupId>
|
||||||
|
<artifactId>javax.json</artifactId>
|
||||||
|
<version>${javax.json.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>johnzon</id>
|
||||||
|
<dependencies>
|
||||||
|
<!-- Dependencies for Johnzon -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.geronimo.specs</groupId>
|
||||||
|
<artifactId>geronimo-json_1.1_spec</artifactId>
|
||||||
|
<version>${geronimo-json_1.1_spec.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.johnzon</groupId>
|
||||||
|
<artifactId>johnzon-jsonb</artifactId>
|
||||||
|
<version>${johnzon.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.json.bind</groupId>
|
||||||
|
<artifactId>javax.json.bind-api</artifactId>
|
||||||
|
<version>${jsonb-api.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- utils -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-collections4</artifactId>
|
||||||
|
<version>${commons-collections4.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<version>${junit.jupiter.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
|
<version>${junit.jupiter.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.platform</groupId>
|
||||||
|
<artifactId>junit-platform-surefire-provider</artifactId>
|
||||||
|
<version>${junit.platform.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.platform</groupId>
|
||||||
|
<artifactId>junit-platform-runner</artifactId>
|
||||||
|
<version>${junit.platform.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
<junit.platform.version>1.0.0</junit.platform.version>
|
||||||
|
<junit.jupiter.version>5.0.0</junit.jupiter.version>
|
||||||
|
<maven-surefire-plugin.version>2.20</maven-surefire-plugin.version>
|
||||||
|
<jsonb-api.version>1.0</jsonb-api.version>
|
||||||
|
<johnzon.version>1.1.3</johnzon.version>
|
||||||
|
<geronimo-json_1.1_spec.version>1.0</geronimo-json_1.1_spec.version>
|
||||||
|
<yasson.version>1.0</yasson.version>
|
||||||
|
<javax.json.version>1.1.2</javax.json.version>
|
||||||
|
<commons-collections4.version>4.1</commons-collections4.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
127
jsonb/src/main/java/com/baeldung/jsonb/Person.java
Normal file
127
jsonb/src/main/java/com/baeldung/jsonb/Person.java
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
package com.baeldung.jsonb;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
import javax.json.bind.annotation.JsonbDateFormat;
|
||||||
|
import javax.json.bind.annotation.JsonbNumberFormat;
|
||||||
|
import javax.json.bind.annotation.JsonbProperty;
|
||||||
|
import javax.json.bind.annotation.JsonbTransient;
|
||||||
|
|
||||||
|
public class Person {
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
@JsonbProperty("person-name")
|
||||||
|
private String name;
|
||||||
|
@JsonbProperty(nillable = true)
|
||||||
|
private String email;
|
||||||
|
@JsonbTransient
|
||||||
|
private int age;
|
||||||
|
@JsonbDateFormat("dd-MM-yyyy")
|
||||||
|
private LocalDate registeredDate;
|
||||||
|
private BigDecimal salary;
|
||||||
|
|
||||||
|
public Person() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person(int id, String name, String email, int age, LocalDate registeredDate, BigDecimal salary) {
|
||||||
|
super();
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
this.email = email;
|
||||||
|
this.age = age;
|
||||||
|
this.registeredDate = registeredDate;
|
||||||
|
this.salary = salary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(int id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAge() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAge(int age) {
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonbNumberFormat(locale = "en_US", value = "#0.0")
|
||||||
|
public BigDecimal getSalary() {
|
||||||
|
return salary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSalary(BigDecimal salary) {
|
||||||
|
this.salary = salary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDate getRegisteredDate() {
|
||||||
|
return registeredDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRegisteredDate(LocalDate registeredDate) {
|
||||||
|
this.registeredDate = registeredDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
builder.append("Person [id=");
|
||||||
|
builder.append(id);
|
||||||
|
builder.append(", name=");
|
||||||
|
builder.append(name);
|
||||||
|
builder.append(", email=");
|
||||||
|
builder.append(email);
|
||||||
|
builder.append(", age=");
|
||||||
|
builder.append(age);
|
||||||
|
builder.append(", registeredDate=");
|
||||||
|
builder.append(registeredDate);
|
||||||
|
builder.append(", salary=");
|
||||||
|
builder.append(salary);
|
||||||
|
builder.append("]");
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + id;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
Person other = (Person) obj;
|
||||||
|
if (id != other.id)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
158
jsonb/src/test/java/com/baeldung/jsonb/JsonbTest.java
Normal file
158
jsonb/src/test/java/com/baeldung/jsonb/JsonbTest.java
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
package com.baeldung.jsonb;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.json.bind.Jsonb;
|
||||||
|
import javax.json.bind.JsonbBuilder;
|
||||||
|
import javax.json.bind.JsonbConfig;
|
||||||
|
import javax.json.bind.config.PropertyNamingStrategy;
|
||||||
|
import javax.json.bind.config.PropertyOrderStrategy;
|
||||||
|
|
||||||
|
import org.apache.commons.collections4.ListUtils;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class JsonbTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonList_whenSerializeWithJsonb_thenGetPersonJsonArray() {
|
||||||
|
Jsonb jsonb = JsonbBuilder.create();
|
||||||
|
// @formatter:off
|
||||||
|
List<Person> personList = Arrays.asList(
|
||||||
|
new Person(1, "Jhon", "jhon@test.com", 20, LocalDate.of(2019, 9, 9), BigDecimal.valueOf(1000)),
|
||||||
|
new Person(2, "Jhon", "jhon1@test.com", 20, LocalDate.of(2019, 9, 9), BigDecimal.valueOf(1500)),
|
||||||
|
new Person(3, "Jhon", null, 20, LocalDate.of(2019, 9, 9), BigDecimal.valueOf(1000)),
|
||||||
|
new Person(4, "Tom", "tom@test.com", 21, LocalDate.of(2019, 9, 9), BigDecimal.valueOf(1500)));
|
||||||
|
// @formatter:on
|
||||||
|
String jsonArrayPerson = jsonb.toJson(personList);
|
||||||
|
// @formatter:off
|
||||||
|
String jsonExpected = "[" +
|
||||||
|
"{\"email\":\"jhon@test.com\"," +
|
||||||
|
"\"id\":1,\"person-name\":\"Jhon\"," +
|
||||||
|
"\"registeredDate\":\"09-09-2019\"," +
|
||||||
|
"\"salary\":\"1000.0\"}," +
|
||||||
|
"{\"email\":\"jhon1@test.com\"," +
|
||||||
|
"\"id\":2,\"person-name\":\"Jhon\"," +
|
||||||
|
"\"registeredDate\":\"09-09-2019\"," +
|
||||||
|
"\"salary\":\"1500.0\"},{\"email\":null," +
|
||||||
|
"\"id\":3,\"person-name\":\"Jhon\"," +
|
||||||
|
"\"registeredDate\":\"09-09-2019\"," +
|
||||||
|
"\"salary\":\"1000.0\"}," +
|
||||||
|
"{\"email\":\"tom@test.com\"," +
|
||||||
|
"\"id\":4,\"person-name\":\"Tom\"," +
|
||||||
|
"\"registeredDate\":\"09-09-2019\"," +
|
||||||
|
"\"salary\":\"1500.0\"}"
|
||||||
|
+ "]";
|
||||||
|
// @formatter:on
|
||||||
|
assertTrue(jsonArrayPerson.equals(jsonExpected));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonJsonArray_whenDeserializeWithJsonb_thenGetPersonList() {
|
||||||
|
Jsonb jsonb = JsonbBuilder.create();
|
||||||
|
// @formatter:off
|
||||||
|
String personJsonArray =
|
||||||
|
"[" +
|
||||||
|
"{\"email\":\"jhon@test.com\"," +
|
||||||
|
"\"id\":1,\"person-name\":\"Jhon\"," +
|
||||||
|
"\"registeredDate\":\"09-09-2019\"," +
|
||||||
|
"\"salary\":\"1000.0\"}," +
|
||||||
|
"{\"email\":\"jhon1@test.com\"," +
|
||||||
|
"\"id\":2,\"person-name\":\"Jhon\"," +
|
||||||
|
"\"registeredDate\":\"09-09-2019\"," +
|
||||||
|
"\"salary\":\"1500.0\"},{\"email\":null," +
|
||||||
|
"\"id\":3,\"person-name\":\"Jhon\"," +
|
||||||
|
"\"registeredDate\":\"09-09-2019\"," +
|
||||||
|
"\"salary\":\"1000.0\"}," +
|
||||||
|
"{\"email\":\"tom@test.com\"," +
|
||||||
|
"\"id\":4,\"person-name\":\"Tom\"," +
|
||||||
|
"\"registeredDate\":\"09-09-2019\"," +
|
||||||
|
"\"salary\":\"1500.0\"}"
|
||||||
|
+ "]";
|
||||||
|
// @formatter:on
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
List<Person> personList = jsonb.fromJson(personJsonArray, new ArrayList<Person>() {
|
||||||
|
}.getClass()
|
||||||
|
.getGenericSuperclass());
|
||||||
|
// @formatter:off
|
||||||
|
List<Person> personListExpected = Arrays.asList(
|
||||||
|
new Person(1, "Jhon", "jhon@test.com", 20, LocalDate.of(2019, 9, 9), BigDecimal.valueOf(1000)),
|
||||||
|
new Person(2, "Jhon", "jhon1@test.com", 20, LocalDate.of(2019, 9, 9), BigDecimal.valueOf(1500)),
|
||||||
|
new Person(3, "Jhon", null, 20, LocalDate.of(2019, 9, 9), BigDecimal.valueOf(1000)),
|
||||||
|
new Person(4, "Tom", "tom@test.com", 21, LocalDate.of(2019, 9, 9), BigDecimal.valueOf(1500)));
|
||||||
|
// @formatter:on
|
||||||
|
assertTrue(ListUtils.isEqualList(personList, personListExpected));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonObject_whenNamingStrategy_thenGetCustomPersonJson() {
|
||||||
|
JsonbConfig config = new JsonbConfig().withPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE_WITH_UNDERSCORES);
|
||||||
|
Jsonb jsonb = JsonbBuilder.create(config);
|
||||||
|
Person person = new Person(1, "Jhon", "jhon@test.com", 20, LocalDate.of(2019, 9, 7), BigDecimal.valueOf(1000));
|
||||||
|
String jsonPerson = jsonb.toJson(person);
|
||||||
|
// @formatter:off
|
||||||
|
String jsonExpected =
|
||||||
|
"{\"email\":\"jhon@test.com\"," +
|
||||||
|
"\"id\":1," +
|
||||||
|
"\"person-name\":\"Jhon\"," +
|
||||||
|
"\"registered_date\":\"07-09-2019\"," +
|
||||||
|
"\"salary\":\"1000.0\"}";
|
||||||
|
// @formatter:on
|
||||||
|
assertTrue(jsonExpected.equals(jsonPerson));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonObject_whenWithPropertyOrderStrategy_thenGetReversePersonJson() {
|
||||||
|
JsonbConfig config = new JsonbConfig().withPropertyOrderStrategy(PropertyOrderStrategy.REVERSE);
|
||||||
|
Jsonb jsonb = JsonbBuilder.create(config);
|
||||||
|
Person person = new Person(1, "Jhon", "jhon@test.com", 20, LocalDate.of(2019, 9, 7), BigDecimal.valueOf(1000));
|
||||||
|
String jsonPerson = jsonb.toJson(person);
|
||||||
|
// @formatter:off
|
||||||
|
String jsonExpected =
|
||||||
|
"{\"salary\":\"1000.0\","+
|
||||||
|
"\"registeredDate\":\"07-09-2019\"," +
|
||||||
|
"\"person-name\":\"Jhon\"," +
|
||||||
|
"\"id\":1," +
|
||||||
|
"\"email\":\"jhon@test.com\"}";
|
||||||
|
// @formatter:on
|
||||||
|
assertTrue(jsonExpected.equals(jsonPerson));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonObject_whenSerializeWithJsonb_thenGetPersonJson() {
|
||||||
|
Jsonb jsonb = JsonbBuilder.create();
|
||||||
|
Person person = new Person(1, "Jhon", "jhon@test.com", 20, LocalDate.of(2019, 9, 7), BigDecimal.valueOf(1000));
|
||||||
|
String jsonPerson = jsonb.toJson(person);
|
||||||
|
// @formatter:off
|
||||||
|
String jsonExpected =
|
||||||
|
"{\"email\":\"jhon@test.com\"," +
|
||||||
|
"\"id\":1," +
|
||||||
|
"\"person-name\":\"Jhon\"," +
|
||||||
|
"\"registeredDate\":\"07-09-2019\"," +
|
||||||
|
"\"salary\":\"1000.0\"}";
|
||||||
|
// @formatter:on
|
||||||
|
assertTrue(jsonExpected.equals(jsonPerson));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPersonJson_whenDeserializeWithJsonb_thenGetPersonObject() {
|
||||||
|
Jsonb jsonb = JsonbBuilder.create();
|
||||||
|
Person person = new Person(1, "Jhon", "jhon@test.com", 0, LocalDate.of(2019, 9, 7), BigDecimal.valueOf(1000.0));
|
||||||
|
// @formatter:off
|
||||||
|
String jsonPerson =
|
||||||
|
"{\"email\":\"jhon@test.com\"," +
|
||||||
|
"\"id\":1," +
|
||||||
|
"\"person-name\":\"Jhon\"," +
|
||||||
|
"\"registeredDate\":\"07-09-2019\"," +
|
||||||
|
"\"salary\":\"1000.0\"}";
|
||||||
|
// @formatter:on
|
||||||
|
assertTrue(jsonb.fromJson(jsonPerson, Person.class)
|
||||||
|
.equals(person));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,32 +1,31 @@
|
|||||||
package com.baeldung.templatemethodpattern.model;
|
package com.baeldung.templatemethodpattern.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public abstract class Computer {
|
public abstract class Computer {
|
||||||
|
|
||||||
protected Map<String, String> computerParts = new HashMap<>();
|
protected Map<String, String> computerParts = new HashMap<>();
|
||||||
|
protected List<String> moterboardSetupStatus = new ArrayList<>();
|
||||||
|
|
||||||
public final void buildComputer() {
|
public final void buildComputer() {
|
||||||
addMotherboard();
|
addMotherboard();
|
||||||
|
setupMotherboard();
|
||||||
addProcessor();
|
addProcessor();
|
||||||
addMemory();
|
|
||||||
addHardDrive();
|
|
||||||
addGraphicCard();
|
|
||||||
addSoundCard();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void addProcessor();
|
|
||||||
|
|
||||||
public abstract void addMotherboard();
|
public abstract void addMotherboard();
|
||||||
|
|
||||||
public abstract void addMemory();
|
public abstract void setupMotherboard();
|
||||||
|
|
||||||
public abstract void addHardDrive();
|
public abstract void addProcessor();
|
||||||
|
|
||||||
public abstract void addGraphicCard();
|
public List<String> getMotherboardSetupStatus() {
|
||||||
|
return moterboardSetupStatus;
|
||||||
public abstract void addSoundCard();
|
}
|
||||||
|
|
||||||
public Map<String, String> getComputerParts() {
|
public Map<String, String> getComputerParts() {
|
||||||
return computerParts;
|
return computerParts;
|
||||||
|
@ -2,33 +2,25 @@ package com.baeldung.templatemethodpattern.model;
|
|||||||
|
|
||||||
public class HighEndComputer extends Computer {
|
public class HighEndComputer extends Computer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addMotherboard() {
|
||||||
|
computerParts.put("Motherboard", "High-end Motherboard");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setupMotherboard() {
|
||||||
|
moterboardSetupStatus.add("Screwing the high-end motherboard to the case.");
|
||||||
|
moterboardSetupStatus.add("Pluging in the power supply connectors.");
|
||||||
|
moterboardSetupStatus.forEach(step -> System.out.println(step));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addProcessor() {
|
public void addProcessor() {
|
||||||
computerParts.put("Processor", "High End Processor");
|
computerParts.put("Processor", "High-end Processor");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addMotherboard() {
|
public void addMotherboard() {
|
||||||
computerParts.put("Motherboard", "High End Motherboard");
|
computerParts.put("Motherboard", "High End Motherboard");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addMemory() {
|
|
||||||
computerParts.put("Memory", "16GB");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addHardDrive() {
|
|
||||||
computerParts.put("Hard Drive", "2TB Hard Drive");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addGraphicCard() {
|
|
||||||
computerParts.put("Graphic Card", "High End Graphic Card");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addSoundCard() {
|
|
||||||
computerParts.put("Sound Card", "High End Sound Card");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,17 @@ package com.baeldung.templatemethodpattern.model;
|
|||||||
|
|
||||||
public class StandardComputer extends Computer {
|
public class StandardComputer extends Computer {
|
||||||
|
|
||||||
|
public void addMotherboard() {
|
||||||
|
computerParts.put("Motherboard", "Standard Motherboard");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setupMotherboard() {
|
||||||
|
moterboardSetupStatus.add("Screwing the standard motherboard to the case.");
|
||||||
|
moterboardSetupStatus.add("Pluging in the power supply connectors.");
|
||||||
|
moterboardSetupStatus.forEach(step -> System.out.println(step));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addProcessor() {
|
public void addProcessor() {
|
||||||
computerParts.put("Processor", "Standard Processor");
|
computerParts.put("Processor", "Standard Processor");
|
||||||
@ -11,24 +22,4 @@ public class StandardComputer extends Computer {
|
|||||||
public void addMotherboard() {
|
public void addMotherboard() {
|
||||||
computerParts.put("Motherboard", "Standard Motherboard");
|
computerParts.put("Motherboard", "Standard Motherboard");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addMemory() {
|
|
||||||
computerParts.put("Memory", "8GB");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addHardDrive() {
|
|
||||||
computerParts.put("Hard Drive", "1TB Hard Drive");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addGraphicCard() {
|
|
||||||
computerParts.put("Graphic Card", "Standard Graphic Card");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addSoundCard() {
|
|
||||||
computerParts.put("Sound Card", "Standard Sound Card");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.baeldung.templatemethodpatterntest;
|
|||||||
import com.baeldung.templatemethodpattern.model.HighEndComputer;
|
import com.baeldung.templatemethodpattern.model.HighEndComputer;
|
||||||
import com.baeldung.templatemethodpattern.model.StandardComputer;
|
import com.baeldung.templatemethodpattern.model.StandardComputer;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -21,100 +22,53 @@ public class TemplateMethodPatternTest {
|
|||||||
highEndComputer = new HighEndComputer();
|
highEndComputer = new HighEndComputer();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void givenStandardProcessor_whenAddingProcessor_thenEqualAssertion() {
|
|
||||||
standardComputer.addProcessor();
|
|
||||||
Assert.assertEquals("Standard Processor", standardComputer
|
|
||||||
.getComputerParts().get("Processor"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenStandardMotherBoard_whenAddingMotherBoard_thenEqualAssertion() {
|
public void givenStandardMotherBoard_whenAddingMotherBoard_thenEqualAssertion() {
|
||||||
standardComputer.addMotherboard();
|
standardComputer.addMotherboard();
|
||||||
Assert.assertEquals("Standard Motherboard", standardComputer
|
assertEquals("Standard Motherboard", standardComputer.getComputerParts().get("Motherboard"));
|
||||||
.getComputerParts().get("Motherboard"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenStandardMemory_whenAddingMemory_thenEqualAssertion() {
|
public void givenStandardMotheroboard_whenSetup_thenTwoEqualAssertions() {
|
||||||
standardComputer.addMemory();
|
standardComputer.setupMotherboard();
|
||||||
Assert.assertEquals("8GB", standardComputer
|
assertEquals("Screwing the standard motherboard to the case.", standardComputer.getMotherboardSetupStatus().get(0));
|
||||||
.getComputerParts().get("Memory"));
|
assertEquals("Plugin in the power supply connectors.", standardComputer.getMotherboardSetupStatus().get(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenStandardHardDrive_whenAddingHardDrive_thenEqualAssertion() {
|
public void givenStandardProcessor_whenAddingProcessor_thenEqualAssertion() {
|
||||||
standardComputer.addHardDrive();
|
standardComputer.addProcessor();
|
||||||
Assert.assertEquals("1TB Hard Drive", standardComputer
|
assertEquals("Standard Processor", standardComputer.getComputerParts().get("Processor"));
|
||||||
.getComputerParts().get("Hard Drive"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenStandardGraphicaCard_whenAddingGraphicCard_thenEqualAssertion() {
|
public void givenAllStandardParts_whenBuildingComputer_thenTwoParts() {
|
||||||
standardComputer.addGraphicCard();
|
|
||||||
Assert.assertEquals("Standard Graphic Card", standardComputer
|
|
||||||
.getComputerParts().get("Graphic Card"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void givenStandardSoundCard_whenAddingSoundCard_thenEqualAssertion() {
|
|
||||||
standardComputer.addSoundCard();
|
|
||||||
Assert.assertEquals("Standard Sound Card", standardComputer
|
|
||||||
.getComputerParts().get("Sound Card"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void givenAllStandardParts_whenBuildingComputer_thenSixParts() {
|
|
||||||
standardComputer.buildComputer();
|
standardComputer.buildComputer();
|
||||||
Assert.assertEquals(6, standardComputer
|
assertEquals(2, standardComputer.getComputerParts().size());
|
||||||
.getComputerParts().size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void givenHightEndProcessor_whenAddingProcessor_thenEqualAssertion() {
|
|
||||||
highEndComputer.addProcessor();
|
|
||||||
Assert.assertEquals("High End Processor", highEndComputer
|
|
||||||
.getComputerParts().get("Processor"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenHighEnddMotherBoard_whenAddingMotherBoard_thenEqualAssertion() {
|
public void givenHighEnddMotherBoard_whenAddingMotherBoard_thenEqualAssertion() {
|
||||||
highEndComputer.addMotherboard();
|
highEndComputer.addMotherboard();
|
||||||
Assert.assertEquals("High End Motherboard", highEndComputer
|
Assert.assertEquals("High-end Motherboard", highEndComputer.getComputerParts().get("Motherboard"));
|
||||||
.getComputerParts().get("Motherboard"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenHighEndMemory_whenAddingMemory_thenEqualAssertion() {
|
public void givenHighEnddMotheroboard_whenSetup_thenTwoEqualAssertions() {
|
||||||
highEndComputer.addMemory();
|
highEndComputer.setupMotherboard();
|
||||||
Assert.assertEquals("16GB", highEndComputer
|
assertEquals("Screwing the high-end motherboard to the case.", highEndComputer.getMotherboardSetupStatus().get(0));
|
||||||
.getComputerParts().get("Memory"));
|
assertEquals("Plugin in the power supply connectors.", highEndComputer.getMotherboardSetupStatus().get(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenHighEndHardDrive_whenAddingHardDrive_thenEqualAssertion() {
|
public void givenHightEndProcessor_whenAddingProcessor_thenEqualAssertion() {
|
||||||
highEndComputer.addHardDrive();
|
highEndComputer.addProcessor();
|
||||||
Assert.assertEquals("2TB Hard Drive", highEndComputer
|
Assert.assertEquals("High-end Processor", highEndComputer.getComputerParts().get("Processor"));
|
||||||
.getComputerParts().get("Hard Drive"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenHighEndGraphicCard_whenAddingGraphicCard_thenEqualAssertion() {
|
public void givenAllHighEnddParts_whenBuildingComputer_thenTwoParts() {
|
||||||
highEndComputer.addGraphicCard();
|
|
||||||
Assert.assertEquals("High End Graphic Card", highEndComputer
|
|
||||||
.getComputerParts().get("Graphic Card"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void givenHighEndSoundCard_whenAddingSoundCard_thenEqualAssertion() {
|
|
||||||
highEndComputer.addSoundCard();
|
|
||||||
Assert.assertEquals("High End Sound Card", highEndComputer
|
|
||||||
.getComputerParts().get("Sound Card"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void givenAllHighEndParts_whenBuildingComputer_thenSixParts() {
|
|
||||||
highEndComputer.buildComputer();
|
highEndComputer.buildComputer();
|
||||||
Assert.assertEquals(6, highEndComputer.getComputerParts().size());
|
assertEquals(2, highEndComputer.getComputerParts().size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,18 @@
|
|||||||
<artifactId>javax.json.bind-api</artifactId>
|
<artifactId>javax.json.bind-api</artifactId>
|
||||||
<version>${jsonb-api.version}</version>
|
<version>${jsonb-api.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- Dependencies for Yasson -->
|
||||||
|
<!-- <dependency> -->
|
||||||
|
<!-- <groupId>org.eclipse</groupId> -->
|
||||||
|
<!-- <artifactId>yasson</artifactId> -->
|
||||||
|
<!-- <version>1.0</version> -->
|
||||||
|
<!-- </dependency> -->
|
||||||
|
<!-- <dependency> -->
|
||||||
|
<!-- <groupId>org.glassfish</groupId> -->
|
||||||
|
<!-- <artifactId>javax.json</artifactId> -->
|
||||||
|
<!-- <version>1.1.2</version> -->
|
||||||
|
<!-- </dependency> -->
|
||||||
|
<!-- Dependencies for Johnzon -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.geronimo.specs</groupId>
|
<groupId>org.apache.geronimo.specs</groupId>
|
||||||
<artifactId>geronimo-json_1.1_spec</artifactId>
|
<artifactId>geronimo-json_1.1_spec</artifactId>
|
||||||
@ -88,6 +100,13 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-collections4</artifactId>
|
||||||
|
<version>4.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
<artifactId>junit-jupiter-api</artifactId>
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
package com.baeldung.jsonb;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDate;
|
|
||||||
|
|
||||||
import javax.json.bind.Jsonb;
|
|
||||||
import javax.json.bind.JsonbBuilder;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class JsonbTest {
|
|
||||||
|
|
||||||
private Jsonb jsonb;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setup() {
|
|
||||||
jsonb = JsonbBuilder.create();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void givenPersonObject_whenSerializeWithJsonb_thenGetPersonJson() {
|
|
||||||
Person person = new Person(1, "Jhon", "jhon@test.com", 20, LocalDate.of(2019, 9, 7), BigDecimal.valueOf(1000));
|
|
||||||
String jsonPerson = jsonb.toJson(person);
|
|
||||||
assertTrue("{\"email\":\"jhon@test.com\",\"id\":1,\"person-name\":\"Jhon\",\"registeredDate\":\"07-09-2019\",\"salary\":\"1000.0\"}".equals(jsonPerson));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void givenPersonJson_whenDeserializeWithJsonb_thenGetPersonObject() {
|
|
||||||
Person person = new Person(1, "Jhon", "jhon@test.com", 0, LocalDate.of(2019, 9, 7), BigDecimal.valueOf(1000.0));
|
|
||||||
String jsonPerson = "{\"email\":\"jhon@test.com\",\"id\":1,\"person-name\":\"Jhon\",\"registeredDate\":\"07-09-2019\",\"salary\":\"1000.0\"}";
|
|
||||||
assertTrue(jsonb.fromJson(jsonPerson, Person.class)
|
|
||||||
.equals(person));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,29 @@
|
|||||||
|
package org.baeldung.dsrouting;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Database access code for datasource routing example.
|
||||||
|
*/
|
||||||
|
public class ClientDao {
|
||||||
|
|
||||||
|
private static final String SQL_GET_CLIENT_NAME = "select name from client";
|
||||||
|
|
||||||
|
private final JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
public ClientDao(DataSource datasource) {
|
||||||
|
this.jdbcTemplate = new JdbcTemplate(datasource);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientName() {
|
||||||
|
return this.jdbcTemplate.query(SQL_GET_CLIENT_NAME, rowMapper)
|
||||||
|
.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RowMapper<String> rowMapper = (rs, rowNum) -> {
|
||||||
|
return rs.getString("name");
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package org.baeldung.dsrouting;
|
||||||
|
|
||||||
|
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns thread bound client lookup key for current context.
|
||||||
|
*/
|
||||||
|
public class ClientDataSourceRouter extends AbstractRoutingDataSource {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object determineCurrentLookupKey() {
|
||||||
|
return ClientDatabaseContextHolder.getClientDatabase();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package org.baeldung.dsrouting;
|
||||||
|
|
||||||
|
public enum ClientDatabase {
|
||||||
|
|
||||||
|
ACME_WIDGETS, WIDGETS_ARE_US, WIDGET_DEPOT
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package org.baeldung.dsrouting;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread shared context to point to the datasource which should be used. This
|
||||||
|
* enables context switches between different clients.
|
||||||
|
*/
|
||||||
|
public class ClientDatabaseContextHolder {
|
||||||
|
|
||||||
|
private static final ThreadLocal<ClientDatabase> CONTEXT = new ThreadLocal<>();
|
||||||
|
|
||||||
|
public static void set(ClientDatabase clientDatabase) {
|
||||||
|
Assert.notNull(clientDatabase, "clientDatabase cannot be null");
|
||||||
|
CONTEXT.set(clientDatabase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ClientDatabase getClientDatabase() {
|
||||||
|
return CONTEXT.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clear() {
|
||||||
|
CONTEXT.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package org.baeldung.dsrouting;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Service layer code for datasource routing example. Here, the service methods are responsible
|
||||||
|
* for setting and clearing the context.
|
||||||
|
*/
|
||||||
|
public class ClientService {
|
||||||
|
|
||||||
|
private final ClientDao clientDao;
|
||||||
|
|
||||||
|
public ClientService(ClientDao clientDao) {
|
||||||
|
this.clientDao = clientDao;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientName(ClientDatabase clientDb) {
|
||||||
|
ClientDatabaseContextHolder.set(clientDb);
|
||||||
|
String clientName = this.clientDao.getClientName();
|
||||||
|
ClientDatabaseContextHolder.clear();
|
||||||
|
return clientName;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package org.baeldung.dsrouting;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
|
||||||
|
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||||
|
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class DataSourceRoutingTestConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ClientService clientService() {
|
||||||
|
return new ClientService(new ClientDao(clientDatasource()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DataSource clientDatasource() {
|
||||||
|
Map<Object, Object> targetDataSources = new HashMap<>();
|
||||||
|
DataSource acmeWidgetsDatasource = acmeWidgetsDatasource();
|
||||||
|
DataSource widgetsAreUsDatasource = widgetsAreUsDatasource();
|
||||||
|
DataSource widgetsDepotDatasource = widgetsDepotDatasource();
|
||||||
|
targetDataSources.put(ClientDatabase.ACME_WIDGETS, acmeWidgetsDatasource);
|
||||||
|
targetDataSources.put(ClientDatabase.WIDGETS_ARE_US, widgetsAreUsDatasource);
|
||||||
|
targetDataSources.put(ClientDatabase.WIDGET_DEPOT, widgetsDepotDatasource);
|
||||||
|
|
||||||
|
ClientDataSourceRouter clientRoutingDatasource = new ClientDataSourceRouter();
|
||||||
|
clientRoutingDatasource.setTargetDataSources(targetDataSources);
|
||||||
|
clientRoutingDatasource.setDefaultTargetDataSource(acmeWidgetsDatasource);
|
||||||
|
return clientRoutingDatasource;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataSource acmeWidgetsDatasource() {
|
||||||
|
EmbeddedDatabaseBuilder dbBuilder = new EmbeddedDatabaseBuilder();
|
||||||
|
EmbeddedDatabase embeddedDb = dbBuilder.setType(EmbeddedDatabaseType.H2)
|
||||||
|
.setName("ACMEWIDGETS")
|
||||||
|
.addScript("classpath:dsrouting-db.sql")
|
||||||
|
.build();
|
||||||
|
return embeddedDb;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataSource widgetsAreUsDatasource() {
|
||||||
|
EmbeddedDatabaseBuilder dbBuilder = new EmbeddedDatabaseBuilder();
|
||||||
|
EmbeddedDatabase embeddedDb = dbBuilder.setType(EmbeddedDatabaseType.H2)
|
||||||
|
.setName("WIDGETSAREUS")
|
||||||
|
.addScript("classpath:dsrouting-db.sql")
|
||||||
|
.build();
|
||||||
|
return embeddedDb;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DataSource widgetsDepotDatasource() {
|
||||||
|
EmbeddedDatabaseBuilder dbBuilder = new EmbeddedDatabaseBuilder();
|
||||||
|
EmbeddedDatabase embeddedDb = dbBuilder.setType(EmbeddedDatabaseType.H2)
|
||||||
|
.setName("WIDGETDEPOT")
|
||||||
|
.addScript("classpath:dsrouting-db.sql")
|
||||||
|
.build();
|
||||||
|
return embeddedDb;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
package org.baeldung.dsrouting;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@ContextConfiguration(classes = DataSourceRoutingTestConfiguration.class)
|
||||||
|
public class DataSourceRoutingTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
DataSource routingDatasource;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ClientService clientService;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
final String SQL_ACME_WIDGETS = "insert into client (id, name) values (1, 'ACME WIDGETS')";
|
||||||
|
final String SQL_WIDGETS_ARE_US = "insert into client (id, name) values (2, 'WIDGETS ARE US')";
|
||||||
|
final String SQL_WIDGET_DEPOT = "insert into client (id, name) values (3, 'WIDGET DEPOT')";
|
||||||
|
|
||||||
|
JdbcTemplate jdbcTemplate = new JdbcTemplate();
|
||||||
|
jdbcTemplate.setDataSource(routingDatasource);
|
||||||
|
|
||||||
|
ClientDatabaseContextHolder.set(ClientDatabase.ACME_WIDGETS);
|
||||||
|
jdbcTemplate.execute(SQL_ACME_WIDGETS);
|
||||||
|
ClientDatabaseContextHolder.clear();
|
||||||
|
|
||||||
|
ClientDatabaseContextHolder.set(ClientDatabase.WIDGETS_ARE_US);
|
||||||
|
jdbcTemplate.execute(SQL_WIDGETS_ARE_US);
|
||||||
|
ClientDatabaseContextHolder.clear();
|
||||||
|
|
||||||
|
ClientDatabaseContextHolder.set(ClientDatabase.WIDGET_DEPOT);
|
||||||
|
jdbcTemplate.execute(SQL_WIDGET_DEPOT);
|
||||||
|
ClientDatabaseContextHolder.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenClientDbs_whenContextsSwitch_thenRouteToCorrectDatabase() throws Exception {
|
||||||
|
|
||||||
|
// test ACME WIDGETS
|
||||||
|
String clientName = clientService.getClientName(ClientDatabase.ACME_WIDGETS);
|
||||||
|
assertEquals(clientName, "ACME WIDGETS");
|
||||||
|
|
||||||
|
// test WIDGETS_ARE_US
|
||||||
|
clientName = clientService.getClientName(ClientDatabase.WIDGETS_ARE_US);
|
||||||
|
assertEquals(clientName, "WIDGETS ARE US");
|
||||||
|
|
||||||
|
// test WIDGET_DEPOT
|
||||||
|
clientName = clientService.getClientName(ClientDatabase.WIDGET_DEPOT);
|
||||||
|
assertEquals(clientName, "WIDGET DEPOT");
|
||||||
|
}
|
||||||
|
}
|
5
spring-boot/src/test/resources/dsrouting-db.sql
Normal file
5
spring-boot/src/test/resources/dsrouting-db.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
create table client (
|
||||||
|
id numeric,
|
||||||
|
name varchar(50),
|
||||||
|
constraint pk_client primary key (id)
|
||||||
|
);
|
Loading…
x
Reference in New Issue
Block a user