Merge branch 'eugenp:master' into PR-7145
|
@ -5,6 +5,5 @@ This module contains articles about various Amazon Web Services (AWS) such as EC
|
||||||
### Relevant articles
|
### Relevant articles
|
||||||
|
|
||||||
- [Managing EC2 Instances in Java](https://www.baeldung.com/ec2-java)
|
- [Managing EC2 Instances in Java](https://www.baeldung.com/ec2-java)
|
||||||
- [Integration Testing with a Local DynamoDB Instance](https://www.baeldung.com/dynamodb-local-integration-tests)
|
|
||||||
- [Managing Amazon SQS Queues in Java](https://www.baeldung.com/aws-queues-java)
|
- [Managing Amazon SQS Queues in Java](https://www.baeldung.com/aws-queues-java)
|
||||||
- [Guide to AWS Aurora RDS with Java](https://www.baeldung.com/aws-aurora-rds-java)
|
- [Guide to AWS Aurora RDS with Java](https://www.baeldung.com/aws-aurora-rds-java)
|
||||||
|
|
|
@ -11,5 +11,5 @@ This module contains articles about Java 8 core features
|
||||||
- [Finding Min/Max in an Array with Java](https://www.baeldung.com/java-array-min-max)
|
- [Finding Min/Max in an Array with Java](https://www.baeldung.com/java-array-min-max)
|
||||||
- [Internationalization and Localization in Java 8](https://www.baeldung.com/java-8-localization)
|
- [Internationalization and Localization in Java 8](https://www.baeldung.com/java-8-localization)
|
||||||
- [Generalized Target-Type Inference in Java](https://www.baeldung.com/java-generalized-target-type-inference)
|
- [Generalized Target-Type Inference in Java](https://www.baeldung.com/java-generalized-target-type-inference)
|
||||||
- [Monads in Java](https://www.baeldung.com/java-monads)
|
- [Monads in Java – Optional](https://www.baeldung.com/java-monads)
|
||||||
- [[More -->]](/core-java-modules/core-java-8-2)
|
- [[More -->]](/core-java-modules/core-java-8-2)
|
||||||
|
|
|
@ -3,3 +3,4 @@
|
||||||
This module contains articles about Java array fundamentals. They assume no previous background knowledge on working with arrays.
|
This module contains articles about Java array fundamentals. They assume no previous background knowledge on working with arrays.
|
||||||
|
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
|
- [Arrays mismatch() Method in Java](https://www.baeldung.com/java-arrays-mismatch)
|
||||||
|
|
|
@ -7,4 +7,5 @@
|
||||||
- [Creating Custom Iterator in Java](https://www.baeldung.com/java-creating-custom-iterator)
|
- [Creating Custom Iterator in Java](https://www.baeldung.com/java-creating-custom-iterator)
|
||||||
- [Difference Between Arrays.sort() and Collections.sort()](https://www.baeldung.com/java-arrays-collections-sort-methods)
|
- [Difference Between Arrays.sort() and Collections.sort()](https://www.baeldung.com/java-arrays-collections-sort-methods)
|
||||||
- [Skipping the First Iteration in Java](https://www.baeldung.com/java-skip-first-iteration)
|
- [Skipping the First Iteration in Java](https://www.baeldung.com/java-skip-first-iteration)
|
||||||
|
- [Remove Elements From a Queue Using Loop](https://www.baeldung.com/java-remove-elements-queue)
|
||||||
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-4)
|
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-4)
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
## Relevant Articles
|
## Relevant Articles
|
||||||
- [Difference Between putIfAbsent() and computeIfAbsent() in Java’s Map](https://www.baeldung.com/java-map-putifabsent-computeifabsent)
|
- [Difference Between putIfAbsent() and computeIfAbsent() in Java’s Map](https://www.baeldung.com/java-map-putifabsent-computeifabsent)
|
||||||
|
- [How to Write Hashmap to CSV File](https://www.baeldung.com/java-write-hashmap-csv)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
### Relevant Articles:
|
||||||
|
- [Why wait() Requires Synchronization?](https://www.baeldung.com/java-wait-necessary-synchronization)
|
|
@ -10,4 +10,5 @@ This module contains articles about basic Java concurrency.
|
||||||
- [Returning a Value After Finishing Thread’s Job in Java](https://www.baeldung.com/java-return-value-after-thread-finish)
|
- [Returning a Value After Finishing Thread’s Job in Java](https://www.baeldung.com/java-return-value-after-thread-finish)
|
||||||
- [CompletableFuture and ThreadPool in Java](https://www.baeldung.com/java-completablefuture-threadpool)
|
- [CompletableFuture and ThreadPool in Java](https://www.baeldung.com/java-completablefuture-threadpool)
|
||||||
- [CompletableFuture allOf().join() vs. CompletableFuture.join()](https://www.baeldung.com/java-completablefuture-allof-join)
|
- [CompletableFuture allOf().join() vs. CompletableFuture.join()](https://www.baeldung.com/java-completablefuture-allof-join)
|
||||||
|
- [Retry Logic with CompletableFuture](https://www.baeldung.com/java-completablefuture-retry-logic)
|
||||||
- [[<-- Prev]](../core-java-concurrency-basic-2)
|
- [[<-- Prev]](../core-java-concurrency-basic-2)
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
package com.baeldung.concurrent.completablefuturelist;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
ScheduledExecutorService asyncOperationEmulation;
|
||||||
|
|
||||||
|
Application initialize() {
|
||||||
|
asyncOperationEmulation = Executors.newScheduledThreadPool(10);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompletableFuture<String> asyncOperation(String operationId) {
|
||||||
|
CompletableFuture<String> cf = new CompletableFuture<>();
|
||||||
|
asyncOperationEmulation.submit(() -> {
|
||||||
|
// The following lines simulate an exception happening on the 567th operation
|
||||||
|
// if (operationId.endsWith("567")) {
|
||||||
|
// cf.completeExceptionally(new Exception("Error on operation " + operationId));
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
cf.complete(operationId);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
System.err.println("Thread interrupted error");
|
||||||
|
cf.completeExceptionally(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return cf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void startNaive() {
|
||||||
|
List<CompletableFuture<String>> futures = new ArrayList<>();
|
||||||
|
for (int i = 1; i <= 1000; i++) {
|
||||||
|
String operationId = "Naive-Operation-" + i;
|
||||||
|
futures.add(asyncOperation(operationId));
|
||||||
|
}
|
||||||
|
|
||||||
|
CompletableFuture<List<String>> aggregate = CompletableFuture.completedFuture(new ArrayList<>());
|
||||||
|
for (CompletableFuture<String> future : futures) {
|
||||||
|
aggregate = aggregate.thenCompose(list -> {
|
||||||
|
try {
|
||||||
|
list.add(future.get());
|
||||||
|
return CompletableFuture.completedFuture(list);
|
||||||
|
} catch (Exception e) {
|
||||||
|
final CompletableFuture<List<String>> excFuture = new CompletableFuture<>();
|
||||||
|
excFuture.completeExceptionally(e);
|
||||||
|
return excFuture;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final List<String> results = aggregate.join();
|
||||||
|
System.out.println("Printing first 10 results");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println("Finished " + results.get(i));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void start() {
|
||||||
|
List<CompletableFuture<String>> futures = new ArrayList<>();
|
||||||
|
for (int i = 1; i <= 1000; i++) {
|
||||||
|
String operationId = "Operation-" + i;
|
||||||
|
futures.add(asyncOperation(operationId));
|
||||||
|
}
|
||||||
|
CompletableFuture<?>[] futuresArray = futures.toArray(new CompletableFuture<?>[0]);
|
||||||
|
CompletableFuture<List<String>> listFuture = CompletableFuture.allOf(futuresArray).thenApply(v -> futures.stream().map(CompletableFuture::join).collect(Collectors.toList()));
|
||||||
|
try {
|
||||||
|
final List<String> results = listFuture.join();
|
||||||
|
System.out.println("Printing first 10 results");
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
System.out.println("Finished " + results.get(i));
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() {
|
||||||
|
asyncOperationEmulation.shutdownNow();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
new Application().initialize()
|
||||||
|
// Switch between .startNaive() and .start() to test both implementations
|
||||||
|
// .startNaive();
|
||||||
|
.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -12,6 +12,7 @@ This module contains articles about Java Concurrency that are also part of an Eb
|
||||||
- [Guide to the Volatile Keyword in Java](https://www.baeldung.com/java-volatile)
|
- [Guide to the Volatile Keyword in Java](https://www.baeldung.com/java-volatile)
|
||||||
- [A Guide to the Java ExecutorService](https://www.baeldung.com/java-executor-service-tutorial)
|
- [A Guide to the Java ExecutorService](https://www.baeldung.com/java-executor-service-tutorial)
|
||||||
- [Guide To CompletableFuture](https://www.baeldung.com/java-completablefuture)
|
- [Guide To CompletableFuture](https://www.baeldung.com/java-completablefuture)
|
||||||
|
- [How To Manage Timeout for CompletableFuture](https://www.baeldung.com/java-completablefuture-timeout)
|
||||||
|
|
||||||
### NOTE:
|
### NOTE:
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,21 @@
|
||||||
<artifactId>simplemagic</artifactId>
|
<artifactId>simplemagic</artifactId>
|
||||||
<version>${simplemagic.version}</version>
|
<version>${simplemagic.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<version>${commons-io.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjdk.jmh</groupId>
|
||||||
|
<artifactId>jmh-core</artifactId>
|
||||||
|
<version>${jmh.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openjdk.jmh</groupId>
|
||||||
|
<artifactId>jmh-generator-annprocess</artifactId>
|
||||||
|
<version>${jmh.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -62,5 +77,6 @@
|
||||||
<jmime-magic.version>0.1.5</jmime-magic.version>
|
<jmime-magic.version>0.1.5</jmime-magic.version>
|
||||||
<jodd-util.version>6.2.1</jodd-util.version>
|
<jodd-util.version>6.2.1</jodd-util.version>
|
||||||
<simplemagic.version>1.17</simplemagic.version>
|
<simplemagic.version>1.17</simplemagic.version>
|
||||||
|
<jmh.version>1.37</jmh.version>
|
||||||
</properties>
|
</properties>
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,112 @@
|
||||||
|
package com.baeldung.zip;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.zip.*;
|
||||||
|
|
||||||
|
import org.openjdk.jmh.annotations.*;
|
||||||
|
import org.openjdk.jmh.infra.Blackhole;
|
||||||
|
import org.openjdk.jmh.runner.Runner;
|
||||||
|
import org.openjdk.jmh.runner.options.Options;
|
||||||
|
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||||
|
|
||||||
|
@State(Scope.Benchmark)
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
@Warmup(iterations = 1, time = 2, timeUnit = TimeUnit.SECONDS)
|
||||||
|
@Measurement(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS)
|
||||||
|
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||||
|
@Fork(value = 1)
|
||||||
|
public class ZipBenchmark {
|
||||||
|
|
||||||
|
public static final int NUM_OF_FILES = 10;
|
||||||
|
public static final int DATA_SIZE = 204800;
|
||||||
|
|
||||||
|
@State(Scope.Thread)
|
||||||
|
public static class SourceState {
|
||||||
|
|
||||||
|
public File compressedFile;
|
||||||
|
|
||||||
|
@Setup(Level.Trial)
|
||||||
|
public void setup() throws IOException {
|
||||||
|
ZipSampleFileStore sampleFileStore = new ZipSampleFileStore(NUM_OF_FILES, DATA_SIZE);
|
||||||
|
compressedFile = sampleFileStore.getFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
@TearDown(Level.Trial)
|
||||||
|
public void cleanup() {
|
||||||
|
if (compressedFile.exists()) {
|
||||||
|
compressedFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public static void readAllEntriesByZipFile(SourceState sourceState, Blackhole blackhole) throws IOException {
|
||||||
|
|
||||||
|
try (ZipFile zipFile = new ZipFile(sourceState.compressedFile)) {
|
||||||
|
Enumeration<? extends ZipEntry> zipEntries = zipFile.entries();
|
||||||
|
while (zipEntries.hasMoreElements()) {
|
||||||
|
ZipEntry zipEntry = zipEntries.nextElement();
|
||||||
|
try (InputStream inputStream = new BufferedInputStream(zipFile.getInputStream(zipEntry))) {
|
||||||
|
blackhole.consume(ZipSampleFileStore.getString(inputStream));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public static void readAllEntriesByZipInputStream(SourceState sourceState, Blackhole blackhole) throws IOException {
|
||||||
|
|
||||||
|
try (
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceState.compressedFile));
|
||||||
|
ZipInputStream zipInputStream = new ZipInputStream(bis)
|
||||||
|
) {
|
||||||
|
ZipEntry entry;
|
||||||
|
while ((entry = zipInputStream.getNextEntry()) != null) {
|
||||||
|
blackhole.consume(ZipSampleFileStore.getString(zipInputStream));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public static void readLastEntryByZipFile(SourceState sourceState, Blackhole blackhole) throws IOException {
|
||||||
|
|
||||||
|
try (ZipFile zipFile = new ZipFile(sourceState.compressedFile)) {
|
||||||
|
ZipEntry zipEntry = zipFile.getEntry(getLastEntryName());
|
||||||
|
try (InputStream inputStream = new BufferedInputStream(zipFile.getInputStream(zipEntry))) {
|
||||||
|
blackhole.consume(ZipSampleFileStore.getString(inputStream));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public static void readLastEntryByZipInputStream(SourceState sourceState, Blackhole blackhole) throws IOException {
|
||||||
|
|
||||||
|
try (
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceState.compressedFile));
|
||||||
|
ZipInputStream zipInputStream = new ZipInputStream(bis)
|
||||||
|
) {
|
||||||
|
ZipEntry entry;
|
||||||
|
while ((entry = zipInputStream.getNextEntry()) != null) {
|
||||||
|
if (Objects.equals(entry.getName(), getLastEntryName())){
|
||||||
|
blackhole.consume(ZipSampleFileStore.getString(zipInputStream));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getLastEntryName() {
|
||||||
|
return String.format(ZipSampleFileStore.ENTRY_NAME_PATTERN, NUM_OF_FILES);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Options options = new OptionsBuilder()
|
||||||
|
.include(ZipBenchmark.class.getSimpleName()).threads(1)
|
||||||
|
.shouldFailOnError(true)
|
||||||
|
.shouldDoGC(true)
|
||||||
|
.jvmArgs("-server").build();
|
||||||
|
new Runner(options).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
package com.baeldung.zip;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
public class ZipSampleFileStore {
|
||||||
|
|
||||||
|
public static final String ENTRY_NAME_PATTERN = "str-data-%s.txt";
|
||||||
|
private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
private final File file;
|
||||||
|
private final List<String> dataList;
|
||||||
|
|
||||||
|
public ZipSampleFileStore(int numOfFiles, int fileSize) throws IOException {
|
||||||
|
|
||||||
|
dataList = new ArrayList<>(numOfFiles);
|
||||||
|
file = File.createTempFile("zip-sample", "");
|
||||||
|
|
||||||
|
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(file))) {
|
||||||
|
|
||||||
|
for (int idx=0; idx<=numOfFiles; idx++) {
|
||||||
|
|
||||||
|
byte[] data = createRandomStringInByte(fileSize);
|
||||||
|
dataList.add(new String(data, DEFAULT_ENCODING));
|
||||||
|
|
||||||
|
ZipEntry entry = new ZipEntry(String.format(ENTRY_NAME_PATTERN, idx));
|
||||||
|
zos.putNextEntry(entry);
|
||||||
|
zos.write(data);
|
||||||
|
zos.closeEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] createRandomStringInByte(int size) {
|
||||||
|
Random random = new Random();
|
||||||
|
byte[] data = new byte[size];
|
||||||
|
for (int n = 0; n < data.length; n++) {
|
||||||
|
char randomChar;
|
||||||
|
int choice = random.nextInt(2); // 0 for uppercase, 1 for lowercase
|
||||||
|
if (choice == 0) {
|
||||||
|
randomChar = (char) ('A' + random.nextInt(26)); // 'A' to 'Z'
|
||||||
|
} else {
|
||||||
|
randomChar = (char) ('a' + random.nextInt(26)); // 'a' to 'z'
|
||||||
|
}
|
||||||
|
data[n] = (byte) randomChar;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getFile() {
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getDataList() {
|
||||||
|
return dataList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getString(InputStream inputStream) throws IOException {
|
||||||
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
|
IOUtils.copy(inputStream, byteArrayOutputStream);
|
||||||
|
return byteArrayOutputStream.toString(DEFAULT_ENCODING);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.baeldung.zip;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.zip.*;
|
||||||
|
|
||||||
|
import org.junit.*;
|
||||||
|
|
||||||
|
public class ZipUnitTest {
|
||||||
|
|
||||||
|
private static File compressedFile;
|
||||||
|
private static List<String> dataList = new ArrayList<>();
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void prepareData() throws IOException {
|
||||||
|
ZipSampleFileStore sampleFileStore = new ZipSampleFileStore(ZipBenchmark.NUM_OF_FILES, ZipBenchmark.DATA_SIZE);
|
||||||
|
compressedFile = sampleFileStore.getFile();
|
||||||
|
dataList = sampleFileStore.getDataList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCreateZipFile_thenCompressedSizeShouldBeLessThanOriginal() throws IOException {
|
||||||
|
byte[] data = ZipSampleFileStore.createRandomStringInByte(10240);
|
||||||
|
File file = File.createTempFile("zip-temp", "");
|
||||||
|
|
||||||
|
try (
|
||||||
|
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
|
||||||
|
ZipOutputStream zos = new ZipOutputStream(bos)
|
||||||
|
) {
|
||||||
|
ZipEntry zipEntry = new ZipEntry("zip-entry.txt");
|
||||||
|
zos.putNextEntry(zipEntry);
|
||||||
|
zos.write(data);
|
||||||
|
zos.closeEntry();
|
||||||
|
|
||||||
|
assertThat(file.length()).isLessThan(data.length);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenReadAllEntriesViaZipFile_thenDataIsEqualtoTheSource() throws IOException {
|
||||||
|
|
||||||
|
try (ZipFile zipFile = new ZipFile(compressedFile)) {
|
||||||
|
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||||
|
List<? extends ZipEntry> entryList = Collections.list(entries);
|
||||||
|
|
||||||
|
for (int idx=0; idx<entryList.size(); idx++) {
|
||||||
|
ZipEntry zipEntry = entryList.get(idx);
|
||||||
|
try (InputStream inputStream = zipFile.getInputStream(zipEntry)) {
|
||||||
|
String actual = ZipSampleFileStore.getString(inputStream);
|
||||||
|
assertThat(actual).as("Data for ZIP entry: " + zipEntry.getName()).isEqualTo(dataList.get(idx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenReadAllEntriesViaZipInputStream_thenDataIsEqualtoTheSource() throws IOException {
|
||||||
|
int idx = 0;
|
||||||
|
try (
|
||||||
|
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(compressedFile));
|
||||||
|
ZipInputStream zipInputStream = new ZipInputStream(bis)
|
||||||
|
) {
|
||||||
|
ZipEntry zipEntry;
|
||||||
|
while ((zipEntry = zipInputStream.getNextEntry()) != null) {
|
||||||
|
String actual = ZipSampleFileStore.getString(zipInputStream);
|
||||||
|
assertThat(actual).as("Data for ZIP entry: " + zipEntry.getName()).isEqualTo(dataList.get(idx++));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void cleanup() {
|
||||||
|
if (compressedFile.exists()) {
|
||||||
|
compressedFile.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
I'm going to Alabama
|
||||||
|
Alabama is a state in the US
|
|
@ -0,0 +1 @@
|
||||||
|
Dreams from My Father by Barack Obama
|
|
@ -0,0 +1 @@
|
||||||
|
Harry Potter and the Chamber of Secrets
|
|
@ -0,0 +1,64 @@
|
||||||
|
package com.baeldung.printwritervsfilewriter;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class PrintWriterVsFilePrinterUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenWritingToTextFileUsingFileWriter_thenTextMatches() throws IOException {
|
||||||
|
String result = "Harry Potter and the Chamber of Secrets";
|
||||||
|
|
||||||
|
File file = new File("potter.txt");
|
||||||
|
try (FileWriter fw = new FileWriter(file);) {
|
||||||
|
fw.write("Harry Potter and the Chamber of Secrets");
|
||||||
|
}
|
||||||
|
|
||||||
|
try (BufferedReader reader = new BufferedReader(new FileReader(file));) {
|
||||||
|
String actualData = reader.readLine();
|
||||||
|
assertEquals(result, actualData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenWritingToTextFileUsingPrintWriterPrintf_thenTextMatches() throws IOException {
|
||||||
|
String result = "Dreams from My Father by Barack Obama";
|
||||||
|
File file = new File("dream.txt");
|
||||||
|
try (PrintWriter pw = new PrintWriter(file);) {
|
||||||
|
String author = "Barack Obama";
|
||||||
|
pw.printf("Dreams from My Father by %s", author);
|
||||||
|
assertTrue(!pw.checkError());
|
||||||
|
}
|
||||||
|
|
||||||
|
try (BufferedReader reader = new BufferedReader(new FileReader(file));) {
|
||||||
|
String actualData = reader.readLine();
|
||||||
|
assertEquals(result, actualData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenWritingToTextFileUsingPrintWriterPrintln_thenTextMatches() throws IOException {
|
||||||
|
String result = "I'm going to Alabama\nAlabama is a state in the US\n";
|
||||||
|
try (PrintWriter pw = new PrintWriter("alabama.txt");) {
|
||||||
|
pw.println("I'm going to Alabama");
|
||||||
|
pw.println("Alabama is a state in the US");
|
||||||
|
}
|
||||||
|
Path path = Paths.get("alabama.txt");
|
||||||
|
String actualData = new String(Files.readAllBytes(path));
|
||||||
|
assertEquals(result, actualData);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,3 +4,4 @@
|
||||||
- [Aggregate Runtime Exceptions in Java Streams](https://www.baeldung.com/java-streams-aggregate-exceptions)
|
- [Aggregate Runtime Exceptions in Java Streams](https://www.baeldung.com/java-streams-aggregate-exceptions)
|
||||||
- [Streams vs. Loops in Java](https://www.baeldung.com/java-streams-vs-loops)
|
- [Streams vs. Loops in Java](https://www.baeldung.com/java-streams-vs-loops)
|
||||||
- [Partition a Stream in Java](https://www.baeldung.com/java-partition-stream)
|
- [Partition a Stream in Java](https://www.baeldung.com/java-partition-stream)
|
||||||
|
- [Taking Every N-th Element from Finite and Infinite Streams in Java](https://www.baeldung.com/java-nth-element-finite-infinite-streams)
|
||||||
|
|
|
@ -13,3 +13,4 @@ This module contains articles about string-related algorithms.
|
||||||
- [Find the Most Frequent Characters in a String](https://www.baeldung.com/java-string-find-most-frequent-characters)
|
- [Find the Most Frequent Characters in a String](https://www.baeldung.com/java-string-find-most-frequent-characters)
|
||||||
- [Checking If a String Is a Repeated Substring](https://www.baeldung.com/java-repeated-substring)
|
- [Checking If a String Is a Repeated Substring](https://www.baeldung.com/java-repeated-substring)
|
||||||
- [Check if Letter Is Emoji With Java](https://www.baeldung.com/java-check-letter-emoji)
|
- [Check if Letter Is Emoji With Java](https://www.baeldung.com/java-check-letter-emoji)
|
||||||
|
- [Wrapping a String After a Number of Characters Word-Wise](https://www.baeldung.com/java-wrap-string-number-characters-word-wise)
|
||||||
|
|
|
@ -3,3 +3,5 @@
|
||||||
- [Convert String to Int Using Encapsulation](https://www.baeldung.com/java-encapsulation-convert-string-to-int)
|
- [Convert String to Int Using Encapsulation](https://www.baeldung.com/java-encapsulation-convert-string-to-int)
|
||||||
- [HashMap with Multiple Values for the Same Key](https://www.baeldung.com/java-hashmap-multiple-values-per-key)
|
- [HashMap with Multiple Values for the Same Key](https://www.baeldung.com/java-hashmap-multiple-values-per-key)
|
||||||
- [Split Java String Into Key-Value Pairs](https://www.baeldung.com/java-split-string-map)
|
- [Split Java String Into Key-Value Pairs](https://www.baeldung.com/java-split-string-map)
|
||||||
|
- [How to Center Text Output in Java](https://www.baeldung.com/java-center-text-output)
|
||||||
|
- [How to Convert an Object to String](https://www.baeldung.com/java-object-string-representation)
|
||||||
|
|
|
@ -11,4 +11,4 @@
|
||||||
- [Check if a String Has All Unique Characters in Java](https://www.baeldung.com/java-check-string-all-unique-chars)
|
- [Check if a String Has All Unique Characters in Java](https://www.baeldung.com/java-check-string-all-unique-chars)
|
||||||
- [Performance Comparison Between Different Java String Concatenation Methods](https://www.baeldung.com/java-string-concatenation-methods)
|
- [Performance Comparison Between Different Java String Concatenation Methods](https://www.baeldung.com/java-string-concatenation-methods)
|
||||||
- [Replacing Single Quote with \’ in Java String](https://www.baeldung.com/java-replacing-single-quote-string)
|
- [Replacing Single Quote with \’ in Java String](https://www.baeldung.com/java-replacing-single-quote-string)
|
||||||
|
- [Check if a String Contains a Number Value in Java](https://www.baeldung.com/java-string-number-presence)
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
|
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
|
- [How to Center Text Output in Java](https://www.baeldung.com/java-center-text-output)
|
||||||
|
- [Capitalize the First Letter of Each Word in a String](https://www.baeldung.com/java-string-initial-capital-letter-every-word)
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.baeldung.passstringbyreference;
|
||||||
|
|
||||||
|
public class Dummy {
|
||||||
|
|
||||||
|
String dummyString;
|
||||||
|
|
||||||
|
public String getDummyString() {
|
||||||
|
return dummyString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDummyString(String dummyString) {
|
||||||
|
this.dummyString = dummyString;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package com.baeldung.passstringbyreference;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class PassStringUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenAString_whenPassedToVoidMethod_thenStringIsNotModified() {
|
||||||
|
String s = "hello";
|
||||||
|
concatStringWithNoReturn(s);
|
||||||
|
assertEquals("hello", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void concatStringWithNoReturn(String input) {
|
||||||
|
input += " world";
|
||||||
|
assertEquals("hello world", input);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenAString_whenPassedToMethodAndReturnNewString_thenStringIsModified() {
|
||||||
|
String s = "hello";
|
||||||
|
assertEquals("hello world", concatStringWithReturn(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
String concatStringWithReturn(String input) {
|
||||||
|
return input + " world";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenAString_whenPassStringBuilderToVoidMethod_thenConcatNewStringOk() {
|
||||||
|
StringBuilder builder = new StringBuilder("hello");
|
||||||
|
concatWithStringBuilder(builder);
|
||||||
|
|
||||||
|
assertEquals("hello world", builder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void concatWithStringBuilder(StringBuilder input) {
|
||||||
|
input.append(" world");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenAString_whenPassStringBufferToVoidMethod_thenConcatNewStringOk() {
|
||||||
|
StringBuffer builder = new StringBuffer("hello");
|
||||||
|
concatWithStringBuffer(builder);
|
||||||
|
|
||||||
|
assertEquals("hello world", builder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void concatWithStringBuffer(StringBuffer input) {
|
||||||
|
input.append(" world");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenObjectWithStringField_whenSetDifferentValue_thenObjectIsModified() {
|
||||||
|
Dummy dummy = new Dummy();
|
||||||
|
assertNull(dummy.getDummyString());
|
||||||
|
modifyStringValueInInputObject(dummy, "hello world");
|
||||||
|
assertEquals("hello world", dummy.getDummyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void modifyStringValueInInputObject(Dummy dummy, String dummyString) {
|
||||||
|
dummy.setDummyString(dummyString);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenObjectWithStringField_whenSetDifferentValueWithStringBuilder_thenSetStringInNewObject() {
|
||||||
|
assertEquals("hello world", getDummy("hello", "world").getDummyString());
|
||||||
|
}
|
||||||
|
|
||||||
|
Dummy getDummy(String hello, String world) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
builder.append(hello)
|
||||||
|
.append(" ")
|
||||||
|
.append(world);
|
||||||
|
|
||||||
|
Dummy dummy = new Dummy();
|
||||||
|
dummy.setDummyString(builder.toString());
|
||||||
|
|
||||||
|
return dummy;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,4 +3,4 @@
|
||||||
|
|
||||||
- [Transferring a File Through SFTP in Java](https://www.baeldung.com/java-file-sftp)
|
- [Transferring a File Through SFTP in Java](https://www.baeldung.com/java-file-sftp)
|
||||||
- [How to Create Password-Protected Zip Files and Unzip Them in Java](https://www.baeldung.com/java-password-protected-zip-unzip)
|
- [How to Create Password-Protected Zip Files and Unzip Them in Java](https://www.baeldung.com/java-password-protected-zip-unzip)
|
||||||
|
- [How to Create CSV File from POJO with Custom Column Headers and Positions](https://www.baeldung.com/java-create-csv-pojo-customize-columns)
|
||||||
|
|
|
@ -22,6 +22,7 @@ public class EditorUnitTest {
|
||||||
loadAndVerifyTestData(entityManagerFactory, editor);
|
loadAndVerifyTestData(entityManagerFactory, editor);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenNeo4j_WhenEntitiesCreated_thenCanBeRetrieved() throws Exception {
|
public void givenNeo4j_WhenEntitiesCreated_thenCanBeRetrieved() throws Exception {
|
||||||
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("ogm-neo4j");
|
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("ogm-neo4j");
|
||||||
|
|
|
@ -106,6 +106,7 @@
|
||||||
<module>spring-jpa</module>
|
<module>spring-jpa</module>
|
||||||
<module>spring-jpa-2</module>
|
<module>spring-jpa-2</module>
|
||||||
<module>spring-jdbc</module>
|
<module>spring-jdbc</module>
|
||||||
|
<module>spring-jdbc-2</module>
|
||||||
<module>spring-jooq</module>
|
<module>spring-jooq</module>
|
||||||
<module>spring-mybatis</module>
|
<module>spring-mybatis</module>
|
||||||
<module>spring-persistence-simple</module>
|
<module>spring-persistence-simple</module>
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>org.example</groupId>
|
||||||
|
<artifactId>spring-jdbc-2</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<name>spring-jdbc-2</name>
|
||||||
|
<description>Demo project for Spring Jdbc</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-boot-3</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../../parent-boot-3</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<scope>runtime</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>spring-milestones</id>
|
||||||
|
<name>Spring Milestones</name>
|
||||||
|
<url>https://repo.spring.io/milestone</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>spring-snapshots</id>
|
||||||
|
<name>Spring Snapshots</name>
|
||||||
|
<url>https://repo.spring.io/snapshot</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</releases>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<pluginRepositories>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>spring-milestones</id>
|
||||||
|
<name>Spring Milestones</name>
|
||||||
|
<url>https://repo.spring.io/milestone</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</pluginRepository>
|
||||||
|
<pluginRepository>
|
||||||
|
<id>spring-snapshots</id>
|
||||||
|
<name>Spring Snapshots</name>
|
||||||
|
<url>https://repo.spring.io/snapshot</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</releases>
|
||||||
|
</pluginRepository>
|
||||||
|
</pluginRepositories>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<spring-boot.version>3.2.0-SNAPSHOT</spring-boot.version>
|
||||||
|
<junit-jupiter.version>5.10.0</junit-jupiter.version>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.baeldung.jdbcclient;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@ComponentScan(basePackages = "com.baledung.jdbcclient")
|
||||||
|
public class JdbcClientDemoApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(JdbcClientDemoApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
package com.baeldung.jdbcclient.dao;
|
||||||
|
|
||||||
|
import com.baeldung.jdbcclient.model.Student;
|
||||||
|
import com.baeldung.jdbcclient.model.StudentResultExtractor;
|
||||||
|
import com.baeldung.jdbcclient.model.StudentRowMapper;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.jdbc.core.RowCountCallbackHandler;
|
||||||
|
import org.springframework.jdbc.core.simple.JdbcClient;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.sql.Types;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public class StudentDao {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(StudentDao.class);
|
||||||
|
@Autowired
|
||||||
|
private JdbcClient jdbcClient;
|
||||||
|
|
||||||
|
public Integer insertWithSetParamWithNamedParamAndSqlType(Student student) {
|
||||||
|
String sql = "INSERT INTO student (student_name, age, grade, gender, state)"
|
||||||
|
+ "VALUES (:name, :age, :grade, :gender, :state)";
|
||||||
|
Integer noOfrowsAffected = this.jdbcClient.sql(sql)
|
||||||
|
.param("name", student.getStudentName(), Types.VARCHAR)
|
||||||
|
.param("age", student.getAge(), Types.INTEGER)
|
||||||
|
.param("grade", student.getGrade(), Types.INTEGER)
|
||||||
|
.param("gender", student.getStudentGender(), Types.VARCHAR)
|
||||||
|
.param("state", student.getState(), Types.VARCHAR)
|
||||||
|
.update();
|
||||||
|
logger.info("No. of rows affected: " + noOfrowsAffected);
|
||||||
|
return noOfrowsAffected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Student> getStudentsOfGradeStateAndGenderWithPositionalParams(int grade, String state, String gender) {
|
||||||
|
String sql = "select student_id, student_name, age, grade, gender, state from student"
|
||||||
|
+ " where grade = ? and state = ? and gender = ?";
|
||||||
|
return jdbcClient.sql(sql)
|
||||||
|
.param(grade)
|
||||||
|
.param(state)
|
||||||
|
.param(gender)
|
||||||
|
.query(new StudentRowMapper()).list();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Student> getStudentsOfGradeStateAndGenderWithParamIndex(int grade, String state, String gender) {
|
||||||
|
String sql = "select student_id, student_name, age, grade, gender, state from student"
|
||||||
|
+ " where grade = ? and state = ? and gender = ?";
|
||||||
|
return jdbcClient.sql(sql)
|
||||||
|
.param(1,grade)
|
||||||
|
.param(2, state)
|
||||||
|
.param(3, gender)
|
||||||
|
.query(new StudentResultExtractor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Student getStudentsOfGradeStateAndGenderWithParamsInVarargs(int grade, String state, String gender) {
|
||||||
|
String sql = "select student_id, student_name, age, grade, gender, state from student"
|
||||||
|
+ " where grade = ? and state = ? and gender = ? limit 1";
|
||||||
|
return jdbcClient.sql(sql)
|
||||||
|
.params(grade, state, gender)
|
||||||
|
.query(new StudentRowMapper()).single();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Student> getStudentsOfGradeStateAndGenderWithParamsInList(List params) {
|
||||||
|
String sql = "select student_id, student_name, age, grade, gender, state from student"
|
||||||
|
+ " where grade = ? and state = ? and gender = ? limit 1";
|
||||||
|
return jdbcClient.sql(sql)
|
||||||
|
.params(params)
|
||||||
|
.query(new StudentRowMapper()).optional();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public int getCountOfStudentsOfGradeStateAndGenderWithNamedParam(int grade, String state, String gender) {
|
||||||
|
String sql = "select student_id, student_name, age, grade, gender, state from student"
|
||||||
|
+ " where grade = :grade and state = :state and gender = :gender";
|
||||||
|
RowCountCallbackHandler countCallbackHandler = new RowCountCallbackHandler();
|
||||||
|
jdbcClient.sql(sql)
|
||||||
|
.param("grade", grade)
|
||||||
|
.param("state", state)
|
||||||
|
.param("gender", gender)
|
||||||
|
.query(countCallbackHandler);
|
||||||
|
return countCallbackHandler.getRowCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Student> getStudentsOfGradeStateAndGenderWithParamMap(Map<String, ?> paramMap) {
|
||||||
|
String sql = "select student_id, student_name, age, grade, gender, state from student"
|
||||||
|
+ " where grade = :grade and state = :state and gender = :gender";
|
||||||
|
return jdbcClient.sql(sql)
|
||||||
|
.params(paramMap)
|
||||||
|
.query(new StudentRowMapper()).list();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.baeldung.jdbcclient.model;
|
||||||
|
|
||||||
|
public class Student {
|
||||||
|
private Integer studentId;
|
||||||
|
private String studentName;
|
||||||
|
private String studentGender;
|
||||||
|
private Integer age;
|
||||||
|
private Integer grade;
|
||||||
|
|
||||||
|
public Integer getStudentId() {
|
||||||
|
return studentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStudentId(Integer studentId) {
|
||||||
|
this.studentId = studentId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStudentName() {
|
||||||
|
return studentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStudentName(String studentName) {
|
||||||
|
this.studentName = studentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStudentGender() {
|
||||||
|
return studentGender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStudentGender(String studentGender) {
|
||||||
|
this.studentGender = studentGender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAge() {
|
||||||
|
return age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAge(Integer age) {
|
||||||
|
this.age = age;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getGrade() {
|
||||||
|
return grade;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGrade(Integer grade) {
|
||||||
|
this.grade = grade;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(String state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String state;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.baeldung.jdbcclient.model;
|
||||||
|
|
||||||
|
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class StudentResultExtractor implements ResultSetExtractor<List<Student>> {
|
||||||
|
@Override
|
||||||
|
public List<Student> extractData(ResultSet rs) throws SQLException {
|
||||||
|
List<Student> students = new ArrayList<Student>();
|
||||||
|
while(rs.next()) {
|
||||||
|
Student student = new Student();
|
||||||
|
student.setStudentId(rs.getInt("student_id"));
|
||||||
|
student.setStudentName(rs.getString("student_name"));
|
||||||
|
student.setAge(rs.getInt("age"));
|
||||||
|
student.setStudentGender(rs.getString("gender"));
|
||||||
|
student.setGrade(rs.getInt("grade"));
|
||||||
|
student.setState(rs.getString("state"));
|
||||||
|
students.add(student);
|
||||||
|
}
|
||||||
|
return students;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.baeldung.jdbcclient.model;
|
||||||
|
|
||||||
|
import org.springframework.jdbc.core.RowMapper;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
public class StudentRowMapper implements RowMapper<Student> {
|
||||||
|
@Override
|
||||||
|
public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
|
||||||
|
Student student = new Student();
|
||||||
|
student.setStudentId(rs.getInt("student_id"));
|
||||||
|
student.setStudentName(rs.getString("student_name"));
|
||||||
|
student.setAge(rs.getInt("age"));
|
||||||
|
student.setStudentGender(rs.getString("gender"));
|
||||||
|
student.setGrade(rs.getInt("grade"));
|
||||||
|
student.setState(rs.getString("state"));
|
||||||
|
return student;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
# DataSource Configuration
|
||||||
|
spring.datasource.url=jdbc:h2:mem:testdb
|
||||||
|
spring.datasource.driverClassName=org.h2.Driver
|
||||||
|
spring.datasource.username=user
|
||||||
|
spring.datasource.password= # Leave this empty
|
|
@ -0,0 +1 @@
|
||||||
|
DROP TABLE student;
|
|
@ -0,0 +1,98 @@
|
||||||
|
|
||||||
|
CREATE TABLE student (
|
||||||
|
student_id INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
student_name VARCHAR(255) NOT NULL,
|
||||||
|
age INT,
|
||||||
|
grade INT NOT NULL,
|
||||||
|
gender VARCHAR(10) NOT NULL,
|
||||||
|
state VARCHAR(100) NOT NULL
|
||||||
|
);
|
||||||
|
-- Student 1
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('John Smith', 18, 3, 'Male', 'California');
|
||||||
|
|
||||||
|
-- Student 2
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Emily Johnson', 17, 2, 'Female', 'New York');
|
||||||
|
|
||||||
|
-- Student 3
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Michael Davis', 4, 1, 'Male', 'Texas');
|
||||||
|
|
||||||
|
-- Student 4
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Sophia Martinez', 2, 1, 'Female', 'Florida');
|
||||||
|
|
||||||
|
-- Student 5
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('William Brown', 5, 5, 'Male', 'California');
|
||||||
|
|
||||||
|
-- Student 6
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Olivia Garcia', 4, 2, 'Female', 'Texas');
|
||||||
|
|
||||||
|
-- Student 7
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Ethan Rodriguez', 3, 1, 'Male', 'New York');
|
||||||
|
|
||||||
|
-- Student 8
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Ava Hernandez', 2, 1, 'Female', 'Florida');
|
||||||
|
|
||||||
|
-- Student 9
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('James Wilson', 5, 4, 'Male', 'Texas');
|
||||||
|
|
||||||
|
-- Student 10
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Emma Miller', 3, 1, 'Female', 'California');
|
||||||
|
|
||||||
|
-- Student 11
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Benjamin Brown', 4, 1, 'Male', 'New York');
|
||||||
|
|
||||||
|
-- Student 12
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Mia Smith', 2, 1, 'Female', 'Florida');
|
||||||
|
|
||||||
|
-- Student 13
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Daniel Johnson', 5, 4, 'Male', 'California');
|
||||||
|
|
||||||
|
-- Student 14
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Ava Davis', 4, 2, 'Female', 'Texas');
|
||||||
|
|
||||||
|
-- Student 15
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Matthew Martinez', 3, 1, 'Male', 'New York');
|
||||||
|
|
||||||
|
-- Student 16
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Sophia Taylor', 2, 1, 'Female', 'Florida');
|
||||||
|
|
||||||
|
-- Student 17
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Alexander White', 5, 4, 'Male', 'California');
|
||||||
|
|
||||||
|
-- Student 18
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Olivia Johnson', 4, 2, 'Female', 'Texas');
|
||||||
|
|
||||||
|
-- Student 19
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Christopher Lee', 3, 1, 'Male', 'New York');
|
||||||
|
|
||||||
|
-- Student 20
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Emma Wilson', 2, 1, 'Female', 'Florida');
|
||||||
|
|
||||||
|
-- Student 21
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Elijah Smith', 5, 3, 'Male', 'Texas');
|
||||||
|
|
||||||
|
-- Student 22
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Isabella Davis', 4, 2, 'Female', 'California');
|
||||||
|
|
||||||
|
-- Student 23
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Liam Johnson', 3, 1, 'Male', 'New York');
|
||||||
|
|
||||||
|
-- Student 24
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Olivia Garcia', 2, 1, 'Female', 'Florida');
|
||||||
|
|
||||||
|
-- Student 25
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Noah Rodriguez', 5, 3, 'Male', 'Texas');
|
||||||
|
|
||||||
|
-- Student 26
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Sophia Hernandez', 4, 2, 'Female', 'California');
|
||||||
|
|
||||||
|
-- Student 27
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Mason Smith', 3, 1, 'Male', 'New York');
|
||||||
|
|
||||||
|
-- Student 28
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Ava Taylor', 2, 1, 'Female', 'Florida');
|
||||||
|
|
||||||
|
-- Student 29
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('William Brown', 5, 5, 'Male', 'Texas');
|
||||||
|
|
||||||
|
-- Student 30
|
||||||
|
INSERT INTO student (student_name, age, grade, gender, state) VALUES ('Olivia Martinez', 4, 4, 'Female', 'California');
|
|
@ -0,0 +1,104 @@
|
||||||
|
package com.baeldung.jdbcclient;
|
||||||
|
|
||||||
|
import com.baeldung.jdbcclient.dao.StudentDao;
|
||||||
|
import com.baeldung.jdbcclient.model.Student;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.TestPropertySource;
|
||||||
|
import org.springframework.test.context.jdbc.Sql;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
@Sql(value = "/jdbcclient/student.sql", executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
|
||||||
|
@Sql(value = "/jdbcclient/drop_student.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
|
||||||
|
@SpringBootTest(classes = JdbcClientDemoApplication.class)
|
||||||
|
@TestPropertySource(locations = {"classpath:jdbcclient/application.properties"})
|
||||||
|
|
||||||
|
public class JdbcClientUnitTest {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(JdbcClientUnitTest.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private StudentDao studentDao;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenJdbcClient_whenInsertWithNamedParamAndSqlType_thenSuccess() {
|
||||||
|
logger.info("testing invoked successfully");
|
||||||
|
Student student = getSampleStudent("Johny Dep", 8, 4, "Male", "New York");
|
||||||
|
assertEquals(1, studentDao.insertWithSetParamWithNamedParamAndSqlType(student));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenJdbcClient_whenQueryWithPositionalParams_thenSuccess() {
|
||||||
|
logger.info("testing invoked successfully");
|
||||||
|
List<Student> students = studentDao.getStudentsOfGradeStateAndGenderWithPositionalParams(
|
||||||
|
1, "New York", "Male");
|
||||||
|
logger.info("number of students fetched " + students.size());
|
||||||
|
assertEquals(6, students.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenJdbcClient_whenQueryWithParamsInVarargs_thenSuccess() {
|
||||||
|
logger.info("testing invoked successfully");
|
||||||
|
Student student = studentDao.getStudentsOfGradeStateAndGenderWithParamsInVarargs(
|
||||||
|
1, "New York", "Male");
|
||||||
|
assertNotNull(student);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenJdbcClient_whenQueryWithParamsInList_thenSuccess() {
|
||||||
|
logger.info("testing invoked successfully");
|
||||||
|
List params = List.of(1, "New York", "Male");
|
||||||
|
Optional<Student> optional = studentDao.getStudentsOfGradeStateAndGenderWithParamsInList(params);
|
||||||
|
if(optional.isPresent()) {
|
||||||
|
assertNotNull(optional.get());
|
||||||
|
} else {
|
||||||
|
assertThrows(NoSuchElementException.class, () -> optional.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenJdbcClient_whenQueryWithParamsIndex_thenSuccess() {
|
||||||
|
logger.info("testing invoked successfully");
|
||||||
|
List<Student> students = studentDao.getStudentsOfGradeStateAndGenderWithParamIndex(
|
||||||
|
1, "New York", "Male");
|
||||||
|
assertEquals(6, students.size());
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
void givenJdbcClient_whenQueryWithNamedParam_thenSuccess() {
|
||||||
|
logger.info("testing invoked successfully");
|
||||||
|
Integer count = studentDao.getCountOfStudentsOfGradeStateAndGenderWithNamedParam(
|
||||||
|
1, "New York", "Male");
|
||||||
|
logger.info("number of students fetched " + count);
|
||||||
|
assertEquals(6, count);
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
void givenJdbcClient_whenQueryWithParamMap_thenSuccess() {
|
||||||
|
logger.info("testing invoked successfully");
|
||||||
|
Map<String, ?> paramMap = Map.of(
|
||||||
|
"grade", 1,
|
||||||
|
"gender", "Male",
|
||||||
|
"state", "New York"
|
||||||
|
);
|
||||||
|
List<Student> students = studentDao.getStudentsOfGradeStateAndGenderWithParamMap(paramMap);
|
||||||
|
logger.info("number of students fetched " + students.size());
|
||||||
|
assertEquals(6, students.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Student getSampleStudent(String name, int age, int grade, String gender, String state) {
|
||||||
|
Student student = new Student();
|
||||||
|
student.setStudentName(name);
|
||||||
|
student.setStudentGender(gender);
|
||||||
|
student.setAge(age);
|
||||||
|
student.setGrade(grade);
|
||||||
|
student.setState(state);
|
||||||
|
return student;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration scan="true" scanPeriod="15 seconds" debug="false">
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>[%d{ISO8601}]-[%thread] %-5level %logger - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="STDOUT" />
|
||||||
|
</root>
|
||||||
|
</configuration>
|
7
pom.xml
|
@ -349,7 +349,6 @@
|
||||||
|
|
||||||
<!-- <module>ethereum</module> --> <!-- JAVA-6001 -->
|
<!-- <module>ethereum</module> --> <!-- JAVA-6001 -->
|
||||||
<!-- <module>gradle-modules</module> --> <!-- Not a maven project -->
|
<!-- <module>gradle-modules</module> --> <!-- Not a maven project -->
|
||||||
<!-- <module>grails</module> --> <!-- Not a maven project -->
|
|
||||||
<!-- <module>guest</module> --> <!-- not to be built as its for guest articles -->
|
<!-- <module>guest</module> --> <!-- not to be built as its for guest articles -->
|
||||||
|
|
||||||
<!-- <module>lagom</module> --> <!-- Not a maven project -->
|
<!-- <module>lagom</module> --> <!-- Not a maven project -->
|
||||||
|
@ -362,7 +361,7 @@
|
||||||
<module>muleesb</module>
|
<module>muleesb</module>
|
||||||
<module>web-modules/java-lite</module>
|
<module>web-modules/java-lite</module>
|
||||||
<module>persistence-modules/deltaspike</module> <!-- delta spike it doesn't support yet the jakarta API-->
|
<module>persistence-modules/deltaspike</module> <!-- delta spike it doesn't support yet the jakarta API-->
|
||||||
<module>persistence-modules/hibernate-ogm</module> <!-- hibernate-ogm wasn't updated because it doesn't support jakarta API -->
|
<module>persistence-modules/hibernate-ogm</module> <!-- hibernate-ogm wasn't updated because a workaround for jakarta namespace wasn't found JAVA-20557 -->
|
||||||
<module>persistence-modules/spring-data-cassandra-reactive</module> <!--JAVA-21844-->
|
<module>persistence-modules/spring-data-cassandra-reactive</module> <!--JAVA-21844-->
|
||||||
<module>java-nashorn</module>
|
<module>java-nashorn</module>
|
||||||
<module>jeromq</module>
|
<module>jeromq</module>
|
||||||
|
@ -523,7 +522,6 @@
|
||||||
|
|
||||||
<!-- <module>ethereum</module> --> <!-- JAVA-6001 -->
|
<!-- <module>ethereum</module> --> <!-- JAVA-6001 -->
|
||||||
<!-- <module>gradle-modules</module> --> <!-- Not a maven project -->
|
<!-- <module>gradle-modules</module> --> <!-- Not a maven project -->
|
||||||
<!-- <module>grails</module> --> <!-- Not a maven project -->
|
|
||||||
<!-- <module>guest</module> --> <!-- not to be built as its for guest articles -->
|
<!-- <module>guest</module> --> <!-- not to be built as its for guest articles -->
|
||||||
|
|
||||||
<!-- <module>lagom</module> --> <!-- Not a maven project -->
|
<!-- <module>lagom</module> --> <!-- Not a maven project -->
|
||||||
|
@ -534,7 +532,7 @@
|
||||||
<module>muleesb</module>
|
<module>muleesb</module>
|
||||||
<module>web-modules/java-lite</module>
|
<module>web-modules/java-lite</module>
|
||||||
<module>persistence-modules/deltaspike</module> <!-- delta spike it doesn't support yet the jakarta API-->
|
<module>persistence-modules/deltaspike</module> <!-- delta spike it doesn't support yet the jakarta API-->
|
||||||
<module>persistence-modules/hibernate-ogm</module> <!-- hibernate-ogm wasn't updated because it doesn't support jakarta API -->
|
<module>persistence-modules/hibernate-ogm</module> <!-- hibernate-ogm wasn't updated because a workaround for jakarta namespace wasn't found JAVA-20557 -->
|
||||||
<module>persistence-modules/spring-data-cassandra-reactive</module> <!--JAVA-21844-->
|
<module>persistence-modules/spring-data-cassandra-reactive</module> <!--JAVA-21844-->
|
||||||
<module>java-nashorn</module>
|
<module>java-nashorn</module>
|
||||||
<module>jeromq</module>
|
<module>jeromq</module>
|
||||||
|
@ -1211,7 +1209,6 @@
|
||||||
<module>gradle-modules/gradle/maven-to-gradle</module>
|
<module>gradle-modules/gradle/maven-to-gradle</module>
|
||||||
<module>persistence-modules/spring-data-neo4j</module>
|
<module>persistence-modules/spring-data-neo4j</module>
|
||||||
<module>spring-actuator</module>
|
<module>spring-actuator</module>
|
||||||
<module>gcp-firebase</module>
|
|
||||||
<module>spring-di-4</module>
|
<module>spring-di-4</module>
|
||||||
<module>spring-kafka-2</module>
|
<module>spring-kafka-2</module>
|
||||||
<!--<module>java-panama</module> Java-19 module-->
|
<!--<module>java-panama</module> Java-19 module-->
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
## Relevant Articles
|
||||||
|
- [Spring Boot 3.1’s ConnectionDetails Abstraction](https://www.baeldung.com/spring-boot-3-1-connectiondetails-abstraction)
|
|
@ -8,3 +8,4 @@
|
||||||
- [HTTP Interface in Spring 6](https://www.baeldung.com/spring-6-http-interface)
|
- [HTTP Interface in Spring 6](https://www.baeldung.com/spring-6-http-interface)
|
||||||
- [Working with Virtual Threads in Spring 6](https://www.baeldung.com/spring-6-virtual-threads)
|
- [Working with Virtual Threads in Spring 6](https://www.baeldung.com/spring-6-virtual-threads)
|
||||||
- [Docker Compose Support in Spring Boot 3](https://www.baeldung.com/ops/docker-compose-support-spring-boot)
|
- [Docker Compose Support in Spring Boot 3](https://www.baeldung.com/ops/docker-compose-support-spring-boot)
|
||||||
|
- [A Guide to RestClient in Spring Boot](https://www.baeldung.com/spring-boot-restclient)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
|
|
||||||
- [HttpMessageNotWritableException: No Converter for [class …] With Preset Content-Type](https://www.baeldung.com/spring-no-converter-with-preset)
|
- [HttpMessageNotWritableException: No Converter for [class …] With Preset Content-Type](https://www.baeldung.com/spring-no-converter-with-preset)
|
||||||
- [Spring Boot: Customize the Jackson ObjectMapper](https://www.baeldung.com/spring-boot-customize-jackson-objectmapper)
|
|
||||||
- [“HttpMessageNotWritableException: No converter found for return value of type”](https://www.baeldung.com/spring-no-converter-found)
|
- [“HttpMessageNotWritableException: No converter found for return value of type”](https://www.baeldung.com/spring-no-converter-found)
|
||||||
- [Creating a Read-Only Repository with Spring Data](https://www.baeldung.com/spring-data-read-only-repository)
|
- [Creating a Read-Only Repository with Spring Data](https://www.baeldung.com/spring-data-read-only-repository)
|
||||||
- [Using JaVers for Data Model Auditing in Spring Data](https://www.baeldung.com/spring-data-javers-audit)
|
- [Using JaVers for Data Model Auditing in Spring Data](https://www.baeldung.com/spring-data-javers-audit)
|
||||||
|
|
|
@ -11,4 +11,5 @@ This module contains articles about Spring Boot with Spring Data
|
||||||
- [Spring Custom Property Editor](https://www.baeldung.com/spring-mvc-custom-property-editor)
|
- [Spring Custom Property Editor](https://www.baeldung.com/spring-mvc-custom-property-editor)
|
||||||
- [Using @JsonComponent in Spring Boot](https://www.baeldung.com/spring-boot-jsoncomponent)
|
- [Using @JsonComponent in Spring Boot](https://www.baeldung.com/spring-boot-jsoncomponent)
|
||||||
- [Guide To Running Logic on Startup in Spring](https://www.baeldung.com/running-setup-logic-on-startup-in-spring)
|
- [Guide To Running Logic on Startup in Spring](https://www.baeldung.com/running-setup-logic-on-startup-in-spring)
|
||||||
|
- [Spring Boot: Customize the Jackson ObjectMapper](https://www.baeldung.com/spring-boot-customize-jackson-objectmapper)
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
package com.baeldung.boot.jackson.config;
|
package com.baeldung.boot.jackson.config;
|
||||||
|
|
||||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
||||||
|
|
||||||
public class CoffeeConstants {
|
public class CoffeeConstants {
|
||||||
|
|
||||||
public static final String DATETIME_FORMAT = "dd-MM-yyyy HH:mm";
|
public static final String DATETIME_FORMAT = "dd-MM-yyyy HH:mm";
|
|
@ -1,11 +1,12 @@
|
||||||
package com.baeldung.boot.jackson.config;
|
package com.baeldung.boot.jackson.config;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
|
||||||
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 static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class CoffeeCustomizerConfig {
|
public class CoffeeCustomizerConfig {
|
|
@ -1,12 +1,13 @@
|
||||||
package com.baeldung.boot.jackson.config;
|
package com.baeldung.boot.jackson.config;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
|
||||||
|
|
||||||
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.http.converter.json.Jackson2ObjectMapperBuilder;
|
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||||
|
|
||||||
import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class CoffeeHttpConverterConfiguration {
|
public class CoffeeHttpConverterConfiguration {
|
|
@ -1,12 +1,13 @@
|
||||||
package com.baeldung.boot.jackson.config;
|
package com.baeldung.boot.jackson.config;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
|
||||||
|
|
||||||
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.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||||
|
|
||||||
import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class CoffeeJacksonBuilderConfig {
|
public class CoffeeJacksonBuilderConfig {
|
|
@ -1,13 +1,14 @@
|
||||||
package com.baeldung.boot.jackson.config;
|
package com.baeldung.boot.jackson.config;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
|
||||||
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.context.annotation.Primary;
|
import org.springframework.context.annotation.Primary;
|
||||||
|
|
||||||
import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class CoffeeObjectMapperConfig {
|
public class CoffeeObjectMapperConfig {
|
|
@ -1,19 +1,19 @@
|
||||||
package com.baeldung.boot.jackson.config;
|
package com.baeldung.boot.jackson.config;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.Module;
|
import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
|
||||||
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.context.annotation.PropertySource;
|
import org.springframework.context.annotation.PropertySource;
|
||||||
|
|
||||||
import static com.baeldung.boot.jackson.config.CoffeeConstants.LOCAL_DATETIME_SERIALIZER;
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@PropertySource("classpath:coffee.properties")
|
@PropertySource("classpath:coffee.properties")
|
||||||
public class CoffeeRegisterModuleConfig {
|
public class CoffeeRegisterModuleConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public Module javaTimeModule() {
|
public JavaTimeModule javaTimeModule() {
|
||||||
JavaTimeModule module = new JavaTimeModule();
|
JavaTimeModule module = new JavaTimeModule();
|
||||||
module.addSerializer(LOCAL_DATETIME_SERIALIZER);
|
module.addSerializer(LOCAL_DATETIME_SERIALIZER);
|
||||||
return module;
|
return module;
|
|
@ -1,11 +1,12 @@
|
||||||
package com.baeldung.boot.jackson.controller;
|
package com.baeldung.boot.jackson.controller;
|
||||||
|
|
||||||
import com.baeldung.boot.jackson.model.Coffee;
|
import static com.baeldung.boot.jackson.config.CoffeeConstants.FIXED_DATE;
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import static com.baeldung.boot.jackson.config.CoffeeConstants.FIXED_DATE;
|
import com.baeldung.boot.jackson.model.Coffee;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
public class CoffeeController {
|
public class CoffeeController {
|
|
@ -1,15 +1,16 @@
|
||||||
package com.baeldung.boot.jackson.app;
|
package com.baeldung.boot.jackson.app;
|
||||||
|
|
||||||
import com.baeldung.boot.jackson.config.CoffeeConstants;
|
import static com.baeldung.boot.jackson.config.CoffeeConstants.FIXED_DATE;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
|
||||||
import java.time.format.DateTimeFormatter;
|
import com.baeldung.boot.jackson.config.CoffeeConstants;
|
||||||
|
|
||||||
import static com.baeldung.boot.jackson.config.CoffeeConstants.FIXED_DATE;
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
|
||||||
|
|
||||||
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||||
public abstract class AbstractCoffeeIntegrationTest {
|
public abstract class AbstractCoffeeIntegrationTest {
|
|
@ -1,8 +1,9 @@
|
||||||
package com.baeldung.boot.jackson.app;
|
package com.baeldung.boot.jackson.app;
|
||||||
|
|
||||||
import com.baeldung.boot.jackson.config.CoffeeCustomizerConfig;
|
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
|
import com.baeldung.boot.jackson.config.CoffeeCustomizerConfig;
|
||||||
|
|
||||||
@Import(CoffeeCustomizerConfig.class)
|
@Import(CoffeeCustomizerConfig.class)
|
||||||
public class CoffeeCustomizerIntegrationTest extends AbstractCoffeeIntegrationTest {
|
public class CoffeeCustomizerIntegrationTest extends AbstractCoffeeIntegrationTest {
|
||||||
}
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
package com.baeldung.boot.jackson.app;
|
package com.baeldung.boot.jackson.app;
|
||||||
|
|
||||||
import com.baeldung.boot.jackson.config.CoffeeHttpConverterConfiguration;
|
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
|
import com.baeldung.boot.jackson.config.CoffeeHttpConverterConfiguration;
|
||||||
|
|
||||||
@Import(CoffeeHttpConverterConfiguration.class)
|
@Import(CoffeeHttpConverterConfiguration.class)
|
||||||
public class CoffeeHttpConverterIntegrationTest extends AbstractCoffeeIntegrationTest {
|
public class CoffeeHttpConverterIntegrationTest extends AbstractCoffeeIntegrationTest {
|
||||||
}
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
package com.baeldung.boot.jackson.app;
|
package com.baeldung.boot.jackson.app;
|
||||||
|
|
||||||
import com.baeldung.boot.jackson.config.CoffeeJacksonBuilderConfig;
|
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
|
import com.baeldung.boot.jackson.config.CoffeeJacksonBuilderConfig;
|
||||||
|
|
||||||
@Import(CoffeeJacksonBuilderConfig.class)
|
@Import(CoffeeJacksonBuilderConfig.class)
|
||||||
public class CoffeeJacksonBuilderIntegrationTest extends AbstractCoffeeIntegrationTest {
|
public class CoffeeJacksonBuilderIntegrationTest extends AbstractCoffeeIntegrationTest {
|
||||||
}
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
package com.baeldung.boot.jackson.app;
|
package com.baeldung.boot.jackson.app;
|
||||||
|
|
||||||
import com.baeldung.boot.jackson.config.CoffeeObjectMapperConfig;
|
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
|
import com.baeldung.boot.jackson.config.CoffeeObjectMapperConfig;
|
||||||
|
|
||||||
@Import(CoffeeObjectMapperConfig.class)
|
@Import(CoffeeObjectMapperConfig.class)
|
||||||
public class CoffeeObjectMapperIntegrationTest extends AbstractCoffeeIntegrationTest {
|
public class CoffeeObjectMapperIntegrationTest extends AbstractCoffeeIntegrationTest {
|
||||||
}
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
package com.baeldung.boot.jackson.app;
|
package com.baeldung.boot.jackson.app;
|
||||||
|
|
||||||
import com.baeldung.boot.jackson.config.CoffeeRegisterModuleConfig;
|
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
|
import com.baeldung.boot.jackson.config.CoffeeRegisterModuleConfig;
|
||||||
|
|
||||||
@Import(CoffeeRegisterModuleConfig.class)
|
@Import(CoffeeRegisterModuleConfig.class)
|
||||||
public class CoffeeRegisterModuleIntegrationTest extends AbstractCoffeeIntegrationTest {
|
public class CoffeeRegisterModuleIntegrationTest extends AbstractCoffeeIntegrationTest {
|
||||||
}
|
}
|
|
@ -1,5 +1,10 @@
|
||||||
package com.baeldung.spring.cloud.springcloudcontractconsumer.controller;
|
package com.baeldung.spring.cloud.springcloudcontractconsumer.controller;
|
||||||
|
|
||||||
|
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||||
|
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
@ -13,6 +18,7 @@ import org.springframework.test.context.junit4.SpringRunner;
|
||||||
import org.springframework.test.web.servlet.MockMvc;
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||||
|
|
||||||
|
import static com.github.tomakehurst.wiremock.client.WireMock.*;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
@ -26,6 +32,36 @@ public class BasicMathControllerIntegrationTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private MockMvc mockMvc;
|
private MockMvc mockMvc;
|
||||||
|
private static WireMockServer wireMockServer;
|
||||||
|
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setupClass() {
|
||||||
|
WireMockConfiguration wireMockConfiguration = WireMockConfiguration.options().port(8090); // Use the same port as in your code
|
||||||
|
|
||||||
|
wireMockServer = new WireMockServer(wireMockConfiguration);
|
||||||
|
wireMockServer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void teardownClass() {
|
||||||
|
wireMockServer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
wireMockServer.stubFor(get(urlEqualTo("/validate/prime-number?number=1"))
|
||||||
|
.willReturn(aResponse()
|
||||||
|
.withStatus(200)
|
||||||
|
.withHeader("Content-Type", "application/json")
|
||||||
|
.withBody("Odd")));
|
||||||
|
|
||||||
|
wireMockServer.stubFor(get(urlEqualTo("/validate/prime-number?number=2"))
|
||||||
|
.willReturn(aResponse()
|
||||||
|
.withStatus(200)
|
||||||
|
.withHeader("Content-Type", "application/json")
|
||||||
|
.withBody("Even")));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void given_WhenPassEvenNumberInQueryParam_ThenReturnEven() throws Exception {
|
public void given_WhenPassEvenNumberInQueryParam_ThenReturnEven() throws Exception {
|
||||||
|
|
|
@ -8,7 +8,8 @@ This module contains articles about core Spring Security
|
||||||
- [Prevent Cross-Site Scripting (XSS) in a Spring Application](https://www.baeldung.com/spring-prevent-xss)
|
- [Prevent Cross-Site Scripting (XSS) in a Spring Application](https://www.baeldung.com/spring-prevent-xss)
|
||||||
- [Guide to the AuthenticationManagerResolver in Spring Security](https://www.baeldung.com/spring-security-authenticationmanagerresolver)
|
- [Guide to the AuthenticationManagerResolver in Spring Security](https://www.baeldung.com/spring-security-authenticationmanagerresolver)
|
||||||
- [A Custom Spring SecurityConfigurer](https://www.baeldung.com/spring-security-custom-configurer)
|
- [A Custom Spring SecurityConfigurer](https://www.baeldung.com/spring-security-custom-configurer)
|
||||||
|
- [HttpSecurity vs. WebSecurity in Spring Security](https://www.baeldung.com/spring-security-httpsecurity-vs-websecurity)
|
||||||
|
|
||||||
### Build the Project
|
### Build the Project
|
||||||
|
|
||||||
`mvn clean install`
|
`mvn clean install`
|
||||||
|
|
|
@ -7,3 +7,4 @@
|
||||||
- [Gray Box Testing Using the OAT Technique](https://www.baeldung.com/java-gray-box-orthogonal-array-testing)
|
- [Gray Box Testing Using the OAT Technique](https://www.baeldung.com/java-gray-box-orthogonal-array-testing)
|
||||||
- [Unit Testing of System.in With JUnit](https://www.baeldung.com/java-junit-testing-system-in)
|
- [Unit Testing of System.in With JUnit](https://www.baeldung.com/java-junit-testing-system-in)
|
||||||
- [Fail Maven Build if JUnit Coverage Falls Below Certain Threshold](https://www.baeldung.com/maven-junit-fail-build-coverage-threshold)
|
- [Fail Maven Build if JUnit Coverage Falls Below Certain Threshold](https://www.baeldung.com/maven-junit-fail-build-coverage-threshold)
|
||||||
|
- [How to Mock Environment Variables in Unit Tests](https://www.baeldung.com/java-unit-testing-environment-variables)
|
||||||
|
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 6.8 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 658 B After Width: | Height: | Size: 658 B |
Before Width: | Height: | Size: 659 B After Width: | Height: | Size: 659 B |
Before Width: | Height: | Size: 767 B After Width: | Height: | Size: 767 B |
Before Width: | Height: | Size: 755 B After Width: | Height: | Size: 755 B |
Before Width: | Height: | Size: 726 B After Width: | Height: | Size: 726 B |
Before Width: | Height: | Size: 701 B After Width: | Height: | Size: 701 B |
Before Width: | Height: | Size: 806 B After Width: | Height: | Size: 806 B |
Before Width: | Height: | Size: 778 B After Width: | Height: | Size: 778 B |
Before Width: | Height: | Size: 300 B After Width: | Height: | Size: 300 B |
Before Width: | Height: | Size: 835 B After Width: | Height: | Size: 835 B |
Before Width: | Height: | Size: 834 B After Width: | Height: | Size: 834 B |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |