Merge pull request #52 from eugenp/master

update
This commit is contained in:
Maiklins 2020-05-10 22:47:09 +02:00 committed by GitHub
commit 03d74d627f
61 changed files with 1181 additions and 40 deletions

View File

@ -1,7 +1,6 @@
## Atomikos
This module contains articles about Atomikos
### Relevant Articles:
- [Guide Transactions Using Atomikos]()
- [A Guide to Atomikos](https://www.baeldung.com/java-atomikos)

View File

@ -1,3 +0,0 @@
### Relevant Articles:
- [Building Java Applications with Bazel](https://www.baeldung.com/bazel-build-tool)

View File

@ -12,4 +12,5 @@ This module contains articles about core Groovy concepts
- [Closures in Groovy](https://www.baeldung.com/groovy-closures)
- [Converting a String to a Date in Groovy](https://www.baeldung.com/groovy-string-to-date)
- [Guide to I/O in Groovy](https://www.baeldung.com/groovy-io)
- [[More -->]](/core-groovy-2)
- [Convert String to Integer in Groovy](https://www.baeldung.com/groovy-convert-string-to-integer)
- [[More -->]](/core-groovy-2)

View File

@ -0,0 +1,84 @@
package com.baeldung.java14.foreign.api;
import jdk.incubator.foreign.*;
import org.junit.Test;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import java.lang.invoke.VarHandle;
import java.nio.ByteOrder;
public class ForeignMemoryUnitTest {
@Test
public void whenAValueIsSet_thenAccessTheValue() {
long value = 10;
MemoryAddress memoryAddress =
MemorySegment.allocateNative(8).baseAddress();
VarHandle varHandle = MemoryHandles.varHandle(long.class,
ByteOrder.nativeOrder());
varHandle.set(memoryAddress, value);
assertThat(varHandle.get(memoryAddress), is(value));
}
@Test
public void whenMultipleValuesAreSet_thenAccessAll() {
VarHandle varHandle = MemoryHandles.varHandle(int.class,
ByteOrder.nativeOrder());
try(MemorySegment memorySegment =
MemorySegment.allocateNative(100)) {
MemoryAddress base = memorySegment.baseAddress();
for(int i=0; i<25; i++) {
varHandle.set(base.addOffset((i*4)), i);
}
for(int i=0; i<25; i++) {
assertThat(varHandle.get(base.addOffset((i*4))), is(i));
}
}
}
@Test
public void whenSetValuesWithMemoryLayout_thenTheyCanBeRetrieved() {
SequenceLayout sequenceLayout =
MemoryLayout.ofSequence(25,
MemoryLayout.ofValueBits(64, ByteOrder.nativeOrder()));
VarHandle varHandle =
sequenceLayout.varHandle(long.class,
MemoryLayout.PathElement.sequenceElement());
try(MemorySegment memorySegment =
MemorySegment.allocateNative(sequenceLayout)) {
MemoryAddress base = memorySegment.baseAddress();
for(long i=0; i<sequenceLayout.elementCount().getAsLong(); i++) {
varHandle.set(base, i, i);
}
for(long i=0; i<sequenceLayout.elementCount().getAsLong(); i++) {
assertThat(varHandle.get(base, i), is(i));
}
}
}
@Test
public void whenSlicingMemorySegment_thenTheyCanBeAccessedIndividually() {
MemoryAddress memoryAddress =
MemorySegment.allocateNative(12).baseAddress();
MemoryAddress memoryAddress1 =
memoryAddress.segment().asSlice(0,4).baseAddress();
MemoryAddress memoryAddress2 =
memoryAddress.segment().asSlice(4,4).baseAddress();
MemoryAddress memoryAddress3 =
memoryAddress.segment().asSlice(8,4).baseAddress();
VarHandle intHandle =
MemoryHandles.varHandle(int.class, ByteOrder.nativeOrder());
intHandle.set(memoryAddress1, Integer.MIN_VALUE);
intHandle.set(memoryAddress2, 0);
intHandle.set(memoryAddress3, Integer.MAX_VALUE);
assertThat(intHandle.get(memoryAddress1), is(Integer.MIN_VALUE));
assertThat(intHandle.get(memoryAddress2), is(0));
assertThat(intHandle.get(memoryAddress3), is(Integer.MAX_VALUE));
}
}

View File

@ -5,4 +5,5 @@ This module contains articles about Map data structures in Java.
### Relevant Articles:
- [Java TreeMap vs HashMap](https://www.baeldung.com/java-treemap-vs-hashmap)
- [Comparing Two HashMaps in Java](https://www.baeldung.com/java-compare-hashmaps)
- [The Map.computeIfAbsent() Method](https://www.baeldung.com/java-map-computeifabsent)
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-2)

View File

@ -4,5 +4,5 @@
### Relevant Articles:
- [Using a Mutex Object in Java](https://www.baeldung.com/java-mutex)
- [Testing Multi-Threaded Code in Java] (https://www.baeldung.com/java-testing-multithreaded)
- [Testing Multi-Threaded Code in Java](https://www.baeldung.com/java-testing-multithreaded)

View File

@ -0,0 +1,81 @@
package com.baeldung.lockfree;
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class NonBlockingQueue<T> {
private final AtomicReference<Node<T>> head, tail;
private final AtomicInteger size;
public NonBlockingQueue() {
head = new AtomicReference<>(null);
tail = new AtomicReference<>(null);
size = new AtomicInteger();
size.set(0);
}
public void add(T element) {
if (element == null) {
throw new NullPointerException();
}
Node<T> node = new Node<>(element);
Node<T> currentTail;
do {
currentTail = tail.get();
node.setPrevious(currentTail);
} while(!tail.compareAndSet(currentTail, node));
if(node.previous != null) {
node.previous.next = node;
}
head.compareAndSet(null, node); //if we are inserting the first element
size.incrementAndGet();
}
public T get() {
if(head.get() == null) {
throw new NoSuchElementException();
}
Node<T> currentHead;
Node<T> nextNode;
do {
currentHead = head.get();
nextNode = currentHead.getNext();
} while(!head.compareAndSet(currentHead, nextNode));
size.decrementAndGet();
return currentHead.getValue();
}
public int size() {
return this.size.get();
}
private class Node<T> {
private final T value;
private volatile Node<T> next;
private volatile Node<T> previous;
public Node(T value) {
this.value = value;
this.next = null;
}
public T getValue() {
return value;
}
public Node<T> getNext() {
return next;
}
public void setPrevious(Node<T> previous) {
this.previous = previous;
}
}
}

View File

@ -11,4 +11,5 @@ This module contains articles about networking in Java
- [Sending Emails with Java](https://www.baeldung.com/java-email)
- [Authentication with HttpUrlConnection](https://www.baeldung.com/java-http-url-connection)
- [Download a File from an URL in Java](https://www.baeldung.com/java-download-file)
- [Handling java.net.ConnectException](https://www.baeldung.com/java-net-connectexception)
- [[<-- Prev]](/core-java-modules/core-java-networking)

View File

@ -26,7 +26,6 @@ public class RegexUnitTest {
while (matcher.find())
matches++;
assertEquals(matches, 2);
}
@Test
@ -452,7 +451,6 @@ public class RegexUnitTest {
Matcher matcher = pattern.matcher("dogs are friendly");
assertTrue(matcher.lookingAt());
assertFalse(matcher.matches());
}
@Test
@ -460,7 +458,6 @@ public class RegexUnitTest {
Pattern pattern = Pattern.compile("dog");
Matcher matcher = pattern.matcher("dog");
assertTrue(matcher.matches());
}
@Test
@ -469,7 +466,6 @@ public class RegexUnitTest {
Matcher matcher = pattern.matcher("dogs are domestic animals, dogs are friendly");
String newStr = matcher.replaceFirst("cat");
assertEquals("cats are domestic animals, dogs are friendly", newStr);
}
@Test
@ -478,7 +474,6 @@ public class RegexUnitTest {
Matcher matcher = pattern.matcher("dogs are domestic animals, dogs are friendly");
String newStr = matcher.replaceAll("cat");
assertEquals("cats are domestic animals, cats are friendly", newStr);
}
public synchronized static int runTest(String regex, String text) {

View File

@ -0,0 +1,129 @@
package com.baeldung.regex.phonenumbers;
import static org.junit.Assert.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.Test;
public class PhoneNumbersRegexUnitTest {
@Test
public void whenMatchesTenDigitsNumber_thenCorrect() {
Pattern pattern = Pattern.compile("^\\d{10}$");
Matcher matcher = pattern.matcher("2055550125");
assertTrue(matcher.matches());
}
@Test
public void whenMOreThanTenDigits_thenNotCorrect() {
Pattern pattern = Pattern.compile("^\\d{10}$");
Matcher matcher = pattern.matcher("20555501251");
assertFalse(matcher.matches());
}
@Test
public void whenMatchesTenDigitsNumberWhitespacesDotHyphen_thenCorrect() {
Pattern pattern = Pattern.compile("^(\\d{3}[- .]?){2}\\d{4}$");
Matcher matcher = pattern.matcher("202 555 0125");
assertTrue(matcher.matches());
}
@Test
public void whenIncludesBracket_thenNotCorrect() {
Pattern pattern = Pattern.compile("^(\\d{3}[- .]?){2}\\d{4}$");
Matcher matcher = pattern.matcher("202]555 0125");
assertFalse(matcher.matches());
}
@Test
public void whenNotStartsWithBatchesOfThreeDigits_thenNotCorrect() {
Pattern pattern = Pattern.compile("^(\\d{3}[- .]?){2}\\d{4}$");
Matcher matcher = pattern.matcher("2021 555 0125");
assertFalse(matcher.matches());
}
@Test
public void whenLastPartWithNoFourDigits_thenNotCorrect() {
Pattern pattern = Pattern.compile("^(\\d{3}[- .]?){2}\\d{4}$");
Matcher matcher = pattern.matcher("202 555 012");
assertFalse(matcher.matches());
}
@Test
public void whenMatchesTenDigitsNumberParenthesis_thenCorrect() {
Pattern pattern = Pattern.compile("^((\\(\\d{3}\\))|\\d{3})[- .]?\\d{3}[- .]?\\d{4}$");
Matcher matcher = pattern.matcher("(202) 555-0125");
assertTrue(matcher.matches());
}
@Test
public void whenJustOpeningParenthesis_thenNotCorrect() {
Pattern pattern = Pattern.compile("^((\\(\\d{3}\\))|\\d{3})[- .]?\\d{3}[- .]?\\d{4}$");
Matcher matcher = pattern.matcher("(202 555-0125");
assertFalse(matcher.matches());
}
@Test
public void whenJustClosingParenthesis_thenNotCorrect() {
Pattern pattern = Pattern.compile("^((\\(\\d{3}\\))|\\d{3})[- .]?\\d{3}[- .]?\\d{4}$");
Matcher matcher = pattern.matcher("202) 555-0125");
assertFalse(matcher.matches());
}
@Test
public void whenMatchesTenDigitsNumberPrefix_thenCorrect() {
Pattern pattern = Pattern.compile("^(\\+\\d{1,3}( )?)?((\\(\\d{3}\\))|\\d{3})[- .]?\\d{3}[- .]?\\d{4}$");
Matcher matcher = pattern.matcher("+111 (202) 555-0125");
assertTrue(matcher.matches());
}
@Test
public void whenIncorrectPrefix_thenNotCorrect() {
Pattern pattern = Pattern.compile("^(\\+\\d{1,3}( )?)?((\\(\\d{3}\\))|\\d{3})[- .]?\\d{3}[- .]?\\d{4}$");
Matcher matcher = pattern.matcher("-111 (202) 555-0125");
assertFalse(matcher.matches());
}
@Test
public void whenTooLongPrefix_thenNotCorrect() {
Pattern pattern = Pattern.compile("^(\\+\\d{1,3}( )?)?((\\(\\d{3}\\))|\\d{3})[- .]?\\d{3}[- .]?\\d{4}$");
Matcher matcher = pattern.matcher("+1111 (202) 555-0125");
assertFalse(matcher.matches());
}
@Test
public void whenMatchesPhoneNumber_thenCorrect() {
String patterns
= "^(\\+\\d{1,3}( )?)?((\\(\\d{3}\\))|\\d{3})[- .]?\\d{3}[- .]?\\d{4}$"
+ "|^(\\+\\d{1,3}( )?)?(\\d{3}[ ]?){2}\\d{3}$"
+ "|^(\\+\\d{1,3}( )?)?(\\d{3}[ ]?)(\\d{2}[ ]?){2}\\d{2}$";
String[] validPhoneNumbers
= {"2055550125","202 555 0125", "(202) 555-0125", "+111 (202) 555-0125", "636 856 789", "+111 636 856 789", "636 85 67 89", "+111 636 85 67 89"};
Pattern pattern = Pattern.compile(patterns);
for(String phoneNumber : validPhoneNumbers) {
Matcher matcher = pattern.matcher(phoneNumber);
assertTrue(matcher.matches());
}
}
@Test
public void whenNotMatchesPhoneNumber_thenNotCorrect() {
String patterns
= "^(\\+\\d{1,3}( )?)?((\\(\\d{3}\\))|\\d{3})[- .]?\\d{3}[- .]?\\d{4}$"
+ "|^(\\+\\d{1,3}( )?)?(\\d{3}[ ]?){2}\\d{3}$"
+ "|^(\\+\\d{1,3}( )?)?(\\d{3}[ ]?)(\\d{2}[ ]?){2}\\d{2}$";
String[] invalidPhoneNumbers
= {"20555501251","202]555 0125", "2021 555 012", "(202 555-0125", "202) 555-0125", "-111 (202) 555-0125", "+1111 (202) 555-0125", "636 85 789", "636 85 67 893"};
Pattern pattern = Pattern.compile(patterns);
for(String phoneNumber : invalidPhoneNumbers) {
Matcher matcher = pattern.matcher(phoneNumber);
assertFalse(matcher.matches());
}
}
}

View File

@ -10,4 +10,5 @@ This module contains articles about the Stream API in Java.
- [Primitive Type Streams in Java 8](https://www.baeldung.com/java-8-primitive-streams)
- [Debugging Java 8 Streams with IntelliJ](https://www.baeldung.com/intellij-debugging-java-streams)
- [Add BigDecimals using the Stream API](https://www.baeldung.com/java-stream-add-bigdecimals)
- [Should We Close a Java Stream?](https://www.baeldung.com/java-stream-close)
- More articles: [[<-- prev>]](/../core-java-streams-2)

View File

@ -0,0 +1,22 @@
package com.baeldung.late
import org.junit.Test
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class LateInitUnitTest {
private lateinit var answer: String
@Test(expected = UninitializedPropertyAccessException::class)
fun givenLateInit_WhenNotInitialized_ShouldThrowAnException() {
answer.length
}
@Test
fun givenLateInit_TheIsInitialized_ReturnsTheInitializationStatus() {
assertFalse { this::answer.isInitialized }
answer = "42"
assertTrue { this::answer.isInitialized }
}
}

View File

@ -6,6 +6,7 @@ import org.apache.commons.collections4.MapUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
public class ConvertListToMapService {
@ -21,7 +22,7 @@ public class ConvertListToMapService {
}
public Map<Integer, Animal> convertListAfterJava8(List<Animal> list) {
Map<Integer, Animal> map = list.stream().collect(Collectors.toMap(Animal::getId, animal -> animal));
Map<Integer, Animal> map = list.stream().collect(Collectors.toMap(Animal::getId, Function.identity()));
return map;
}

View File

@ -53,14 +53,14 @@ public class CollectionToArrayListUnitTest {
verifyShallowCopy(srcCollection, newList);
}
/**
* Section 5. Deep Copy
*/
@Test
public void whenUsingDeepCopy_thenVerifyDeepCopy() {
ArrayList<Foo> newList = srcCollection.stream()
.map(foo -> foo.deepCopy())
.map(Foo::deepCopy)
.collect(toCollection(ArrayList::new));
verifyDeepCopy(srcCollection, newList);
@ -83,13 +83,13 @@ public class CollectionToArrayListUnitTest {
* @param a
* @param b
*/
private void verifyShallowCopy(Collection a, Collection b) {
private void verifyShallowCopy(Collection<Foo> a, Collection<Foo> b) {
assertEquals("Collections have different lengths", a.size(), b.size());
Iterator<Foo> iterA = a.iterator();
Iterator<Foo> iterB = b.iterator();
while (iterA.hasNext()) {
// use '==' to test instance identity
assertTrue("Foo instances differ!", iterA.next() == iterB.next());
assertSame("Foo instances differ!", iterA.next(), iterB.next());
}
}
@ -98,7 +98,7 @@ public class CollectionToArrayListUnitTest {
* @param a
* @param b
*/
private void verifyDeepCopy(Collection a, Collection b) {
private void verifyDeepCopy(Collection<Foo> a, Collection<Foo> b) {
assertEquals("Collections have different lengths", a.size(), b.size());
Iterator<Foo> iterA = a.iterator();
Iterator<Foo> iterB = b.iterator();
@ -106,7 +106,7 @@ public class CollectionToArrayListUnitTest {
Foo nextA = iterA.next();
Foo nextB = iterB.next();
// should not be same instance
assertFalse("Foo instances are the same!", nextA == nextB);
assertNotSame("Foo instances are the same!", nextA, nextB);
// but should have same content
assertFalse("Foo instances have different content!", fooDiff(nextA, nextB));
}

View File

@ -23,7 +23,7 @@ public class ConvertIteratorToListServiceUnitTest {
Iterator<Integer> iterator;
@Before
public void setUp() throws Exception {
public void setUp() {
iterator = Arrays.asList(1, 2, 3)
.iterator();
}
@ -31,7 +31,7 @@ public class ConvertIteratorToListServiceUnitTest {
@Test
public void givenAnIterator_whenConvertIteratorToListUsingWhileLoop_thenReturnAList() {
List<Integer> actualList = new ArrayList<Integer>();
List<Integer> actualList = new ArrayList<>();
// Convert Iterator to List using while loop dsf
while (iterator.hasNext()) {
@ -44,7 +44,7 @@ public class ConvertIteratorToListServiceUnitTest {
@Test
public void givenAnIterator_whenConvertIteratorToListAfterJava8_thenReturnAList() {
List<Integer> actualList = new ArrayList<Integer>();
List<Integer> actualList = new ArrayList<>();
// Convert Iterator to List using Java 8
iterator.forEachRemaining(actualList::add);

View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [Java Map With Case-Insensitive Keys](https://www.baeldung.com/java-map-with-case-insensitive-keys)

View File

@ -17,4 +17,4 @@ Remember, for advanced libraries like [Jackson](/jackson) and [JUnit](/testing-m
- [Using NullAway to Avoid NullPointerExceptions](https://www.baeldung.com/java-nullaway)
- [Introduction to Alibaba Arthas](https://www.baeldung.com/java-alibaba-arthas-intro)
- [Quick Guide to Spring Cloud Circuit Breaker](https://www.baeldung.com/spring-cloud-circuit-breaker)
- More articles [[<-- prev]](/libraries-2) [[next -->]](/libraries-4)
- More articles [[<-- prev]](/libraries-2) [[next -->]](/libraries-4)

View File

@ -11,4 +11,4 @@ This module contains articles about test libraries.
- [Introduction to Awaitlity](https://www.baeldung.com/awaitlity-testing)
- [Introduction to Hoverfly in Java](https://www.baeldung.com/hoverfly)
- [Testing with Hamcrest](https://www.baeldung.com/java-junit-hamcrest-guide)
- [Introduction To DBUnit](https://www.baeldung.com/dbunit)
- [Introduction To DBUnit](https://www.baeldung.com/java-dbunit)

3
netty/README.md Normal file
View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [HTTP/2 in Netty](https://www.baeldung.com/netty-http2)

View File

@ -1,3 +0,0 @@
### Relevant Articles:
- [Implementing The OAuth 2.0 Authorization Framework Using Jakarta EE](https://www.baeldung.com/java-ee-oauth2-implementation)

View File

@ -1,3 +0,0 @@
### Relevant Articles:
- [Implementing The OAuth 2.0 Authorization Framework Using Jakarta EE](https://www.baeldung.com/java-ee-oauth2-implementation)

View File

@ -14,3 +14,4 @@ This module contains articles specific to use of Hibernate as a JPA implementati
- [TransactionRequiredException Error](https://www.baeldung.com/jpa-transaction-required-exception)
- [JPA/Hibernate Persistence Context](https://www.baeldung.com/jpa-hibernate-persistence-context)
- [Quick Guide to EntityManager#getReference()](https://www.baeldung.com/jpa-entity-manager-get-reference)
- [Hibernate Error “No Persistence Provider for EntityManager”](https://www.baeldung.com/hibernate-no-persistence-provider)

View File

@ -11,3 +11,4 @@ This module contains articles about MongoDB in Java.
- [Introduction to Morphia Java ODM for MongoDB](https://www.baeldung.com/mongodb-morphia)
- [MongoDB Aggregations Using Java](https://www.baeldung.com/java-mongodb-aggregations)
- [MongoDB BSON to JSON](https://www.baeldung.com/bson-to-json)
- [BSON to JSON Document Conversion in Java](https://www.baeldung.com/java-convert-bson-to-json)

View File

@ -1,3 +1,4 @@
### Relevant Articles:
- [Using JDBI with Spring Boot](https://www.baeldung.com/spring-boot-jdbi)
- [Oracle Connection Pooling With Spring](https://www.baeldung.com/spring-oracle-connection-pooling)

View File

@ -0,0 +1,12 @@
package com.baeldung.spring.transactional;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
class TransactionalCompareApplication {
public static void main(String[] args) {
SpringApplication.run(TransactionalCompareApplication.class, args);
}
}

View File

@ -0,0 +1,60 @@
package com.baeldung.spring.transactional.entity;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Car {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String make;
private String model;
public Car() {
}
public Car(Long id, String make, String model) {
this.id = id;
this.make = make;
this.model = model;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getMake() {
return make;
}
public void setMake(String make) {
this.make = make;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
@Override
public String toString() {
return "Car{" +
"id=" + id +
", make='" + make + '\'' +
", model='" + model + '\'' +
'}';
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.spring.transactional.repository;
import com.baeldung.spring.transactional.entity.Car;
import org.springframework.data.jpa.repository.JpaRepository;
public interface CarRepository extends JpaRepository<Car, Long> {
}

View File

@ -0,0 +1,25 @@
package com.baeldung.spring.transactional.service;
import com.baeldung.spring.transactional.entity.Car;
import com.baeldung.spring.transactional.repository.CarRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityExistsException;
@Service
@Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.SUPPORTS, readOnly = false, timeout = 30)
public class CarService {
@Autowired
private CarRepository carRepository;
@Transactional(rollbackFor = IllegalArgumentException.class, noRollbackFor = EntityExistsException.class,
rollbackForClassName = "IllegalArgumentException", noRollbackForClassName = "EntityExistsException")
public Car save(Car car) {
return carRepository.save(car);
}
}

View File

@ -0,0 +1,22 @@
package com.baeldung.spring.transactional.service;
import com.baeldung.spring.transactional.entity.Car;
import com.baeldung.spring.transactional.repository.CarRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.persistence.EntityExistsException;
import javax.transaction.Transactional;
@Service
@Transactional(Transactional.TxType.SUPPORTS)
public class RentalService {
@Autowired
private CarRepository carRepository;
@Transactional(rollbackOn = IllegalArgumentException.class, dontRollbackOn = EntityExistsException.class)
public Car rent(Car car) {
return carRepository.save(car);
}
}

View File

@ -6,6 +6,7 @@
- [JPA Entity Lifecycle Events](https://www.baeldung.com/jpa-entity-lifecycle-events)
- [Working with Lazy Element Collections in JPA](https://www.baeldung.com/java-jpa-lazy-collections)
- [Calling Stored Procedures from Spring Data JPA Repositories](https://www.baeldung.com/spring-data-jpa-stored-procedures)
- [Custom Naming Convention with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-custom-naming)
### Eclipse Config
After importing the project into Eclipse, you may see the following error:

View File

@ -7,3 +7,4 @@ This module contains articles about Reactor Core.
- [Intro To Reactor Core](https://www.baeldung.com/reactor-core)
- [Combining Publishers in Project Reactor](https://www.baeldung.com/reactor-combine-streams)
- [Programmatically Creating Sequences with Project Reactor](https://www.baeldung.com/flux-sequences-reactor)
- [How to Extract a Monos Content in Java](https://www.baeldung.com/java-string-from-mono)

View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [How to Test GraphQL Using Postman](https://www.baeldung.com/graphql-postman)

View File

@ -3,3 +3,5 @@
This module contains articles about Spring Cloud Circuit Breaker
### Relevant Articles:
- [Quick Guide to Spring Cloud Circuit Breaker](https://www.baeldung.com/spring-cloud-circuit-breaker)

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xmlns="http://maven.apache.org/POM/4.0.0"
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-cloud-gateway</artifactId>
<name>spring-cloud-gateway</name>
@ -49,6 +49,26 @@
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- Circuit Breaker -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
</dependency>
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
<!-- Embedded Redis -->
<dependency>
<groupId>it.ozimov</groupId>
<artifactId>embedded-redis</artifactId>
<version>${redis.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator-cdi</artifactId>
@ -69,8 +89,8 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
@ -84,11 +104,10 @@
</build>
<properties>
<spring-cloud-dependencies.version>Greenwich.SR3</spring-cloud-dependencies.version>
<!-- Spring Boot version compatible with Spring Cloud Release train -->
<spring-boot.version>2.1.9.RELEASE</spring-boot.version>
<spring-cloud-dependencies.version>Hoxton.SR3</spring-cloud-dependencies.version>
<spring-boot.version>2.2.6.RELEASE</spring-boot.version>
<hibernate-validator.version>6.0.2.Final</hibernate-validator.version>
<redis.version>0.7.2</redis.version>
</properties>
</project>

View File

@ -0,0 +1,15 @@
package com.baeldung.springcloudgateway.webfilters;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
@SpringBootApplication
public class WebFilterGatewayApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(WebFilterGatewayApplication.class)
.profiles("webfilters")
.run(args);
}
}

View File

@ -0,0 +1,49 @@
package com.baeldung.springcloudgateway.webfilters.config;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import reactor.core.publisher.Mono;
@Configuration
public class ModifyBodyRouteConfig {
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("modify_request_body", r -> r.path("/post")
.filters(f -> f.modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,
(exchange, s) -> Mono.just(new Hello(s.toUpperCase())))).uri("https://httpbin.org"))
.build();
}
@Bean
public RouteLocator responseRoutes(RouteLocatorBuilder builder) {
return builder.routes()
.route("modify_response_body", r -> r.path("/put/**")
.filters(f -> f.modifyResponseBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,
(exchange, s) -> Mono.just(new Hello("New Body")))).uri("https://httpbin.org"))
.build();
}
static class Hello {
String message;
public Hello() { }
public Hello(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
}

View File

@ -0,0 +1,16 @@
package com.baeldung.springcloudgateway.webfilters.config;
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
@Configuration
public class RequestRateLimiterResolverConfig {
@Bean
KeyResolver userKeyResolver() {
return exchange -> Mono.just("1");
}
}

View File

@ -0,0 +1,102 @@
logging:
level:
org.springframework.cloud.gateway: INFO
reactor.netty.http.client: INFO
spring:
redis:
host: localhost
port: 6379
cloud:
gateway:
routes:
- id: request_header_route
uri: https://httpbin.org
predicates:
- Path=/get/**
filters:
- AddRequestHeader=My-Header-Good,Good
- AddRequestHeader=My-Header-Remove,Remove
- AddRequestParameter=var, good
- AddRequestParameter=var2, remove
- MapRequestHeader=My-Header-Good, My-Header-Bad
- MapRequestHeader=My-Header-Set, My-Header-Bad
- SetRequestHeader=My-Header-Set, Set
- RemoveRequestHeader=My-Header-Remove
- RemoveRequestParameter=var2
- PreserveHostHeader
- id: response_header_route
uri: https://httpbin.org
predicates:
- Path=/header/post/**
filters:
- AddResponseHeader=My-Header-Good,Good
- AddResponseHeader=My-Header-Set,Good
- AddResponseHeader=My-Header-Rewrite, password=12345678
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
- AddResponseHeader=My-Header-Remove,Remove
- SetResponseHeader=My-Header-Set, Set
- RemoveResponseHeader=My-Header-Remove
- RewriteResponseHeader=My-Header-Rewrite, password=[^&]+, password=***
- RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,
- StripPrefix=1
- id: path_route
uri: https://httpbin.org
predicates:
- Path=/new/post/**
filters:
- RewritePath=/new(?<segment>/?.*), $\{segment}
- SetPath=/post
- id: redirect_route
uri: https://httpbin.org
predicates:
- Path=/fake/post/**
filters:
- RedirectTo=302, https://httpbin.org
- id: status_route
uri: https://httpbin.org
predicates:
- Path=/delete/**
filters:
- SetStatus=401
- id: size_route
uri: https://httpbin.org
predicates:
- Path=/anything
filters:
- name: RequestSize
args:
maxSize: 5000000
- id: retry_test
uri: https://httpbin.org
predicates:
- Path=/status/502
filters:
- name: Retry
args:
retries: 3
statuses: BAD_GATEWAY
methods: GET,POST
backoff:
firstBackoff: 10ms
maxBackoff: 50ms
factor: 2
basedOnPreviousValue: false
- id: request_rate_limiter
uri: https://httpbin.org
predicates:
- Path=/redis/get/**
filters:
- StripPrefix=1
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 5
key-resolver: "#{@userKeyResolver}"

View File

@ -0,0 +1,64 @@
package com.baeldung.springcloudgateway.webfilters;
import org.junit.After;
import org.junit.Before;
import org.junit.jupiter.api.RepeatedTest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ActiveProfiles;
import redis.embedded.RedisServer;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@ActiveProfiles("webfilters")
@TestConfiguration
public class RedisWebFilterFactoriesLiveTest {
private static final Logger LOGGER = LoggerFactory.getLogger(RedisWebFilterFactoriesLiveTest.class);
private RedisServer redisServer;
public RedisWebFilterFactoriesLiveTest() {
}
@Before
public void postConstruct() {
this.redisServer = new RedisServer(6379);
redisServer.start();
}
@LocalServerPort
String port;
@Autowired
private TestRestTemplate restTemplate;
@Autowired
TestRestTemplate template;
@RepeatedTest(25)
public void whenCallRedisGetThroughGateway_thenOKStatusOrIsReceived() {
String url = "http://localhost:" + port + "/redis/get";
ResponseEntity<String> r = restTemplate.getForEntity(url, String.class);
// assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
LOGGER.info("Received: status->{}, reason->{}, remaining->{}",
r.getStatusCodeValue(), r.getStatusCode().getReasonPhrase(),
r.getHeaders().get("X-RateLimit-Remaining"));
}
@After
public void preDestroy() {
redisServer.stop();
}
}

View File

@ -0,0 +1,136 @@
package com.baeldung.springcloudgateway.webfilters;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.assertj.core.api.Condition;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec;
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@ActiveProfiles("webfilters")
public class WebFilterFactoriesLiveTest {
@LocalServerPort
String port;
@Autowired
private WebTestClient client;
@Autowired
private TestRestTemplate restTemplate;
@BeforeEach
public void configureClient() {
client = WebTestClient.bindToServer()
.baseUrl("http://localhost:" + port)
.build();
}
@Test
public void whenCallGetThroughGateway_thenAllHTTPRequestHeadersParametersAreSet() throws JSONException {
String url = "http://localhost:" + port + "/get";
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
JSONObject json = new JSONObject(response.getBody());
JSONObject headers = json.getJSONObject("headers");
assertThat(headers.getString("My-Header-Good")).isEqualTo("Good");
assertThat(headers.getString("My-Header-Bad")).isEqualTo("Good");
assertThat(headers.getString("My-Header-Set")).isEqualTo("Set");
assertTrue(headers.isNull("My-Header-Remove"));
JSONObject vars = json.getJSONObject("args");
assertThat(vars.getString("var")).isEqualTo("good");
}
@Test
public void whenCallHeaderPostThroughGateway_thenAllHTTPResponseHeadersAreSet() {
ResponseSpec response = client.post()
.uri("/header/post")
.exchange();
response.expectStatus()
.isOk()
.expectHeader()
.valueEquals("My-Header-Rewrite", "password=***")
.expectHeader()
.valueEquals("My-Header-Set", "Set")
.expectHeader()
.valueEquals("My-Header-Good", "Good")
.expectHeader()
.doesNotExist("My-Header-Remove");
}
@Test
public void whenCallPostThroughGateway_thenBodyIsRetrieved() throws JSONException {
String url = "http://localhost:" + port + "/post";
HttpEntity<String> entity = new HttpEntity<>("content", new HttpHeaders());
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
JSONObject json = new JSONObject(response.getBody());
JSONObject data = json.getJSONObject("json");
assertThat(data.getString("message")).isEqualTo("CONTENT");
}
@Test
public void whenCallPutThroughGateway_thenBodyIsRetrieved() throws JSONException {
String url = "http://localhost:" + port + "/put";
HttpEntity<String> entity = new HttpEntity<>("CONTENT", new HttpHeaders());
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.PUT, entity, String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
JSONObject json = new JSONObject(response.getBody());
assertThat(json.getString("message")).isEqualTo("New Body");
}
@Test
public void whenCallDeleteThroughGateway_thenIsUnauthorizedCodeIsSet() {
ResponseSpec response = client.delete()
.uri("/delete")
.exchange();
response.expectStatus()
.isUnauthorized();
}
@Test
public void whenCallFakePostThroughGateway_thenIsUnauthorizedCodeIsSet() {
ResponseSpec response = client.post()
.uri("/fake/post")
.exchange();
response.expectStatus()
.is3xxRedirection();
}
@Test
public void whenCallStatus504ThroughGateway_thenCircuitBreakerIsExecuted() throws JSONException {
String url = "http://localhost:" + port + "/status/504";
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
JSONObject json = new JSONObject(response.getBody());
assertThat(json.getString("url")).contains("anything");
}
}

View File

@ -3,7 +3,15 @@
<appender name="LISTAPPENDER"
class="com.baeldung.springcloudgateway.customfilters.gatewayapp.utils.LoggerListAppender">
</appender>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="info">
<appender-ref ref="LISTAPPENDER" />
</root>
<root level="info">
<appender-ref ref="STDOUT" />
</root>
</configuration>

View File

@ -14,4 +14,5 @@ This module contains articles about core Spring functionality
- [Spring Events](https://www.baeldung.com/spring-events)
- [Spring Null-Safety Annotations](https://www.baeldung.com/spring-null-safety-annotations)
- [Using @Autowired in Abstract Classes](https://www.baeldung.com/spring-autowired-abstract-class)
- [Running Setup Data on Startup in Spring](https://www.baeldung.com/running-setup-logic-on-startup-in-spring)
- More articles: [[<-- prev]](/spring-core)[[next -->]](/spring-core-3)

View File

@ -0,0 +1,27 @@
package com.baeldung.dynamic.autowire;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BeanFactoryDynamicAutowireService {
private static final String SERVICE_NAME_SUFFIX = "regionService";
private final BeanFactory beanFactory;
@Autowired
public BeanFactoryDynamicAutowireService(BeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
public boolean isServerActive(String isoCountryCode, int serverId) {
RegionService service = beanFactory.getBean(getRegionServiceBeanName(isoCountryCode), RegionService.class);
return service.isServerActive(serverId);
}
private String getRegionServiceBeanName(String isoCountryCode) {
return isoCountryCode + SERVICE_NAME_SUFFIX;
}
}

View File

@ -0,0 +1,26 @@
package com.baeldung.dynamic.autowire;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
@Service
public class CustomMapFromListDynamicAutowireService {
private final Map<String, RegionService> servicesByCountryCode;
@Autowired
public CustomMapFromListDynamicAutowireService(List<RegionService> regionServices) {
servicesByCountryCode = regionServices.stream()
.collect(Collectors.toMap(RegionService::getISOCountryCode, Function.identity()));
}
public boolean isServerActive(String isoCountryCode, int serverId) {
RegionService service = servicesByCountryCode.get(isoCountryCode);
return service.isServerActive(serverId);
}
}

View File

@ -0,0 +1,9 @@
package com.baeldung.dynamic.autowire;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.baeldung.dynamic.autowire")
public class DynamicAutowireConfig {
}

View File

@ -0,0 +1,16 @@
package com.baeldung.dynamic.autowire;
import org.springframework.stereotype.Service;
@Service("GBregionService")
public class GBRegionService implements RegionService {
@Override
public boolean isServerActive(int serverId) {
return false;
}
@Override
public String getISOCountryCode() {
return "GB";
}
}

View File

@ -0,0 +1,7 @@
package com.baeldung.dynamic.autowire;
public interface RegionService {
boolean isServerActive(int serverId);
String getISOCountryCode();
}

View File

@ -0,0 +1,16 @@
package com.baeldung.dynamic.autowire;
import org.springframework.stereotype.Service;
@Service("USregionService")
public class USRegionService implements RegionService {
@Override
public boolean isServerActive(int serverId) {
return true;
}
@Override
public String getISOCountryCode() {
return "US";
}
}

View File

@ -0,0 +1,33 @@
package com.baeldung.dynamic.autowire;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = DynamicAutowireConfig.class)
public class DynamicAutowireIntegrationTest {
@Autowired
private BeanFactoryDynamicAutowireService beanFactoryDynamicAutowireService;
@Autowired
private CustomMapFromListDynamicAutowireService customMapFromListDynamicAutowireService;
@Test
public void givenDynamicallyAutowiredBean_whenCheckingServerInGB_thenServerIsNotActive() {
assertThat(beanFactoryDynamicAutowireService.isServerActive("GB", 101), is(false));
assertThat(customMapFromListDynamicAutowireService.isServerActive("GB", 101), is(false));
}
@Test
public void givenDynamicallyAutowiredBean_whenCheckingServerInUS_thenServerIsActive() {
assertThat(beanFactoryDynamicAutowireService.isServerActive("US", 101), is(true));
assertThat(customMapFromListDynamicAutowireService.isServerActive("US", 101), is(true));
}
}

View File

@ -9,7 +9,7 @@ This module contains articles about Spring MVC
- [Servlet Redirect vs Forward](https://www.baeldung.com/servlet-redirect-forward)
- [Apache Tiles Integration with Spring MVC](https://www.baeldung.com/spring-mvc-apache-tiles)
- [Guide to Spring Email](https://www.baeldung.com/spring-email)
- [Using ThymeLeaf and FreeMarker Emails Templates with Spring](https://www.baeldung.com/thymeleaf-freemarker-email)
- [Using ThymeLeaf and FreeMarker Emails Templates with Spring](https://www.baeldung.com/spring-email-templates)
- [Request Method Not Supported (405) in Spring](https://www.baeldung.com/spring-request-method-not-supported-405)
- [Spring @RequestParam Annotation](https://www.baeldung.com/spring-request-param)
- More articles: [[more -->]](/spring-mvc-basics-3)

View File

@ -31,6 +31,7 @@
<module>spring-security-mvc-persisted-remember-me</module>
<module>spring-security-mvc-socket</module>
<module>spring-security-oidc</module>
<module>spring-security-okta</module>
<module>spring-security-react</module>
<module>spring-security-rest</module>
<module>spring-security-rest-basic-auth</module>

View File

@ -0,0 +1,62 @@
<?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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-security-okta</artifactId>
<version>1.0-SNAPSHOT</version>
<name>spring-security-okta</name>
<packaging>war</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.okta.spring</groupId>
<artifactId>okta-spring-boot-starter</artifactId>
<version>${okta.spring.version}</version>
</dependency>
<dependency>
<groupId>com.okta.spring</groupId>
<artifactId>okta-spring-sdk</artifactId>
<version>${okta.spring.version}</version>
</dependency>
</dependencies>
<build>
<finalName>spring-security-okta</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<addResources>true</addResources>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<okta.spring.version>1.4.0</okta.spring.version>
</properties>
</project>

View File

@ -0,0 +1,13 @@
package com.baeldung.okta;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@ -0,0 +1,43 @@
package com.baeldung.okta.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.okta.sdk.client.Client;
import com.okta.sdk.resource.user.User;
import com.okta.sdk.resource.user.UserBuilder;
import com.okta.sdk.resource.user.UserList;
@RestController
public class AdminController {
@Autowired
public Client client;
@GetMapping("/users")
public UserList getUsers() {
return client.listUsers();
}
@GetMapping("/user")
public UserList searchUserByEmail(@RequestParam String query) {
return client.listUsers(query, null, null, null, null);
}
@GetMapping("/createUser")
public User createUser() {
char[] tempPassword = {'P','a','$','$','w','0','r','d'};
User user = UserBuilder.instance()
.setEmail("norman.lewis@email.com")
.setFirstName("Norman")
.setLastName("Lewis")
.setPassword(tempPassword)
.setActive(true)
.buildAndCreate(client);
return user;
}
}

View File

@ -0,0 +1,16 @@
package com.baeldung.okta.controller;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HomeController {
@GetMapping("/")
public String home(@AuthenticationPrincipal OidcUser user) {
return "Welcome, "+ user.getFullName() +"!";
}
}

View File

@ -0,0 +1,8 @@
okta.oauth2.issuer= //Auth server issuer URL
okta.oauth2.client-id= //Client ID of our Okta application
okta.oauth2.client-secret= //Client secret of our Okta application
okta.oauth2.redirect-uri=/authorization-code/callback
#Okta Spring SDK configs
okta.client.orgUrl= //orgURL
okta.client.token= //token generated

View File

@ -1,3 +1,3 @@
## Spring Swagger Codegen App
This module contains the code for [Generate Spring Boot REST Client with Swagger](http://www.baeldung.com/spring-boot-rest-client-swagger-codegen).
This module contains the code for Generate Spring Boot REST Client with Swagger.

View File

@ -13,4 +13,5 @@ This module contains articles about Spring with Thymeleaf
- [Working with Boolean in Thymeleaf](https://www.baeldung.com/thymeleaf-boolean)
- [Working With Custom HTML Attributes in Thymeleaf](https://www.baeldung.com/thymeleaf-custom-html-attributes)
- [How to Create an Executable JAR with Maven](https://www.baeldung.com/executable-jar-with-maven)
- [Spring MVC Data and Thymeleaf](https://www.baeldung.com/spring-mvc-thymeleaf-data)
- [[<-- prev]](/spring-thymeleaf)

3
terraform/README.md Normal file
View File

@ -0,0 +1,3 @@
### Relevant Articles:
- [Introduction to Terraform](https://www.baeldung.com/ops/terraform-intro)

View File

@ -7,3 +7,4 @@ This module contains articles about JUnit 5 Annotations
- [JUnit 5 Conditional Test Execution with Annotations](https://www.baeldung.com/junit-5-conditional-test-execution)
- [JUnit5 Programmatic Extension Registration with @RegisterExtension](https://www.baeldung.com/junit-5-registerextension-annotation)
- [Guide to JUnit 5 Parameterized Tests](https://www.baeldung.com/parameterized-tests-junit-5)
- [Writing Templates for Test Cases Using JUnit 5](https://www.baeldung.com/junit5-test-templates)

View File

@ -5,3 +5,4 @@
- [Mockito Strict Stubbing and The UnnecessaryStubbingException](https://www.baeldung.com/mockito-unnecessary-stubbing-exception)
- [Mockito and Fluent APIs](https://www.baeldung.com/mockito-fluent-apis)
- [Mocking the ObjectMapper readValue() Method](https://www.baeldung.com/mockito-mock-jackson-read-value)
- [Introduction to Mockitos AdditionalAnswers](https://www.baeldung.com/mockito-additionalanswers)