Merge branch 'eugenp:master' into master
This commit is contained in:
commit
a30a85ddd4
|
@ -0,0 +1,21 @@
|
||||||
|
package com.baeldung.shell;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public class StreamGobbler implements Runnable {
|
||||||
|
private final InputStream inputStream;
|
||||||
|
private final Consumer<String> consumer;
|
||||||
|
|
||||||
|
public StreamGobbler(InputStream inputStream, Consumer<String> consumer) {
|
||||||
|
this.inputStream = inputStream;
|
||||||
|
this.consumer = consumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(consumer);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,10 +5,7 @@ import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
@ -21,21 +18,6 @@ import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
public class JavaProcessUnitIntegrationTest {
|
public class JavaProcessUnitIntegrationTest {
|
||||||
private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().startsWith("windows");
|
private static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().startsWith("windows");
|
||||||
|
|
||||||
private static class StreamGobbler implements Runnable {
|
|
||||||
private InputStream inputStream;
|
|
||||||
private Consumer<String> consumer;
|
|
||||||
|
|
||||||
public StreamGobbler(InputStream inputStream, Consumer<String> consumer) {
|
|
||||||
this.inputStream = inputStream;
|
|
||||||
this.consumer = consumer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
new BufferedReader(new InputStreamReader(inputStream)).lines().forEach(consumer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Consumer<String> consumer = Assert::assertNotNull;
|
private Consumer<String> consumer = Assert::assertNotNull;
|
||||||
|
|
||||||
private String homeDirectory = System.getProperty("user.home");
|
private String homeDirectory = System.getProperty("user.home");
|
||||||
|
@ -58,7 +40,7 @@ public class JavaProcessUnitIntegrationTest {
|
||||||
if (IS_WINDOWS) {
|
if (IS_WINDOWS) {
|
||||||
process = Runtime.getRuntime().exec(String.format("cmd.exe /c dir %s", homeDirectory));
|
process = Runtime.getRuntime().exec(String.format("cmd.exe /c dir %s", homeDirectory));
|
||||||
} else {
|
} else {
|
||||||
process = Runtime.getRuntime().exec(String.format("sh -c ls %s", homeDirectory));
|
process = Runtime.getRuntime().exec(String.format("/bin/sh -c ls %s", homeDirectory));
|
||||||
}
|
}
|
||||||
StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), consumer);
|
StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), consumer);
|
||||||
|
|
||||||
|
@ -70,13 +52,34 @@ public class JavaProcessUnitIntegrationTest {
|
||||||
assertEquals(0, exitCode);
|
assertEquals(0, exitCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldExecuteCommandWithPipesWithRuntimeProcess(){
|
||||||
|
Process process;
|
||||||
|
try {
|
||||||
|
if (IS_WINDOWS) {
|
||||||
|
process = Runtime.getRuntime().exec(String.format("cmd.exe /c dir %s | findstr \"Desktop\"", homeDirectory));
|
||||||
|
} else {
|
||||||
|
process = Runtime.getRuntime().exec(String.format("/bin/sh -c ls %s | grep \"Desktop\"", homeDirectory));
|
||||||
|
}
|
||||||
|
StreamGobbler streamGobbler = new StreamGobbler(process.getInputStream(), consumer);
|
||||||
|
|
||||||
|
Future<?> future = executorService.submit(streamGobbler);
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
|
||||||
|
// verify the stream output from the process
|
||||||
|
assertDoesNotThrow(() -> future.get(10, TimeUnit.SECONDS));
|
||||||
|
assertEquals(0, exitCode);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
@Test
|
@Test
|
||||||
public void givenProcess_whenCreatingViaProcessBuilder_shouldSucceed() throws Exception {
|
public void givenProcess_whenCreatingViaProcessBuilder_shouldSucceed() throws Exception {
|
||||||
ProcessBuilder builder = new ProcessBuilder();
|
ProcessBuilder builder = new ProcessBuilder();
|
||||||
if (IS_WINDOWS) {
|
if (IS_WINDOWS) {
|
||||||
builder.command("cmd.exe", "/c", "dir");
|
builder.command("cmd.exe", "/c", "dir");
|
||||||
} else {
|
} else {
|
||||||
builder.command("sh", "-c", "ls");
|
builder.command("/bin/sh", "-c", "ls");
|
||||||
}
|
}
|
||||||
builder.directory(new File(homeDirectory));
|
builder.directory(new File(homeDirectory));
|
||||||
Process process = builder.start();
|
Process process = builder.start();
|
||||||
|
|
|
@ -1,15 +1,41 @@
|
||||||
package com.baeldung.system.exit;
|
package com.baeldung.system.exit;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.security.Permission;
|
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.security.Permission;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
@Ignore("This test is ignored because it tests deprecated code")
|
||||||
public class SystemExitUnitTest {
|
public class SystemExitUnitTest {
|
||||||
|
|
||||||
|
private SecurityManager securityManager;
|
||||||
|
private SystemExitExample example;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
example = new SystemExitExample();
|
||||||
|
securityManager = System.getSecurityManager();
|
||||||
|
System.setSecurityManager(new NoExitSecurityManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() throws Exception {
|
||||||
|
System.setSecurityManager(securityManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExit() throws Exception {
|
||||||
|
try {
|
||||||
|
example.readFile();
|
||||||
|
} catch (ExitException e) {
|
||||||
|
assertEquals("Exit status", 2, e.status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected static class ExitException extends SecurityException {
|
protected static class ExitException extends SecurityException {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
@ -35,29 +61,4 @@ public class SystemExitUnitTest {
|
||||||
throw new ExitException(status);
|
throw new ExitException(status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private SecurityManager securityManager;
|
|
||||||
|
|
||||||
private SystemExitExample example;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
example = new SystemExitExample();
|
|
||||||
securityManager = System.getSecurityManager();
|
|
||||||
System.setSecurityManager(new NoExitSecurityManager());
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() throws Exception {
|
|
||||||
System.setSecurityManager(securityManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testExit() throws Exception {
|
|
||||||
try {
|
|
||||||
example.readFile();
|
|
||||||
} catch (ExitException e) {
|
|
||||||
assertEquals("Exit status", 2, e.status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -3,8 +3,6 @@ package com.baeldung.uuid;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.time.Duration;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -13,7 +11,8 @@ public final class UUIDGenerator {
|
||||||
|
|
||||||
private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
|
private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
|
||||||
|
|
||||||
private UUIDGenerator() {}
|
private UUIDGenerator() {
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type 1 UUID Generation
|
* Type 1 UUID Generation
|
||||||
|
@ -33,14 +32,12 @@ public final class UUIDGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static long get64MostSignificantBitsForVersion1() {
|
private static long get64MostSignificantBitsForVersion1() {
|
||||||
final LocalDateTime start = LocalDateTime.of(1582, 10, 15, 0, 0, 0);
|
final long timeForUuidIn100Nanos = System.currentTimeMillis();
|
||||||
final Duration duration = Duration.between(start, LocalDateTime.now());
|
final long time_low = (timeForUuidIn100Nanos & 0x0000_0000_FFFF_FFFFL) << 32;
|
||||||
final long seconds = duration.getSeconds();
|
final long time_mid = ((timeForUuidIn100Nanos >> 32) & 0xFFFF) << 16;
|
||||||
final long nanos = duration.getNano();
|
|
||||||
final long timeForUuidIn100Nanos = seconds * 10000000 + nanos * 100;
|
|
||||||
final long least12SignificantBitOfTime = (timeForUuidIn100Nanos & 0x000000000000FFFFL) >> 4;
|
|
||||||
final long version = 1 << 12;
|
final long version = 1 << 12;
|
||||||
return (timeForUuidIn100Nanos & 0xFFFFFFFFFFFF0000L) + version + least12SignificantBitOfTime;
|
final long time_hi = ((timeForUuidIn100Nanos >> 48) & 0x0FFF);
|
||||||
|
return time_low + time_mid + version + time_hi;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -94,32 +91,14 @@ public final class UUIDGenerator {
|
||||||
long lsb = 0;
|
long lsb = 0;
|
||||||
assert data.length == 16 : "data must be 16 bytes in length";
|
assert data.length == 16 : "data must be 16 bytes in length";
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {msb = (msb << 8) | (data[i] & 0xff);}
|
for (int i = 0; i < 8; i++) {
|
||||||
|
msb = (msb << 8) | (data[i] & 0xff);
|
||||||
for (int i = 8; i < 16; i++) {lsb = (lsb << 8) | (data[i] & 0xff);}
|
|
||||||
return new UUID(msb, lsb);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unique Keys Generation Using Message Digest and Type 4 UUID
|
|
||||||
* @throws NoSuchAlgorithmException
|
|
||||||
*/
|
|
||||||
public static String generateUniqueKeysWithUUIDAndMessageDigest() throws NoSuchAlgorithmException {
|
|
||||||
final MessageDigest salt = MessageDigest.getInstance("SHA-256");
|
|
||||||
salt.update(UUID.randomUUID()
|
|
||||||
.toString()
|
|
||||||
.getBytes(StandardCharsets.UTF_8));
|
|
||||||
return bytesToHex(salt.digest());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String bytesToHex(byte[] bytes) {
|
|
||||||
final char[] hexChars = new char[bytes.length * 2];
|
|
||||||
for (int j = 0; j < bytes.length; j++) {
|
|
||||||
final int v = bytes[j] & 0xFF;
|
|
||||||
hexChars[j * 2] = hexArray[v >>> 4];
|
|
||||||
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
|
|
||||||
}
|
}
|
||||||
return new String(hexChars);
|
|
||||||
|
for (int i = 8; i < 16; i++) {
|
||||||
|
lsb = (lsb << 8) | (data[i] & 0xff);
|
||||||
|
}
|
||||||
|
return new UUID(msb, lsb);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] bytesFromUUID(String uuidHexString) {
|
private static byte[] bytesFromUUID(String uuidHexString) {
|
||||||
|
|
|
@ -3,6 +3,10 @@ package com.baeldung.uuid;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
@ -13,17 +17,23 @@ class UUIDGeneratorUnitTest {
|
||||||
private static final String NAMESPACE_DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
|
private static final String NAMESPACE_DNS = "6ba7b810-9dad-11d1-80b4-00c04fd430c8";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void version_1_UUID_is_generated_with_correct_length_version_and_variant() {
|
void shouldGenerateType1UUIDWithCorrectVersionAndVariant() {
|
||||||
|
|
||||||
UUID uuid = UUIDGenerator.generateType1UUID();
|
UUID uuid = UUIDGenerator.generateType1UUID();
|
||||||
|
|
||||||
assertEquals(36, uuid.toString().length());
|
assertEquals(36, uuid.toString().length());
|
||||||
assertEquals(1, uuid.version());
|
assertEquals(1, uuid.version());
|
||||||
assertEquals(2, uuid.variant());
|
assertEquals(2, uuid.variant());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void version_3_UUID_is_correctly_generated_for_domain_baeldung_com() throws UnsupportedEncodingException {
|
void shouldGenerateType1UUIDWithTheCurrentDate() {
|
||||||
|
UUID uuid = UUIDGenerator.generateType1UUID();
|
||||||
|
long time = uuid.timestamp();
|
||||||
|
LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault());
|
||||||
|
assertEquals(LocalDate.now(), dateTime.toLocalDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void version_3_UUID_is_correctly_generated_for_domain_baeldung_com() {
|
||||||
|
|
||||||
UUID uuid = UUIDGenerator.generateType3UUID(NAMESPACE_DNS, "baeldung.com");
|
UUID uuid = UUIDGenerator.generateType3UUID(NAMESPACE_DNS, "baeldung.com");
|
||||||
|
|
||||||
|
@ -33,7 +43,7 @@ class UUIDGeneratorUnitTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void version_3_UUID_is_correctly_generated_for_domain_d() throws UnsupportedEncodingException {
|
void version_3_UUID_is_correctly_generated_for_domain_d() {
|
||||||
|
|
||||||
UUID uuid = UUIDGenerator.generateType3UUID(NAMESPACE_DNS, "d");
|
UUID uuid = UUIDGenerator.generateType3UUID(NAMESPACE_DNS, "d");
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
config.stopBubbling = true
|
config.stopBubbling = true
|
||||||
lombok.experimental.flagUsage = warning
|
lombok.experimental.flagUsage = warning
|
|
@ -20,6 +20,15 @@
|
||||||
<version>${lombok.version}</version>
|
<version>${lombok.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
<version>${jackson.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<jackson.version>2.14.1</jackson.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.baeldung.lombok.jackson;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder(builderClassName = "EmployeeBuilder")
|
||||||
|
@JsonDeserialize(builder = Employee.EmployeeBuilder.class)
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Employee {
|
||||||
|
|
||||||
|
private int identity;
|
||||||
|
private String firstName;
|
||||||
|
|
||||||
|
@JsonPOJOBuilder(buildMethodName = "createEmployee", withPrefix = "construct")
|
||||||
|
public static class EmployeeBuilder {
|
||||||
|
|
||||||
|
private int idValue;
|
||||||
|
private String nameValue;
|
||||||
|
|
||||||
|
public EmployeeBuilder constructId(int id) {
|
||||||
|
idValue = id;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmployeeBuilder constructName(String name) {
|
||||||
|
nameValue = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Employee createEmployee() {
|
||||||
|
return new Employee(idValue, nameValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.baeldung.lombok.jackson;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.extern.jackson.Jacksonized;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@Jacksonized
|
||||||
|
public class Fruit {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.baeldung.lombok.jackson;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
class LombokWithJacksonEmployeeUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void withEmployeeObject_thenSerializeSucessfully() throws IOException {
|
||||||
|
Employee employee = Employee.builder()
|
||||||
|
.identity(5)
|
||||||
|
.firstName("Bob")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
String json = newObjectMapper().writeValueAsString(employee);
|
||||||
|
assertEquals("{\"identity\":5,\"firstName\":\"Bob\"}", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void withEmployeeJSON_thenDeserializeSucessfully() throws IOException {
|
||||||
|
String json = "{\"id\":5,\"name\":\"Bob\"}";
|
||||||
|
Employee employee = newObjectMapper().readValue(json, Employee.class);
|
||||||
|
|
||||||
|
assertEquals(5, employee.getIdentity());
|
||||||
|
assertEquals("Bob", employee.getFirstName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ObjectMapper newObjectMapper() {
|
||||||
|
return new ObjectMapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.baeldung.lombok.jackson;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
class LombokWithJacksonFruitUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void withFruitObject_thenSerializeSucessfully() throws IOException {
|
||||||
|
Fruit fruit = Fruit.builder()
|
||||||
|
.id(101)
|
||||||
|
.name("Apple")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
String json = newObjectMapper().writeValueAsString(fruit);
|
||||||
|
assertEquals("{\"name\":\"Apple\",\"id\":101}", json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void withFruitJSON_thenDeserializeSucessfully() throws IOException {
|
||||||
|
String json = "{\"name\":\"Apple\",\"id\":101}";
|
||||||
|
Fruit fruit = newObjectMapper().readValue(json, Fruit.class);
|
||||||
|
assertEquals(new Fruit("Apple", 101), fruit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ObjectMapper newObjectMapper() {
|
||||||
|
return new ObjectMapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
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>parent-boot-3</artifactId>
|
<artifactId>parent-boot-3</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
@ -34,6 +34,26 @@
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
<version>${logback.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-core</artifactId>
|
||||||
|
<version>${logback.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>${slf4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>jcl-over-slf4j</artifactId>
|
||||||
|
<version>${slf4j.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
@ -44,26 +64,166 @@
|
||||||
<build>
|
<build>
|
||||||
<pluginManagement>
|
<pluginManagement>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-clean-plugin</artifactId>
|
||||||
|
<version>${maven-clean-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>${maven-compiler-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>${maven-jar-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<mainClass>${start-class}</mainClass>
|
||||||
|
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${maven-surefire-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<version>${maven-resources-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.graalvm.buildtools</groupId>
|
||||||
|
<artifactId>native-maven-plugin</artifactId>
|
||||||
|
<version>${native-build-tools-plugin.version}</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
<version>${spring-boot.version}</version>
|
<version>${spring-boot.version}</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<mainClass>${start-class}</mainClass>
|
<mainClass>${start-class}</mainClass>
|
||||||
<!-- this is necessary as we're not using the Boot parent -->
|
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>repackage</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</pluginManagement>
|
</pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>repackage</id>
|
||||||
|
<goals>
|
||||||
|
<goal>repackage</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>native</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<image>
|
||||||
|
<builder>paketobuildpacks/builder:tiny</builder>
|
||||||
|
<env>
|
||||||
|
<BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
|
||||||
|
</env>
|
||||||
|
</image>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>process-aot</id>
|
||||||
|
<goals>
|
||||||
|
<goal>process-aot</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.graalvm.buildtools</groupId>
|
||||||
|
<artifactId>native-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
|
||||||
|
<metadataRepository>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</metadataRepository>
|
||||||
|
<requiredVersion>22.3</requiredVersion>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>add-reachability-metadata</id>
|
||||||
|
<goals>
|
||||||
|
<goal>add-reachability-metadata</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>nativeTest</id>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.platform</groupId>
|
||||||
|
<artifactId>junit-platform-launcher</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>process-test-aot</id>
|
||||||
|
<goals>
|
||||||
|
<goal>process-test-aot</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.graalvm.buildtools</groupId>
|
||||||
|
<artifactId>native-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
|
||||||
|
<metadataRepository>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</metadataRepository>
|
||||||
|
<requiredVersion>22.3</requiredVersion>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>native-test</id>
|
||||||
|
<goals>
|
||||||
|
<goal>test</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
<!-- We currently use a Release Candidate, that is not available in Maven Central -->
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>spring-milestones</id>
|
<id>spring-milestones</id>
|
||||||
|
@ -87,10 +247,21 @@
|
||||||
</pluginRepositories>
|
</pluginRepositories>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
<maven-clean-plugin.version>3.2.0</maven-clean-plugin.version>
|
||||||
|
<maven-compiler-plugin.version>3.10.1</maven-compiler-plugin.version>
|
||||||
|
<maven-jar-plugin.version>3.3.0</maven-jar-plugin.version>
|
||||||
|
<maven-resources-plugin.version>3.3.0</maven-resources-plugin.version>
|
||||||
|
<maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
|
||||||
|
|
||||||
<spring-boot.version>3.0.0-M3</spring-boot.version>
|
<spring-boot.version>3.0.0-M3</spring-boot.version>
|
||||||
<junit-jupiter.version>5.8.2</junit-jupiter.version>
|
<junit-jupiter.version>5.8.2</junit-jupiter.version>
|
||||||
<maven-surefire-plugin.version>3.0.0-M7</maven-surefire-plugin.version>
|
<maven-surefire-plugin.version>3.0.0-M7</maven-surefire-plugin.version>
|
||||||
|
<native-build-tools-plugin.version>0.9.17</native-build-tools-plugin.version>
|
||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
|
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||||
|
<logback.version>1.4.4</logback.version>
|
||||||
|
<slf4j.version>2.0.3</slf4j.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -8,27 +8,30 @@ import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
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.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||||
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
|
public class WebSecurityConfiguration {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private FaunaClient faunaClient;
|
private FaunaClient faunaClient;
|
||||||
|
|
||||||
@Override
|
@Bean
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
http.csrf().disable();
|
http.csrf()
|
||||||
|
.disable();
|
||||||
http.authorizeRequests()
|
http.authorizeRequests()
|
||||||
.antMatchers("/**").permitAll()
|
.antMatchers("/**")
|
||||||
.and().httpBasic();
|
.permitAll()
|
||||||
|
.and()
|
||||||
|
.httpBasic();
|
||||||
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@Override
|
|
||||||
public UserDetailsService userDetailsService() {
|
public UserDetailsService userDetailsService() {
|
||||||
return new FaunaUserDetailsService(faunaClient);
|
return new FaunaUserDetailsService(faunaClient);
|
||||||
}
|
}
|
||||||
|
|
12
pom.xml
12
pom.xml
|
@ -326,7 +326,6 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>parent-boot-1</module>
|
<module>parent-boot-1</module>
|
||||||
<module>parent-boot-2</module>
|
<module>parent-boot-2</module>
|
||||||
<module>parent-boot-3</module>
|
|
||||||
<module>parent-spring-4</module>
|
<module>parent-spring-4</module>
|
||||||
<module>parent-spring-5</module>
|
<module>parent-spring-5</module>
|
||||||
<module>parent-java</module>
|
<module>parent-java</module>
|
||||||
|
@ -456,7 +455,6 @@
|
||||||
<module>logging-modules</module>
|
<module>logging-modules</module>
|
||||||
<module>lombok-modules</module>
|
<module>lombok-modules</module>
|
||||||
<module>lucene</module>
|
<module>lucene</module>
|
||||||
|
|
||||||
<module>mapstruct</module>
|
<module>mapstruct</module>
|
||||||
|
|
||||||
<module>maven-modules</module>
|
<module>maven-modules</module>
|
||||||
|
@ -534,7 +532,6 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>parent-boot-1</module>
|
<module>parent-boot-1</module>
|
||||||
<module>parent-boot-2</module>
|
<module>parent-boot-2</module>
|
||||||
<module>parent-boot-3</module>
|
|
||||||
<module>parent-spring-4</module>
|
<module>parent-spring-4</module>
|
||||||
<module>parent-spring-5</module>
|
<module>parent-spring-5</module>
|
||||||
<module>parent-java</module>
|
<module>parent-java</module>
|
||||||
|
@ -677,7 +674,6 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>parent-boot-1</module>
|
<module>parent-boot-1</module>
|
||||||
<module>parent-boot-2</module>
|
<module>parent-boot-2</module>
|
||||||
<module>parent-boot-3</module>
|
|
||||||
<module>parent-spring-4</module>
|
<module>parent-spring-4</module>
|
||||||
<module>parent-spring-5</module>
|
<module>parent-spring-5</module>
|
||||||
<module>parent-java</module>
|
<module>parent-java</module>
|
||||||
|
@ -732,7 +728,6 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>parent-boot-1</module>
|
<module>parent-boot-1</module>
|
||||||
<module>parent-boot-2</module>
|
<module>parent-boot-2</module>
|
||||||
<module>parent-boot-3</module>
|
|
||||||
<module>parent-spring-4</module>
|
<module>parent-spring-4</module>
|
||||||
<module>parent-spring-5</module>
|
<module>parent-spring-5</module>
|
||||||
<module>parent-java</module>
|
<module>parent-java</module>
|
||||||
|
@ -861,7 +856,6 @@
|
||||||
<module>logging-modules</module>
|
<module>logging-modules</module>
|
||||||
<module>lombok-modules</module>
|
<module>lombok-modules</module>
|
||||||
<module>lucene</module>
|
<module>lucene</module>
|
||||||
|
|
||||||
<module>mapstruct</module>
|
<module>mapstruct</module>
|
||||||
|
|
||||||
<module>maven-modules</module>
|
<module>maven-modules</module>
|
||||||
|
@ -930,7 +924,6 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>parent-boot-1</module>
|
<module>parent-boot-1</module>
|
||||||
<module>parent-boot-2</module>
|
<module>parent-boot-2</module>
|
||||||
<module>parent-boot-3</module>
|
|
||||||
<module>parent-spring-4</module>
|
<module>parent-spring-4</module>
|
||||||
<module>parent-spring-5</module>
|
<module>parent-spring-5</module>
|
||||||
<module>parent-java</module>
|
<module>parent-java</module>
|
||||||
|
@ -1066,7 +1059,6 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>parent-boot-1</module>
|
<module>parent-boot-1</module>
|
||||||
<module>parent-boot-2</module>
|
<module>parent-boot-2</module>
|
||||||
<module>parent-boot-3</module>
|
|
||||||
<module>parent-spring-4</module>
|
<module>parent-spring-4</module>
|
||||||
<module>parent-spring-5</module>
|
<module>parent-spring-5</module>
|
||||||
<module>parent-java</module>
|
<module>parent-java</module>
|
||||||
|
@ -1204,10 +1196,12 @@
|
||||||
<module>spring-boot-modules/spring-boot-cassandre</module>
|
<module>spring-boot-modules/spring-boot-cassandre</module>
|
||||||
<module>spring-boot-modules/spring-boot-camel</module>
|
<module>spring-boot-modules/spring-boot-camel</module>
|
||||||
<module>spring-boot-modules/spring-boot-3</module>
|
<module>spring-boot-modules/spring-boot-3</module>
|
||||||
|
<module>spring-boot-modules/spring-boot-3-native</module>
|
||||||
<module>spring-swagger-codegen/custom-validations-opeanpi-codegen</module>
|
<module>spring-swagger-codegen/custom-validations-opeanpi-codegen</module>
|
||||||
<module>testing-modules/testing-assertions</module>
|
<module>testing-modules/testing-assertions</module>
|
||||||
<module>persistence-modules/fauna</module>
|
<module>persistence-modules/fauna</module>
|
||||||
<module>lightrun</module>
|
<module>lightrun</module>
|
||||||
|
<module>tablesaw</module>
|
||||||
</modules>
|
</modules>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
|
@ -1280,11 +1274,13 @@
|
||||||
<module>spring-boot-modules/spring-boot-cassandre</module>
|
<module>spring-boot-modules/spring-boot-cassandre</module>
|
||||||
<module>spring-boot-modules/spring-boot-camel</module>
|
<module>spring-boot-modules/spring-boot-camel</module>
|
||||||
<module>spring-boot-modules/spring-boot-3</module>
|
<module>spring-boot-modules/spring-boot-3</module>
|
||||||
|
<module>spring-boot-modules/spring-boot-3-native</module>
|
||||||
<module>spring-swagger-codegen/custom-validations-opeanpi-codegen</module>
|
<module>spring-swagger-codegen/custom-validations-opeanpi-codegen</module>
|
||||||
<module>testing-modules/testing-assertions</module>
|
<module>testing-modules/testing-assertions</module>
|
||||||
<module>persistence-modules/fauna</module>
|
<module>persistence-modules/fauna</module>
|
||||||
<module>lightrun</module>
|
<module>lightrun</module>
|
||||||
<module>spring-core-6</module>
|
<module>spring-core-6</module>
|
||||||
|
<module>tablesaw</module>
|
||||||
</modules>
|
</modules>
|
||||||
</profile>
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
|
@ -1,40 +1,46 @@
|
||||||
package com.baeldung.comparison.springsecurity.config;
|
package com.baeldung.comparison.springsecurity.config;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.core.userdetails.User;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
public class SecurityConfig {
|
||||||
|
|
||||||
@Override
|
@Bean
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
http.csrf().disable().authorizeRequests(authorize -> authorize.antMatchers("/index", "/login")
|
http.csrf()
|
||||||
.permitAll()
|
.disable()
|
||||||
.antMatchers("/home", "/logout")
|
.authorizeRequests(authorize -> authorize.antMatchers("/index", "/login")
|
||||||
.authenticated()
|
.permitAll()
|
||||||
.antMatchers("/admin/**")
|
.antMatchers("/home", "/logout")
|
||||||
.hasRole("ADMIN"))
|
.authenticated()
|
||||||
|
.antMatchers("/admin/**")
|
||||||
|
.hasRole("ADMIN"))
|
||||||
.formLogin(formLogin -> formLogin.loginPage("/login")
|
.formLogin(formLogin -> formLogin.loginPage("/login")
|
||||||
.failureUrl("/login-error"));
|
.failureUrl("/login-error"));
|
||||||
|
return http.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Bean
|
||||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
public InMemoryUserDetailsManager userDetailsService() throws Exception {
|
||||||
auth.inMemoryAuthentication()
|
UserDetails jerry = User.withUsername("Jerry")
|
||||||
.withUser("Jerry")
|
|
||||||
.password(passwordEncoder().encode("password"))
|
.password(passwordEncoder().encode("password"))
|
||||||
.authorities("READ", "WRITE")
|
.authorities("READ", "WRITE")
|
||||||
.roles("ADMIN")
|
.roles("ADMIN")
|
||||||
.and()
|
.build();
|
||||||
.withUser("Tom")
|
UserDetails tom = User.withUsername("Tom")
|
||||||
.password(passwordEncoder().encode("password"))
|
.password(passwordEncoder().encode("password"))
|
||||||
.authorities("READ")
|
.authorities("READ")
|
||||||
.roles("USER");
|
.roles("USER")
|
||||||
|
.build();
|
||||||
|
return new InMemoryUserDetailsManager(jerry, tom);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>spring-boot-3-native</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>spring-boot-3-native</name>
|
||||||
|
<description>Demo project for Spring Boot</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-boot-3</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../../parent-boot-3/pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springdoc</groupId>
|
||||||
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
|
<version>${spring-doc.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-graphql</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.graalvm.buildtools</groupId>
|
||||||
|
<artifactId>native-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<!-- Mockito is not supported -->
|
||||||
|
<skipNativeTests>true</skipNativeTests>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<!-- The native profile is already defined by the parent POM. -->
|
||||||
|
<!-- To use this plugin, we need GraalVM (located under $GRAALVM_HOME) and native-builder (located in the $PATH)-->
|
||||||
|
<profile>
|
||||||
|
<id>native</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.graalvm.buildtools</groupId>
|
||||||
|
<artifactId>native-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>build-native</id>
|
||||||
|
<goals>
|
||||||
|
<goal>compile-no-fork</goal>
|
||||||
|
</goals>
|
||||||
|
<phase>package</phase>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<spring-boot.version>3.0.0-RC2</spring-boot.version>
|
||||||
|
<spring-doc.version>2.0.0-RC1</spring-doc.version>
|
||||||
|
<native.maven.plugin.version>0.9.17</native.maven.plugin.version>
|
||||||
|
<start-class>com.baeldung.sample.TodoApplication</start-class>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.baeldung.sample;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
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 BoundaryConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public WebMvcConfigurer webMvcConfigurer() {
|
||||||
|
return new WebMvcConfigurer() {
|
||||||
|
@Override
|
||||||
|
public void addViewControllers(ViewControllerRegistry registry) {
|
||||||
|
registry
|
||||||
|
.addViewController("/")
|
||||||
|
.setViewName("redirect:/index.html");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.baeldung.sample;
|
||||||
|
|
||||||
|
import org.springframework.aot.hint.RuntimeHints;
|
||||||
|
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.ImportRuntimeHints;
|
||||||
|
|
||||||
|
@ImportRuntimeHints(GraphQlRuntimeHints.GraphQlResourcesRegistrar.class)
|
||||||
|
@Configuration
|
||||||
|
public class GraphQlRuntimeHints {
|
||||||
|
|
||||||
|
static class GraphQlResourcesRegistrar implements RuntimeHintsRegistrar {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||||
|
hints.resources()
|
||||||
|
.registerPattern("graphql/**/")
|
||||||
|
.registerPattern("graphiql/index.html");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.baeldung.sample;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
|
||||||
|
import org.springframework.aot.hint.RuntimeHints;
|
||||||
|
import org.springframework.aot.hint.RuntimeHintsRegistrar;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.ImportRuntimeHints;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@ImportRuntimeHints(JacksonRuntimeHints.PropertyNamingStrategyRegistrar.class)
|
||||||
|
public class JacksonRuntimeHints {
|
||||||
|
|
||||||
|
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(JacksonRuntimeHints.class);
|
||||||
|
|
||||||
|
static class PropertyNamingStrategyRegistrar implements RuntimeHintsRegistrar {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
|
||||||
|
try {
|
||||||
|
hints
|
||||||
|
.reflection()
|
||||||
|
.registerField(PropertyNamingStrategies.class.getDeclaredField("SNAKE_CASE"));
|
||||||
|
log.info("Registered native hint for SNAKE_CASE!");
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
log.warn("Unable to register native hint for SNAKE_CASE!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.baeldung.sample;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
@SpringBootApplication
|
||||||
|
public class TodoApplication {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(TodoApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.baeldung.sample;
|
||||||
|
|
||||||
|
public class User {
|
||||||
|
|
||||||
|
private String firstName;
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
|
public User(String firstName, String lastName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.sample;
|
||||||
|
|
||||||
|
import org.springframework.graphql.data.method.annotation.QueryMapping;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/v1/user")
|
||||||
|
public class UserController {
|
||||||
|
|
||||||
|
@QueryMapping("getUser")
|
||||||
|
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public User getUser() {
|
||||||
|
return new User("John", "Doe");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
spring:
|
||||||
|
graphql:
|
||||||
|
graphiql:
|
||||||
|
enabled: true
|
||||||
|
jackson:
|
||||||
|
property-naming-strategy: SNAKE_CASE
|
|
@ -0,0 +1,8 @@
|
||||||
|
type User {
|
||||||
|
firstName: String!
|
||||||
|
lastName: String!
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
getUser: User!
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Spring Native Demo Application</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Spring Native Demo Application</h1>
|
||||||
|
<p>
|
||||||
|
This is a sample application that can be built as native executable.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="./swagger-ui.html">REST API Test Client</a></li>
|
||||||
|
<li><a href="./graphiql">GraphQL API Test Client</a></li>
|
||||||
|
</ul>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.baeldung.sample;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
class JacksonAutoConfigurationIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ObjectMapper mapper;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldUseSnakeCasePropertyNamingStrategy() {
|
||||||
|
assertThat(mapper.getPropertyNamingStrategy())
|
||||||
|
.isSameAs(PropertyNamingStrategies.SNAKE_CASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.baeldung.sample;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.aot.hint.RuntimeHints;
|
||||||
|
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
class JacksonRuntimeHintsUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldRegisterSnakeCasePropertyNamingStrategy() {
|
||||||
|
// arrange
|
||||||
|
final var hints = new RuntimeHints();
|
||||||
|
final var expectSnakeCaseHint = RuntimeHintsPredicates
|
||||||
|
.reflection()
|
||||||
|
.onField(PropertyNamingStrategies.class, "SNAKE_CASE");
|
||||||
|
// act
|
||||||
|
new JacksonRuntimeHints.PropertyNamingStrategyRegistrar()
|
||||||
|
.registerHints(hints, getClass().getClassLoader());
|
||||||
|
// assert
|
||||||
|
assertThat(expectSnakeCaseHint).accepts(hints);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -18,6 +18,8 @@
|
||||||
<modules>
|
<modules>
|
||||||
<module>spring-cloud-config-server</module>
|
<module>spring-cloud-config-server</module>
|
||||||
<module>spring-cloud-config-client</module>
|
<module>spring-cloud-config-client</module>
|
||||||
|
<module>spring-cloud-config-overriding-properties-client</module>
|
||||||
|
<module>spring-cloud-config-overriding-properties-server</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
@ -36,4 +38,4 @@
|
||||||
<spring-cloud-dependencies.version>2021.0.3</spring-cloud-dependencies.version>
|
<spring-cloud-dependencies.version>2021.0.3</spring-cloud-dependencies.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?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">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>spring-cloud-config-overriding-properties-client</artifactId>
|
||||||
|
<name>spring-cloud-config-overriding-properties-client</name>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung.spring.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-config</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-config</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.baeldung.spring.cloud.config.overridingproperties;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Client {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Client.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.baeldung.spring.cloud.config.overridingproperties;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class HelloController {
|
||||||
|
|
||||||
|
@Value("${hello}")
|
||||||
|
private String hello;
|
||||||
|
|
||||||
|
@Value("${welcome}")
|
||||||
|
private String welcome;
|
||||||
|
|
||||||
|
@Value("${shared-property}")
|
||||||
|
private String shared;
|
||||||
|
|
||||||
|
@GetMapping("hello")
|
||||||
|
public String hello() {
|
||||||
|
return this.hello;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("welcome")
|
||||||
|
public String welcome() {
|
||||||
|
return this.welcome;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("shared")
|
||||||
|
public String shared() {
|
||||||
|
return this.shared;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
hello=Hello local property!
|
|
@ -0,0 +1,3 @@
|
||||||
|
spring.cloud.config.name=baeldung
|
||||||
|
spring.config.import=optional:configserver:http://localhost:8081
|
||||||
|
app.hello=Hello, overriden local property!
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.baeldung.spring.cloud.config.client;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
|
||||||
|
@ExtendWith(SpringExtension.class)
|
||||||
|
@SpringBootTest
|
||||||
|
public class SpringContextLiveTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void contextLoads() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?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">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>spring-cloud-config-overriding-properties-server</artifactId>
|
||||||
|
<name>spring-cloud-config-overriding-properties-server</name>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung.spring.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-config</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-config-server</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.baeldung.spring.cloud.config.overridingproperties;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.cloud.config.server.EnableConfigServer;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableConfigServer
|
||||||
|
public class ConfigServer {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(ConfigServer.class, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
server.port=8081
|
||||||
|
spring.cloud.config.server.native.search-locations=classpath:/config
|
||||||
|
#spring.cloud.config.server.overrides.hello=Hello Jane Doe - application.properties!
|
|
@ -0,0 +1 @@
|
||||||
|
shared-property=This property is shared accross all client applications
|
|
@ -0,0 +1,2 @@
|
||||||
|
hello=${app.hello:Hello Jane Doe!}
|
||||||
|
welcome=Welcome Jane Doe!
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.baeldung.spring.cloud.config.server;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
|
||||||
|
import com.baeldung.spring.cloud.config.overridingproperties.ConfigServer;
|
||||||
|
|
||||||
|
@ExtendWith(SpringExtension.class)
|
||||||
|
@SpringBootTest(classes = ConfigServer.class)
|
||||||
|
@ActiveProfiles("native")
|
||||||
|
public class SpringContextTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
spring.cloud.config.server.native.search-locations=classpath:/config
|
|
@ -111,12 +111,12 @@
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<spring-boot.version>2.5.1</spring-boot.version>
|
<spring-boot.version>2.7.1</spring-boot.version>
|
||||||
<spring-native.version>0.10.0</spring-native.version>
|
<spring-native.version>0.12.1</spring-native.version>
|
||||||
<native-maven-plugin.version>0.9.0</native-maven-plugin.version>
|
<native-maven-plugin.version>0.9.17</native-maven-plugin.version>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<maven.compiler.target>1.8</maven.compiler.target>
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
<maven.compiler.source>1.8</maven.compiler.source>
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -70,12 +70,12 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<builder>paketobuildpacks/builder:tiny</builder>
|
<builder>paketobuildpacks/builder:tiny</builder>
|
||||||
<spring-boot.version>2.5.1</spring-boot.version>
|
<spring-boot.version>2.7.1</spring-boot.version>
|
||||||
<spring-native.version>0.10.0</spring-native.version>
|
<spring-native.version>0.12.1</spring-native.version>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<maven.compiler.target>1.8</maven.compiler.target>
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
<maven.compiler.source>1.8</maven.compiler.source>
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
<log4j2.version>2.17.1</log4j2.version>
|
<log4j2.version>2.17.1</log4j2.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
package com.baeldung.clearsitedata;
|
package com.baeldung.clearsitedata;
|
||||||
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
|
||||||
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.web.authentication.logout.HeaderWriterLogoutHandler;
|
|
||||||
import org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter;
|
|
||||||
|
|
||||||
import static org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive.CACHE;
|
import static org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive.CACHE;
|
||||||
import static org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive.COOKIES;
|
import static org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive.COOKIES;
|
||||||
import static org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive.STORAGE;
|
import static org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive.STORAGE;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.logout.HeaderWriterLogoutHandler;
|
||||||
|
import org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
@EnableGlobalMethodSecurity(prePostEnabled = true)
|
||||||
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
|
public class SpringSecurityConfig {
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
http.csrf()
|
http.csrf()
|
||||||
.disable()
|
.disable()
|
||||||
.formLogin()
|
.formLogin()
|
||||||
|
@ -28,8 +28,9 @@ public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
.loginProcessingUrl("/perform_login")
|
.loginProcessingUrl("/perform_login")
|
||||||
.defaultSuccessUrl("/homepage.html", true)
|
.defaultSuccessUrl("/homepage.html", true)
|
||||||
.and()
|
.and()
|
||||||
.logout().logoutUrl("/baeldung/logout")
|
.logout()
|
||||||
.addLogoutHandler(new HeaderWriterLogoutHandler(
|
.logoutUrl("/baeldung/logout")
|
||||||
new ClearSiteDataHeaderWriter(CACHE, COOKIES, STORAGE)));
|
.addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(CACHE, COOKIES, STORAGE)));
|
||||||
|
return http.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,14 @@ package com.baeldung.session.security.config;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
|
||||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
|
import org.springframework.security.core.userdetails.User;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||||
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||||
import org.springframework.security.web.session.HttpSessionEventPublisher;
|
import org.springframework.security.web.session.HttpSessionEventPublisher;
|
||||||
|
|
||||||
|
@ -15,50 +17,56 @@ import com.baeldung.security.MySimpleUrlAuthenticationSuccessHandler;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
// @ImportResource({ "classpath:webSecurityConfig.xml" })
|
// @ImportResource({ "classpath:webSecurityConfig.xml" })
|
||||||
public class SecSecurityConfig extends WebSecurityConfigurerAdapter {
|
public class SecSecurityConfig {
|
||||||
|
|
||||||
public SecSecurityConfig() {
|
@Bean
|
||||||
super();
|
public InMemoryUserDetailsManager userDetailsService() {
|
||||||
|
UserDetails user1 = User.withUsername("user1")
|
||||||
|
.password(passwordEncoder().encode("user1Pass"))
|
||||||
|
.roles("USER")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
UserDetails admin1 = User.withUsername("admin1")
|
||||||
|
.password(passwordEncoder().encode("admin1Pass"))
|
||||||
|
.roles("ADMIN")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return new InMemoryUserDetailsManager(user1, admin1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Bean
|
||||||
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
|
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
// @formatter:off
|
http.csrf()
|
||||||
auth.inMemoryAuthentication()
|
.disable()
|
||||||
.withUser("user1").password(passwordEncoder().encode("user1Pass")).roles("USER")
|
.authorizeRequests()
|
||||||
.and()
|
.antMatchers("/anonymous*")
|
||||||
.withUser("admin1").password(passwordEncoder().encode("admin1Pass")).roles("ADMIN");
|
.anonymous()
|
||||||
// @formatter:on
|
.antMatchers("/login*", "/invalidSession*", "/sessionExpired*", "/foo/**")
|
||||||
}
|
.permitAll()
|
||||||
|
.anyRequest()
|
||||||
@Override
|
.authenticated()
|
||||||
protected void configure(final HttpSecurity http) throws Exception {
|
.and()
|
||||||
// @formatter:off
|
.formLogin()
|
||||||
http
|
.loginPage("/login.html")
|
||||||
.csrf().disable()
|
.loginProcessingUrl("/login")
|
||||||
.authorizeRequests()
|
.successHandler(successHandler())
|
||||||
.antMatchers("/anonymous*").anonymous()
|
.failureUrl("/login.html?error=true")
|
||||||
.antMatchers("/login*","/invalidSession*", "/sessionExpired*", "/foo/**").permitAll()
|
.and()
|
||||||
.anyRequest().authenticated()
|
.logout()
|
||||||
.and()
|
.deleteCookies("JSESSIONID")
|
||||||
.formLogin()
|
.and()
|
||||||
.loginPage("/login.html")
|
.rememberMe()
|
||||||
.loginProcessingUrl("/login")
|
.key("uniqueAndSecret")
|
||||||
.successHandler(successHandler())
|
.tokenValiditySeconds(86400)
|
||||||
.failureUrl("/login.html?error=true")
|
.and()
|
||||||
.and()
|
.sessionManagement()
|
||||||
.logout().deleteCookies("JSESSIONID")
|
.sessionFixation()
|
||||||
.and()
|
.migrateSession()
|
||||||
.rememberMe().key("uniqueAndSecret").tokenValiditySeconds(86400)
|
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
|
||||||
.and()
|
.invalidSessionUrl("/invalidSession.html")
|
||||||
.sessionManagement()
|
.maximumSessions(2)
|
||||||
.sessionFixation().migrateSession()
|
.expiredUrl("/sessionExpired.html");
|
||||||
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
|
return http.build();
|
||||||
.invalidSessionUrl("/invalidSession.html")
|
|
||||||
.maximumSessions(2)
|
|
||||||
.expiredUrl("/sessionExpired.html");
|
|
||||||
|
|
||||||
// @formatter:on
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private AuthenticationSuccessHandler successHandler() {
|
private AuthenticationSuccessHandler successHandler() {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
This module contains tutorials related to the tablesaw java library.
|
||||||
|
|
||||||
|
### Relevant Articles:
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>tablesaw</artifactId>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- TABLESAW -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>tech.tablesaw</groupId>
|
||||||
|
<artifactId>tablesaw-core</artifactId>
|
||||||
|
<version>${tablesaw.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<tablesaw.version>0.43.1</tablesaw.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.0</version>
|
||||||
|
<configuration>
|
||||||
|
<source>17</source>
|
||||||
|
<target>17</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,146 @@
|
||||||
|
package com.baeldung.tablesaw;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import tech.tablesaw.api.DateColumn;
|
||||||
|
import tech.tablesaw.api.DoubleColumn;
|
||||||
|
import tech.tablesaw.api.StringColumn;
|
||||||
|
import tech.tablesaw.api.Table;
|
||||||
|
import tech.tablesaw.api.TimeColumn;
|
||||||
|
import tech.tablesaw.io.csv.CsvReadOptions;
|
||||||
|
import tech.tablesaw.selection.Selection;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatNoException;
|
||||||
|
import static tech.tablesaw.aggregate.AggregateFunctions.max;
|
||||||
|
import static tech.tablesaw.aggregate.AggregateFunctions.mean;
|
||||||
|
import static tech.tablesaw.aggregate.AggregateFunctions.min;
|
||||||
|
import static tech.tablesaw.aggregate.AggregateFunctions.stdDev;
|
||||||
|
|
||||||
|
class CSVUnitTest {
|
||||||
|
|
||||||
|
private static Table table;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setup() {
|
||||||
|
URL resource = CSVUnitTest.class.getClassLoader().getResource("avocado.csv");
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||||
|
Path filePath = Paths.get(resource.getPath());
|
||||||
|
File file = filePath.toFile();
|
||||||
|
CsvReadOptions csvReadOptions =
|
||||||
|
CsvReadOptions.builder(file)
|
||||||
|
.separator(',')
|
||||||
|
.header(true)
|
||||||
|
.dateFormat(formatter)
|
||||||
|
.build();
|
||||||
|
table = Table.read().usingOptions(csvReadOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldReturnTheShapeStringOnAvocadoDataSet() {
|
||||||
|
assertThat(table.shape()).isEqualTo("avocado.csv: 18249 rows X 14 cols");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldOrderTheTableByDateInAscendingOrder() {
|
||||||
|
Table ascendingDateSortedTable = table.sortAscendingOn("Date");
|
||||||
|
assertThat(ascendingDateSortedTable.dateColumn("Date").get(0)).isEqualTo(LocalDate.parse("2015-01-04"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldOrderTheTableByDateInDescendingOrder() {
|
||||||
|
Table descendingDateSortedTable = table.sortDescendingOn("Date");
|
||||||
|
assertThat(descendingDateSortedTable.dateColumn("Date").get(0)).isEqualTo(LocalDate.parse("2018-03-25"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldOrderTheTableByYearAndAveragePriceInAscendingOrder() {
|
||||||
|
Table ascendingYearAndAveragePriceSortedTable = table.sortOn("year", "-AveragePrice");
|
||||||
|
assertThat(ascendingYearAndAveragePriceSortedTable.intColumn("year").get(0)).isEqualTo(2015);
|
||||||
|
assertThat(ascendingYearAndAveragePriceSortedTable.numberColumn("AveragePrice").get(0)).isEqualTo(2.79);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldRemoveTheValueWhenSettingAsMissing() {
|
||||||
|
DoubleColumn averagePrice = table.doubleColumn("AveragePrice").setMissing(0);
|
||||||
|
assertThat(averagePrice.get(0)).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldAppendDataToTheColumn() {
|
||||||
|
DoubleColumn averagePrice = table.doubleColumn("AveragePrice");
|
||||||
|
averagePrice.append(1.123);
|
||||||
|
assertThat(averagePrice.get(averagePrice.size() - 1)).isEqualTo(1.123);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldAppendDataToAveragePriceColumn() {
|
||||||
|
DoubleColumn averagePrice2 = table.doubleColumn("AveragePrice").copy();
|
||||||
|
averagePrice2.setName("AveragePrice2");
|
||||||
|
averagePrice2.append(1.123);
|
||||||
|
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> table.addColumns(averagePrice2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldReturnTheTableContainingDataFrom2017andAveragePriceIsGreaterThan2Only() {
|
||||||
|
DateColumn dateTable = table.dateColumn("Date");
|
||||||
|
DoubleColumn averagePrice = table.doubleColumn("AveragePrice");
|
||||||
|
Selection selection = dateTable.isInYear(2017).and(averagePrice.isGreaterThan(2D));
|
||||||
|
Table table2017 = table.where(selection);
|
||||||
|
assertThat(table2017.intColumn("year")).containsOnly(2017);
|
||||||
|
assertThat(table2017.doubleColumn("AveragePrice")).allMatch(avrgPrice -> avrgPrice > 2D);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldPrintToStandardOutputStatisticsOfAveragePriceByYearData() {
|
||||||
|
Table summary = table.summarize("AveragePrice", max, min, mean, stdDev).by("year");
|
||||||
|
System.out.println(summary.print());
|
||||||
|
Assertions.assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldThrowIllegalArgumentExceptionWhenCreatingTableWithDifferentSizeColumns() {
|
||||||
|
StringColumn type = StringColumn.create("type");
|
||||||
|
StringColumn region = StringColumn.create("region");
|
||||||
|
type.addAll(List.of("Country", "City"));
|
||||||
|
region.append("USA");
|
||||||
|
assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> Table.create(type, region));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldNotThrowIllegalArgumentExceptionWhenCreatingTableWithDifferentSameSizeColumns() {
|
||||||
|
StringColumn type = StringColumn.create("type");
|
||||||
|
StringColumn region = StringColumn.create("region");
|
||||||
|
type.addAll(List.of("Country", "City"));
|
||||||
|
region.append("USA");
|
||||||
|
region.appendMissing();
|
||||||
|
assertThatNoException().isThrownBy(() -> Table.create(type, region));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldAddColumnToTable() {
|
||||||
|
TimeColumn time = TimeColumn.create("time");
|
||||||
|
Table table = Table.create("test");
|
||||||
|
table.addColumns(time);
|
||||||
|
assertThat(table.columnNames()).contains("time");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldBeEqualTwoValuesFromDifferentRowsOnTheTypeColumn() {
|
||||||
|
StringColumn type = table.stringColumn("type");
|
||||||
|
List<String> conventional = type.where(type.isEqualTo("conventional")).asList().stream()
|
||||||
|
.limit(2)
|
||||||
|
.toList();
|
||||||
|
assertThat(conventional.get(0)).isSameAs(conventional.get(1));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue