Merge branch 'master' of https://github.com/eugenp/tutorials into task/BAEL-9709
This commit is contained in:
commit
bbc4cdd3f7
@ -7,7 +7,7 @@ public class BubbleSort {
|
||||
void bubbleSort(Integer[] arr) {
|
||||
int n = arr.length;
|
||||
IntStream.range(0, n - 1)
|
||||
.flatMap(i -> IntStream.range(i + 1, n - i))
|
||||
.flatMap(i -> IntStream.range(1, n - i))
|
||||
.forEach(j -> {
|
||||
if (arr[j - 1] > arr[j]) {
|
||||
int temp = arr[j];
|
||||
|
@ -1,8 +1,8 @@
|
||||
package com.baeldung.algorithms.bubblesort;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class BubbleSortUnitTest {
|
||||
|
||||
|
@ -1,13 +1,20 @@
|
||||
package com.baeldung.java8;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class Java8ForEachUnitTest {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Java8ForEachUnitTest.class);
|
||||
@ -29,8 +36,18 @@ public class Java8ForEachUnitTest {
|
||||
}
|
||||
|
||||
// Java 8 - forEach
|
||||
LOG.debug("--- forEach method ---");
|
||||
names.forEach(name -> LOG.debug(name));
|
||||
names.forEach(name -> {
|
||||
System.out.println(name);
|
||||
});
|
||||
|
||||
LOG.debug("--- Print Consumer ---");
|
||||
Consumer<String> printConsumer = new Consumer<String>() {
|
||||
public void accept(String name) {
|
||||
System.out.println(name);
|
||||
};
|
||||
};
|
||||
|
||||
names.forEach(printConsumer);
|
||||
|
||||
// Anonymous inner class that implements Consumer interface
|
||||
LOG.debug("--- Anonymous inner class ---");
|
||||
@ -40,17 +57,55 @@ public class Java8ForEachUnitTest {
|
||||
}
|
||||
});
|
||||
|
||||
// Create a Consumer implementation to then use in a forEach method
|
||||
Consumer<String> consumerNames = name -> {
|
||||
LOG.debug(name);
|
||||
};
|
||||
LOG.debug("--- Implementation of Consumer interface ---");
|
||||
names.forEach(consumerNames);
|
||||
// Java 8 - forEach - Lambda Syntax
|
||||
LOG.debug("--- forEach method ---");
|
||||
names.forEach(name -> LOG.debug(name));
|
||||
|
||||
// Print elements using a Method Reference
|
||||
// Java 8 - forEach - Print elements using a Method Reference
|
||||
LOG.debug("--- Method Reference ---");
|
||||
names.forEach(LOG::debug);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenList_thenIterateAndPrintResults() {
|
||||
List<String> names = Arrays.asList("Larry", "Steve", "James");
|
||||
|
||||
names.forEach(System.out::println);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenSet_thenIterateAndPrintResults() {
|
||||
Set<String> uniqueNames = new HashSet<>(Arrays.asList("Larry", "Steve", "James"));
|
||||
|
||||
uniqueNames.forEach(System.out::println);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenQueue_thenIterateAndPrintResults() {
|
||||
Queue<String> namesQueue = new ArrayDeque<>(Arrays.asList("Larry", "Steve", "James"));
|
||||
|
||||
namesQueue.forEach(System.out::println);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMap_thenIterateAndPrintResults() {
|
||||
Map<Integer, String> namesMap = new HashMap<>();
|
||||
namesMap.put(1, "Larry");
|
||||
namesMap.put(2, "Steve");
|
||||
namesMap.put(3, "James");
|
||||
|
||||
namesMap.entrySet()
|
||||
.forEach(entry -> System.out.println(entry.getKey() + " " + entry.getValue()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenMap_whenUsingBiConsumer_thenIterateAndPrintResults2() {
|
||||
Map<Integer, String> namesMap = new HashMap<>();
|
||||
namesMap.put(1, "Larry");
|
||||
namesMap.put(2, "Steve");
|
||||
namesMap.put(3, "James");
|
||||
|
||||
namesMap.forEach((key, value) -> System.out.println(key + " " + value));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -154,6 +154,12 @@
|
||||
<artifactId>async-http-client</artifactId>
|
||||
<version>${async-http-client.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.opencsv</groupId>
|
||||
<artifactId>opencsv</artifactId>
|
||||
<version>${opencsv.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@ -247,7 +253,7 @@
|
||||
<protonpack.version>1.13</protonpack.version>
|
||||
<streamex.version>0.6.5</streamex.version>
|
||||
<vavr.version>0.9.0</vavr.version>
|
||||
|
||||
<opencsv.version>4.1</opencsv.version>
|
||||
<!-- testing -->
|
||||
<assertj.version>3.6.1</assertj.version>
|
||||
<avaitility.version>1.7.0</avaitility.version>
|
||||
|
@ -9,13 +9,13 @@ import java.util.zip.ZipInputStream;
|
||||
|
||||
public class UnzipFile {
|
||||
public static void main(final String[] args) throws IOException {
|
||||
final String fileZip = "src/main/resources/compressed.zip";
|
||||
final String fileZip = "src/main/resources/unzipTest/compressed.zip";
|
||||
final File destDir = new File("src/main/resources/unzipTest");
|
||||
final byte[] buffer = new byte[1024];
|
||||
final ZipInputStream zis = new ZipInputStream(new FileInputStream(fileZip));
|
||||
ZipEntry zipEntry = zis.getNextEntry();
|
||||
while (zipEntry != null) {
|
||||
final String fileName = zipEntry.getName();
|
||||
final File newFile = new File("src/main/resources/unzipTest/" + fileName);
|
||||
final File newFile = newFile(destDir, zipEntry);
|
||||
final FileOutputStream fos = new FileOutputStream(newFile);
|
||||
int len;
|
||||
while ((len = zis.read(buffer)) > 0) {
|
||||
@ -27,4 +27,20 @@ public class UnzipFile {
|
||||
zis.closeEntry();
|
||||
zis.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://snyk.io/research/zip-slip-vulnerability
|
||||
*/
|
||||
public static File newFile(File destinationDir, ZipEntry zipEntry) throws IOException {
|
||||
File destFile = new File(destinationDir, zipEntry.getName());
|
||||
|
||||
String destDirPath = destinationDir.getCanonicalPath();
|
||||
String destFilePath = destFile.getCanonicalPath();
|
||||
|
||||
if (!destFilePath.startsWith(destDirPath + File.separator)) {
|
||||
throw new IOException("Entry is outside of the target dir: " + zipEntry.getName());
|
||||
}
|
||||
|
||||
return destFile;
|
||||
}
|
||||
}
|
BIN
core-java-io/src/main/resources/unzipTest/compressed.zip
Normal file
BIN
core-java-io/src/main/resources/unzipTest/compressed.zip
Normal file
Binary file not shown.
@ -0,0 +1,106 @@
|
||||
package com.baeldung.csv;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.opencsv.CSVReader;
|
||||
|
||||
public class ReadCSVInArrayUnitTest {
|
||||
public static final String COMMA_DELIMITER = ",";
|
||||
public static final String CSV_FILE = "src/test/resources/book.csv";
|
||||
public static final List<List<String>> EXPECTED_ARRAY = Collections.unmodifiableList(new ArrayList<List<String>>() {
|
||||
{
|
||||
add(new ArrayList<String>() {
|
||||
{
|
||||
add("Mary Kom");
|
||||
add("Unbreakable");
|
||||
}
|
||||
});
|
||||
add(new ArrayList<String>() {
|
||||
{
|
||||
add("Kapil Isapuari");
|
||||
add("Farishta");
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@Test
|
||||
public void givenCSVFile_whenBufferedReader_thenContentsAsExpected() throws IOException {
|
||||
List<List<String>> records = new ArrayList<List<String>>();
|
||||
try (BufferedReader br = new BufferedReader(new FileReader(CSV_FILE))) {
|
||||
String line = "";
|
||||
while ((line = br.readLine()) != null) {
|
||||
String[] values = line.split(COMMA_DELIMITER);
|
||||
records.add(Arrays.asList(values));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
for (int i = 0; i < EXPECTED_ARRAY.size(); i++) {
|
||||
Assert.assertArrayEquals(EXPECTED_ARRAY.get(i)
|
||||
.toArray(),
|
||||
records.get(i)
|
||||
.toArray());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenCSVFile_whenScanner_thenContentsAsExpected() throws IOException {
|
||||
List<List<String>> records = new ArrayList<List<String>>();
|
||||
try (Scanner scanner = new Scanner(new File(CSV_FILE));) {
|
||||
while (scanner.hasNextLine()) {
|
||||
records.add(getRecordFromLine(scanner.nextLine()));
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
for (int i = 0; i < EXPECTED_ARRAY.size(); i++) {
|
||||
Assert.assertArrayEquals(EXPECTED_ARRAY.get(i)
|
||||
.toArray(),
|
||||
records.get(i)
|
||||
.toArray());
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> getRecordFromLine(String line) {
|
||||
List<String> values = new ArrayList<String>();
|
||||
try (Scanner rowScanner = new Scanner(line)) {
|
||||
rowScanner.useDelimiter(COMMA_DELIMITER);
|
||||
while (rowScanner.hasNext()) {
|
||||
values.add(rowScanner.next());
|
||||
}
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenCSVFile_whenOpencsv_thenContentsAsExpected() throws IOException {
|
||||
List<List<String>> records = new ArrayList<List<String>>();
|
||||
try (CSVReader csvReader = new CSVReader(new FileReader(CSV_FILE));) {
|
||||
String[] values = null;
|
||||
while ((values = csvReader.readNext()) != null) {
|
||||
records.add(Arrays.asList(values));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
for (int i = 0; i < EXPECTED_ARRAY.size(); i++) {
|
||||
Assert.assertArrayEquals(EXPECTED_ARRAY.get(i)
|
||||
.toArray(),
|
||||
records.get(i)
|
||||
.toArray());
|
||||
}
|
||||
}
|
||||
}
|
2
core-java-io/src/test/resources/book.csv
Normal file
2
core-java-io/src/test/resources/book.csv
Normal file
@ -0,0 +1,2 @@
|
||||
Mary Kom,Unbreakable
|
||||
Kapil Isapuari,Farishta
|
|
@ -0,0 +1,41 @@
|
||||
package com.baeldung.string;
|
||||
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
|
||||
public class DoubleToString {
|
||||
|
||||
public static String truncateByCast(double d) {
|
||||
return String.valueOf((int) d);
|
||||
}
|
||||
|
||||
public static String roundWithStringFormat(double d) {
|
||||
return String.format("%.0f", d);
|
||||
}
|
||||
|
||||
public static String truncateWithNumberFormat(double d) {
|
||||
NumberFormat nf = NumberFormat.getInstance();
|
||||
nf.setMaximumFractionDigits(0);
|
||||
nf.setRoundingMode(RoundingMode.FLOOR);
|
||||
return nf.format(d);
|
||||
}
|
||||
|
||||
public static String roundWithNumberFormat(double d) {
|
||||
NumberFormat nf = NumberFormat.getInstance();
|
||||
nf.setMaximumFractionDigits(0);
|
||||
return nf.format(d);
|
||||
}
|
||||
|
||||
public static String truncateWithDecimalFormat(double d) {
|
||||
DecimalFormat df = new DecimalFormat("#,###");
|
||||
df.setRoundingMode(RoundingMode.FLOOR);
|
||||
return df.format(d);
|
||||
}
|
||||
|
||||
public static String roundWithDecimalFormat(double d) {
|
||||
DecimalFormat df = new DecimalFormat("#,###");
|
||||
return df.format(d);
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package com.baeldung;
|
||||
package com.baeldung.simpledateformat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
@ -32,6 +32,7 @@ public class SimpleDateFormatUnitTest {
|
||||
@Test
|
||||
public void givenStringDate_whenParsed_thenCheckDateCorrect() throws Exception{
|
||||
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
|
||||
formatter.setTimeZone(TimeZone.getTimeZone("Europe/London"));
|
||||
Date myDate = new Date(233276400000L);
|
||||
Date parsedDate = formatter.parse("24-05-1977");
|
||||
assertEquals(myDate.getTime(), parsedDate.getTime());
|
||||
|
@ -0,0 +1,45 @@
|
||||
package com.baeldung.string;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class DoubleToStringUnitTest {
|
||||
|
||||
private static final double DOUBLE_VALUE = 3.56;
|
||||
private static final String TRUNCATED_DOUBLE = "3";
|
||||
private static final String ROUNDED_UP_DOUBLE = "4";
|
||||
|
||||
|
||||
@Test
|
||||
public void truncateByCastTest() {
|
||||
assertThat(DoubleToString.truncateByCast(DOUBLE_VALUE)).isEqualTo(TRUNCATED_DOUBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roundingWithStringFormatTest() {
|
||||
assertThat(DoubleToString.roundWithStringFormat(DOUBLE_VALUE)).isEqualTo(ROUNDED_UP_DOUBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void truncateWithNumberFormatTest() {
|
||||
assertThat(DoubleToString.truncateWithNumberFormat(DOUBLE_VALUE)).isEqualTo(TRUNCATED_DOUBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roundWithNumberFormatTest() {
|
||||
assertThat(DoubleToString.roundWithNumberFormat(DOUBLE_VALUE)).isEqualTo(ROUNDED_UP_DOUBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void truncateWithDecimalFormatTest() {
|
||||
assertThat(DoubleToString.truncateWithDecimalFormat(DOUBLE_VALUE)).isEqualTo(TRUNCATED_DOUBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roundWithDecimalFormatTest() {
|
||||
assertThat(DoubleToString.roundWithDecimalFormat(DOUBLE_VALUE)).isEqualTo(ROUNDED_UP_DOUBLE);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.baeldung.thread
|
||||
|
||||
class SimpleRunnable: Runnable {
|
||||
|
||||
override fun run() {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.baeldung.thread
|
||||
|
||||
class SimpleThread: Thread() {
|
||||
|
||||
override fun run() {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
}
|
@ -24,14 +24,15 @@ internal class SliceTest {
|
||||
assertIterableEquals(expected, actual)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenSlicingBeyondTheRangeOfTheArray_thenContainManyNulls() {
|
||||
val original = arrayOf(12, 3, 34, 4)
|
||||
val actual = original.slice(3..8)
|
||||
val expected = listOf(4, null, null, null, null, null)
|
||||
|
||||
assertIterableEquals(expected, actual)
|
||||
}
|
||||
// From the 1.3 version of Kotlin APIs, slice doesn't return array of nulls but throw IndexOutOfBoundsException
|
||||
// @Test
|
||||
// fun whenSlicingBeyondTheRangeOfTheArray_thenContainManyNulls() {
|
||||
// val original = arrayOf(12, 3, 34, 4)
|
||||
// val actual = original.slice(3..8)
|
||||
// val expected = listOf(4, null, null, null, null, null)
|
||||
//
|
||||
// assertIterableEquals(expected, actual)
|
||||
// }
|
||||
|
||||
@Test
|
||||
fun whenSlicingBeyondRangeOfArrayWithStep_thenOutOfBoundsException() {
|
||||
|
@ -1,16 +1,12 @@
|
||||
package com.baeldung.fuel
|
||||
|
||||
import awaitObjectResult
|
||||
import awaitStringResponse
|
||||
import com.github.kittinunf.fuel.Fuel
|
||||
import com.github.kittinunf.fuel.core.FuelManager
|
||||
import com.github.kittinunf.fuel.core.Request
|
||||
import com.github.kittinunf.fuel.core.interceptors.cUrlLoggingRequestInterceptor
|
||||
import com.github.kittinunf.fuel.gson.responseObject
|
||||
import com.github.kittinunf.fuel.httpGet
|
||||
import com.github.kittinunf.fuel.rx.rx_object
|
||||
import com.google.gson.Gson
|
||||
import kotlinx.coroutines.experimental.runBlocking
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.io.File
|
||||
@ -226,32 +222,26 @@ internal class FuelHttpUnitTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenMakeGETRequestUsingCoroutines_thenResponseStatusCode200() {
|
||||
|
||||
runBlocking {
|
||||
val (request, response, result) = Fuel.get("http://httpbin.org/get").awaitStringResponse()
|
||||
// The new 1.3 coroutine APIs, aren't implemented yet in Fuel Library
|
||||
// @Test
|
||||
// fun whenMakeGETRequestUsingCoroutines_thenResponseStatusCode200() = runBlocking {
|
||||
// val (request, response, result) = Fuel.get("http://httpbin.org/get").awaitStringResponse()
|
||||
//
|
||||
// result.fold({ data ->
|
||||
// Assertions.assertEquals(200, response.statusCode)
|
||||
//
|
||||
// }, { error -> })
|
||||
// }
|
||||
|
||||
result.fold({ data ->
|
||||
Assertions.assertEquals(200, response.statusCode)
|
||||
|
||||
}, { error -> })
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenMakeGETRequestUsingCoroutines_thenDeserializeResponse() {
|
||||
|
||||
|
||||
runBlocking {
|
||||
Fuel.get("https://jsonplaceholder.typicode.com/posts?id=1").awaitObjectResult(Post.Deserializer())
|
||||
.fold({ data ->
|
||||
Assertions.assertEquals(1, data.get(0).userId)
|
||||
}, { error -> })
|
||||
}
|
||||
|
||||
}
|
||||
// The new 1.3 coroutine APIs, aren't implemented yet in Fuel Library
|
||||
// @Test
|
||||
// fun whenMakeGETRequestUsingCoroutines_thenDeserializeResponse() = runBlocking {
|
||||
// Fuel.get("https://jsonplaceholder.typicode.com/posts?id=1").awaitObjectResult(Post.Deserializer())
|
||||
// .fold({ data ->
|
||||
// Assertions.assertEquals(1, data.get(0).userId)
|
||||
// }, { error -> })
|
||||
// }
|
||||
|
||||
@Test
|
||||
fun whenMakeGETPostRequestUsingRoutingAPI_thenDeserializeResponse() {
|
||||
|
@ -1,9 +1,8 @@
|
||||
package com.baeldung.kotlin
|
||||
|
||||
import kotlinx.coroutines.experimental.*
|
||||
import kotlinx.coroutines.*
|
||||
import org.junit.Test
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.coroutines.experimental.buildSequence
|
||||
import kotlin.system.measureTimeMillis
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
@ -14,7 +13,7 @@ class CoroutinesTest {
|
||||
@Test
|
||||
fun givenBuildSequence_whenTakeNElements_thenShouldReturnItInALazyWay() {
|
||||
//given
|
||||
val fibonacciSeq = buildSequence {
|
||||
val fibonacciSeq = sequence {
|
||||
var a = 0
|
||||
var b = 1
|
||||
|
||||
@ -39,7 +38,7 @@ class CoroutinesTest {
|
||||
@Test
|
||||
fun givenLazySeq_whenTakeNElements_thenShouldReturnAllElements() {
|
||||
//given
|
||||
val lazySeq = buildSequence {
|
||||
val lazySeq = sequence {
|
||||
print("START ")
|
||||
for (i in 1..5) {
|
||||
yield(i)
|
||||
@ -60,8 +59,8 @@ class CoroutinesTest {
|
||||
val res = mutableListOf<String>()
|
||||
|
||||
//when
|
||||
runBlocking<Unit> {
|
||||
val promise = launch(CommonPool) { expensiveComputation(res) }
|
||||
runBlocking {
|
||||
val promise = launch(Dispatchers.Default) { expensiveComputation(res) }
|
||||
res.add("Hello,")
|
||||
promise.join()
|
||||
}
|
||||
@ -85,7 +84,7 @@ class CoroutinesTest {
|
||||
|
||||
//when
|
||||
val jobs = List(numberOfCoroutines) {
|
||||
launch(CommonPool) {
|
||||
launch(Dispatchers.Default) {
|
||||
delay(1L)
|
||||
counter.incrementAndGet()
|
||||
}
|
||||
@ -101,7 +100,7 @@ class CoroutinesTest {
|
||||
fun givenCancellableJob_whenRequestForCancel_thenShouldQuit() {
|
||||
runBlocking<Unit> {
|
||||
//given
|
||||
val job = launch(CommonPool) {
|
||||
val job = launch(Dispatchers.Default) {
|
||||
while (isActive) {
|
||||
//println("is working")
|
||||
}
|
||||
@ -135,8 +134,8 @@ class CoroutinesTest {
|
||||
val delay = 1000L
|
||||
val time = measureTimeMillis {
|
||||
//given
|
||||
val one = async(CommonPool) { someExpensiveComputation(delay) }
|
||||
val two = async(CommonPool) { someExpensiveComputation(delay) }
|
||||
val one = async(Dispatchers.Default) { someExpensiveComputation(delay) }
|
||||
val two = async(Dispatchers.Default) { someExpensiveComputation(delay) }
|
||||
|
||||
//when
|
||||
runBlocking {
|
||||
@ -156,8 +155,8 @@ class CoroutinesTest {
|
||||
val delay = 1000L
|
||||
val time = measureTimeMillis {
|
||||
//given
|
||||
val one = async(CommonPool, CoroutineStart.LAZY) { someExpensiveComputation(delay) }
|
||||
val two = async(CommonPool, CoroutineStart.LAZY) { someExpensiveComputation(delay) }
|
||||
val one = async(Dispatchers.Default, CoroutineStart.LAZY) { someExpensiveComputation(delay) }
|
||||
val two = async(Dispatchers.Default, CoroutineStart.LAZY) { someExpensiveComputation(delay) }
|
||||
|
||||
//when
|
||||
runBlocking {
|
||||
|
@ -0,0 +1,52 @@
|
||||
package com.baeldung.thread
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class CoroutineUnitTest {
|
||||
|
||||
@Test
|
||||
fun whenCreateCoroutineWithLaunchWithoutContext_thenRun() = runBlocking {
|
||||
|
||||
val job = launch {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCreateCoroutineWithLaunchWithDefaultContext_thenRun() = runBlocking {
|
||||
|
||||
val job = launch(Dispatchers.Default) {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCreateCoroutineWithLaunchWithUnconfinedContext_thenRun() = runBlocking {
|
||||
|
||||
val job = launch(Dispatchers.Unconfined) {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCreateCoroutineWithLaunchWithDedicatedThread_thenRun() = runBlocking {
|
||||
|
||||
val job = launch(newSingleThreadContext("dedicatedThread")) {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCreateAsyncCoroutine_thenRun() = runBlocking {
|
||||
|
||||
val deferred = async(Dispatchers.IO) {
|
||||
return@async "${Thread.currentThread()} has run."
|
||||
}
|
||||
|
||||
val result = deferred.await()
|
||||
println(result)
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.baeldung.thread
|
||||
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
class ThreadUnitTest {
|
||||
|
||||
@Test
|
||||
fun whenCreateThread_thenRun() {
|
||||
|
||||
val thread = SimpleThread()
|
||||
thread.start()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCreateThreadWithRunnable_thenRun() {
|
||||
|
||||
val threadWithRunnable = Thread(SimpleRunnable())
|
||||
threadWithRunnable.start()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCreateThreadWithSAMConversions_thenRun() {
|
||||
|
||||
val thread = Thread {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
thread.start()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun whenCreateThreadWithMethodExtension_thenRun() {
|
||||
|
||||
thread(start = true) {
|
||||
println("${Thread.currentThread()} has run.")
|
||||
}
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ import java.time.LocalDate;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
|
||||
public class HibernateCustomTypesUnitTest {
|
||||
public class HibernateCustomTypesManualTest {
|
||||
|
||||
@Test
|
||||
public void givenEmployee_whenSavedWithCustomTypes_thenEntityIsSaved() throws IOException {
|
@ -1,19 +1,22 @@
|
||||
package com.baeldung.zoneddatetime;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class ZonedDateTimeUnitTest {
|
||||
|
||||
private static final Logger log = Logger.getLogger(ZonedDateTimeUnitTest.class.getName());
|
||||
|
||||
@Test
|
||||
public void testZonedDateTimeToString() {
|
||||
public void givenZonedDateTime_whenConvertToString_thenOk() {
|
||||
|
||||
ZonedDateTime zonedDateTimeNow = ZonedDateTime.now(ZoneId.of("UTC"));
|
||||
ZonedDateTime zonedDateTimeOf = ZonedDateTime.of(2018, 01, 01, 0, 0, 0, 0, ZoneId.of("UTC"));
|
||||
@ -21,10 +24,10 @@ public class ZonedDateTimeUnitTest {
|
||||
LocalDateTime localDateTime = LocalDateTime.now();
|
||||
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.of("UTC"));
|
||||
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy - hh:mm:ss Z");
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy - HH:mm:ss Z");
|
||||
String formattedString = zonedDateTime.format(formatter);
|
||||
|
||||
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MM/dd/yyyy - hh:mm:ss z");
|
||||
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MM/dd/yyyy - HH:mm:ss z");
|
||||
String formattedString2 = zonedDateTime.format(formatter2);
|
||||
|
||||
log.info(formattedString);
|
||||
@ -33,9 +36,21 @@ public class ZonedDateTimeUnitTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZonedDateTimeFromString() {
|
||||
public void givenString_whenParseZonedDateTime_thenOk() {
|
||||
ZonedDateTime zonedDateTime = ZonedDateTime.parse("2011-12-03T10:15:30+01:00");
|
||||
|
||||
ZonedDateTime zonedDateTime = ZonedDateTime.parse("2011-12-03T10:15:30+01:00", DateTimeFormatter.ISO_ZONED_DATE_TIME);
|
||||
log.info(zonedDateTime.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenString_whenParseZonedDateTimeWithoutZone_thenException() {
|
||||
assertThrows(DateTimeParseException.class, () -> ZonedDateTime.parse("2011-12-03T10:15:30", DateTimeFormatter.ISO_DATE_TIME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenString_whenParseLocalDateTimeAtZone_thenOk() {
|
||||
ZoneId timeZone = ZoneId.systemDefault();
|
||||
ZonedDateTime zonedDateTime = LocalDateTime.parse("2011-12-03T10:15:30", DateTimeFormatter.ISO_DATE_TIME).atZone(timeZone);
|
||||
|
||||
log.info(zonedDateTime.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
|
||||
}
|
||||
|
@ -259,6 +259,11 @@
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.storm</groupId>
|
||||
<artifactId>storm-core</artifactId>
|
||||
<version>${storm.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
@ -432,6 +437,7 @@
|
||||
</repositories>
|
||||
|
||||
<properties>
|
||||
<storm.version>1.2.2</storm.version>
|
||||
<kryo.version>4.0.1</kryo.version>
|
||||
<h2.version>1.4.196</h2.version>
|
||||
<reladomo.version>16.5.1</reladomo.version>
|
||||
|
@ -0,0 +1,34 @@
|
||||
package com.baeldung.storm;
|
||||
|
||||
import com.baeldung.storm.bolt.AggregatingBolt;
|
||||
import com.baeldung.storm.bolt.FileWritingBolt;
|
||||
import com.baeldung.storm.bolt.FilteringBolt;
|
||||
import com.baeldung.storm.bolt.PrintingBolt;
|
||||
import com.baeldung.storm.spout.RandomNumberSpout;
|
||||
import org.apache.storm.Config;
|
||||
import org.apache.storm.LocalCluster;
|
||||
import org.apache.storm.topology.TopologyBuilder;
|
||||
import org.apache.storm.topology.base.BaseWindowedBolt;
|
||||
|
||||
public class TopologyRunner {
|
||||
public static void main(String[] args) {
|
||||
runTopology();
|
||||
}
|
||||
|
||||
public static void runTopology() {
|
||||
String filePath = "./src/main/resources/operations.txt";
|
||||
TopologyBuilder builder = new TopologyBuilder();
|
||||
builder.setSpout("randomNumberSpout", new RandomNumberSpout());
|
||||
builder.setBolt("filteringBolt", new FilteringBolt()).shuffleGrouping("randomNumberSpout");
|
||||
builder.setBolt("aggregatingBolt", new AggregatingBolt()
|
||||
.withTimestampField("timestamp")
|
||||
.withLag(BaseWindowedBolt.Duration.seconds(1))
|
||||
.withWindow(BaseWindowedBolt.Duration.seconds(5))).shuffleGrouping("filteringBolt");
|
||||
builder.setBolt("fileBolt", new FileWritingBolt(filePath)).shuffleGrouping("aggregatingBolt");
|
||||
|
||||
Config config = new Config();
|
||||
config.setDebug(false);
|
||||
LocalCluster cluster = new LocalCluster();
|
||||
cluster.submitTopology("Test", config, builder.createTopology());
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.baeldung.storm.bolt;
|
||||
|
||||
import org.apache.storm.task.OutputCollector;
|
||||
import org.apache.storm.task.TopologyContext;
|
||||
import org.apache.storm.topology.OutputFieldsDeclarer;
|
||||
import org.apache.storm.topology.base.BaseWindowedBolt;
|
||||
import org.apache.storm.tuple.Fields;
|
||||
import org.apache.storm.tuple.Tuple;
|
||||
import org.apache.storm.tuple.Values;
|
||||
import org.apache.storm.windowing.TupleWindow;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class AggregatingBolt extends BaseWindowedBolt {
|
||||
private OutputCollector outputCollector;
|
||||
@Override
|
||||
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
|
||||
this.outputCollector = collector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void declareOutputFields(OutputFieldsDeclarer declarer) {
|
||||
declarer.declare(new Fields("sumOfOperations", "beginningTimestamp", "endTimestamp"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(TupleWindow tupleWindow) {
|
||||
List<Tuple> tuples = tupleWindow.get();
|
||||
tuples.sort(Comparator.comparing(a -> a.getLongByField("timestamp")));
|
||||
//This is safe since the window is calculated basing on Tuple's timestamp, thus it can't really be empty
|
||||
Long beginningTimestamp = tuples.get(0).getLongByField("timestamp");
|
||||
Long endTimestamp = tuples.get(tuples.size() - 1).getLongByField("timestamp");
|
||||
int sumOfOperations = tuples.stream().mapToInt(tuple -> tuple.getIntegerByField("operation")).sum();
|
||||
Values values = new Values(sumOfOperations, beginningTimestamp, endTimestamp);
|
||||
outputCollector.emit(values);
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package com.baeldung.storm.bolt;
|
||||
|
||||
import com.baeldung.storm.model.AggregatedWindow;
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.storm.task.OutputCollector;
|
||||
import org.apache.storm.task.TopologyContext;
|
||||
import org.apache.storm.topology.OutputFieldsDeclarer;
|
||||
import org.apache.storm.topology.base.BaseRichBolt;
|
||||
import org.apache.storm.tuple.Tuple;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
public class FileWritingBolt extends BaseRichBolt {
|
||||
public static Logger logger = LoggerFactory.getLogger(FileWritingBolt.class);
|
||||
private BufferedWriter writer;
|
||||
private String filePath;
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
@Override
|
||||
public void prepare(Map map, TopologyContext topologyContext, OutputCollector outputCollector) {
|
||||
objectMapper = new ObjectMapper();
|
||||
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
|
||||
try {
|
||||
writer = new BufferedWriter(new FileWriter(filePath));
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to open a file for writing.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Tuple tuple) {
|
||||
int sumOfOperations = tuple.getIntegerByField("sumOfOperations");
|
||||
long beginningTimestamp = tuple.getLongByField("beginningTimestamp");
|
||||
long endTimestamp = tuple.getLongByField("endTimestamp");
|
||||
|
||||
if(sumOfOperations > 200) {
|
||||
AggregatedWindow aggregatedWindow = new AggregatedWindow(sumOfOperations, beginningTimestamp, endTimestamp);
|
||||
try {
|
||||
writer.write(objectMapper.writeValueAsString(aggregatedWindow));
|
||||
writer.write("\n");
|
||||
writer.flush();
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to write data to file.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public FileWritingBolt(String filePath) {
|
||||
this.filePath = filePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
try {
|
||||
writer.close();
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to close the writer!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package com.baeldung.storm.bolt;
|
||||
|
||||
import org.apache.storm.topology.BasicOutputCollector;
|
||||
import org.apache.storm.topology.OutputFieldsDeclarer;
|
||||
import org.apache.storm.topology.base.BaseBasicBolt;
|
||||
import org.apache.storm.tuple.Fields;
|
||||
import org.apache.storm.tuple.Tuple;
|
||||
|
||||
public class FilteringBolt extends BaseBasicBolt {
|
||||
@Override
|
||||
public void execute(Tuple tuple, BasicOutputCollector basicOutputCollector) {
|
||||
int operation = tuple.getIntegerByField("operation");
|
||||
if(operation > 0 ) {
|
||||
basicOutputCollector.emit(tuple.getValues());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
|
||||
outputFieldsDeclarer.declare(new Fields("operation", "timestamp"));
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.baeldung.storm.bolt;
|
||||
|
||||
import org.apache.storm.topology.BasicOutputCollector;
|
||||
import org.apache.storm.topology.OutputFieldsDeclarer;
|
||||
import org.apache.storm.topology.base.BaseBasicBolt;
|
||||
import org.apache.storm.tuple.Tuple;
|
||||
|
||||
public class PrintingBolt extends BaseBasicBolt {
|
||||
@Override
|
||||
public void execute(Tuple tuple, BasicOutputCollector basicOutputCollector) {
|
||||
System.out.println(tuple);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package com.baeldung.storm.model;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
|
||||
@JsonSerialize
|
||||
public class AggregatedWindow {
|
||||
int sumOfOperations;
|
||||
long beginningTimestamp;
|
||||
long endTimestamp;
|
||||
|
||||
public AggregatedWindow(int sumOfOperations, long beginningTimestamp, long endTimestamp) {
|
||||
this.sumOfOperations = sumOfOperations;
|
||||
this.beginningTimestamp = beginningTimestamp;
|
||||
this.endTimestamp = endTimestamp;
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.baeldung.storm.model;
|
||||
|
||||
public class User {
|
||||
private String username;
|
||||
private String password;
|
||||
private String email;
|
||||
private int age;
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package com.baeldung.storm.serialization;
|
||||
|
||||
|
||||
import com.baeldung.storm.model.User;
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.Serializer;
|
||||
import com.esotericsoftware.kryo.io.Input;
|
||||
import com.esotericsoftware.kryo.io.Output;
|
||||
|
||||
public class UserSerializer extends Serializer<User>{
|
||||
@Override
|
||||
public void write(Kryo kryo, Output output, User user) {
|
||||
output.writeString(user.getEmail());
|
||||
output.writeString(user.getUsername());
|
||||
output.write(user.getAge());
|
||||
}
|
||||
|
||||
@Override
|
||||
public User read(Kryo kryo, Input input, Class<User> aClass) {
|
||||
User user = new User();
|
||||
String email = input.readString();
|
||||
String name = input.readString();
|
||||
int age = input.read();
|
||||
user.setAge(age);
|
||||
user.setEmail(email);
|
||||
user.setUsername(name);
|
||||
|
||||
return user;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package com.baeldung.storm.spout;
|
||||
|
||||
import org.apache.storm.spout.SpoutOutputCollector;
|
||||
import org.apache.storm.task.TopologyContext;
|
||||
import org.apache.storm.topology.OutputFieldsDeclarer;
|
||||
import org.apache.storm.topology.base.BaseRichSpout;
|
||||
import org.apache.storm.tuple.Fields;
|
||||
import org.apache.storm.tuple.Values;
|
||||
import org.apache.storm.utils.Utils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
public class RandomIntSpout extends BaseRichSpout {
|
||||
|
||||
private Random random;
|
||||
private SpoutOutputCollector outputCollector;
|
||||
|
||||
@Override
|
||||
public void open(Map map, TopologyContext topologyContext, SpoutOutputCollector spoutOutputCollector) {
|
||||
random = new Random();
|
||||
outputCollector = spoutOutputCollector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nextTuple() {
|
||||
Utils.sleep(1000);
|
||||
outputCollector.emit(new Values(random.nextInt(), System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
|
||||
outputFieldsDeclarer.declare(new Fields("randomInt", "timestamp"));
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.baeldung.storm.spout;
|
||||
|
||||
import org.apache.storm.spout.SpoutOutputCollector;
|
||||
import org.apache.storm.task.OutputCollector;
|
||||
import org.apache.storm.task.TopologyContext;
|
||||
import org.apache.storm.topology.OutputFieldsDeclarer;
|
||||
import org.apache.storm.topology.base.BaseRichSpout;
|
||||
import org.apache.storm.tuple.Fields;
|
||||
import org.apache.storm.tuple.Values;
|
||||
import org.apache.storm.utils.Utils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
public class RandomNumberSpout extends BaseRichSpout {
|
||||
private Random random;
|
||||
private SpoutOutputCollector collector;
|
||||
|
||||
@Override
|
||||
public void open(Map map, TopologyContext topologyContext, SpoutOutputCollector spoutOutputCollector) {
|
||||
random = new Random();
|
||||
collector = spoutOutputCollector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void nextTuple() {
|
||||
Utils.sleep(1000);
|
||||
//This will select random int from the range (0, 100)
|
||||
int operation = random.nextInt(101);
|
||||
long timestamp = System.currentTimeMillis();
|
||||
|
||||
Values values = new Values(operation, timestamp);
|
||||
collector.emit(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void declareOutputFields(OutputFieldsDeclarer outputFieldsDeclarer) {
|
||||
outputFieldsDeclarer.declare(new Fields("operation", "timestamp"));
|
||||
}
|
||||
}
|
@ -22,7 +22,18 @@
|
||||
<id>kotlin-ktor</id>
|
||||
<url>https://dl.bintray.com/kotlin/ktor/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>kotlin-eap</id>
|
||||
<url>http://dl.bintray.com/kotlin/kotlin-eap</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>kotlin-eap</id>
|
||||
<url>http://dl.bintray.com/kotlin/kotlin-eap</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
@ -42,6 +53,11 @@
|
||||
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-reflect</artifactId>
|
||||
@ -157,6 +173,7 @@
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>${maven-failsafe-plugin.version}</version>
|
||||
<dependencies>
|
||||
@ -185,8 +202,8 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<kotlin.version>1.2.61</kotlin.version>
|
||||
<kotlinx.version>0.25.0</kotlinx.version>
|
||||
<kotlin.version>1.3.0-rc-146</kotlin.version>
|
||||
<kotlinx.version>0.26.1-eap13</kotlinx.version>
|
||||
<ktor.io.version>0.9.3</ktor.io.version>
|
||||
<assertj.version>3.11.0</assertj.version>
|
||||
<junit.platform.version>1.2.0</junit.platform.version>
|
||||
|
@ -16,22 +16,35 @@
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>${h2database.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>tomcat-jdbc</artifactId>
|
||||
<version>${tomcat-jdbc.version}</version>
|
||||
@ -41,20 +54,14 @@
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>${mysql-connector-java.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>${h2database.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
<mysql-connector-java.version>8.0.12</mysql-connector-java.version>
|
||||
<tomcat-jdbc.version>9.0.10</tomcat-jdbc.version>
|
||||
<h2database.version>1.4.197</h2database.version>
|
||||
<mockito.version>2.23.0</mockito.version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
|
@ -0,0 +1,22 @@
|
||||
package com.baeldung.springbootcrudapp.application;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableAutoConfiguration
|
||||
@ComponentScan(basePackages={"com.baeldung.springbootcrudapp.application"})
|
||||
@EnableJpaRepositories(basePackages="com.baeldung.springbootcrudapp.application.repositories")
|
||||
@EnableTransactionManagement
|
||||
@EntityScan(basePackages="com.baeldung.springbootcrudapp.application.entities")
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package com.baeldung.springbootcrudapp.application.controllers;
|
||||
|
||||
import com.baeldung.springbootcrudapp.application.repositories.UserRepository;
|
||||
import com.baeldung.springbootcrudapp.application.entities.User;
|
||||
import javax.validation.Valid;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
@Controller
|
||||
public class UserController {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
public UserController(UserRepository userRepository) {
|
||||
this.userRepository = userRepository;
|
||||
}
|
||||
|
||||
@GetMapping("/signup")
|
||||
public String showSignUpForm(User user) {
|
||||
return "add-user";
|
||||
}
|
||||
|
||||
@PostMapping("/adduser")
|
||||
public String addUser(@Valid User user, BindingResult result, Model model) {
|
||||
if (result.hasErrors()) {
|
||||
return "add-user";
|
||||
}
|
||||
|
||||
userRepository.save(user);
|
||||
model.addAttribute("users", userRepository.findAll());
|
||||
return "index";
|
||||
}
|
||||
|
||||
@GetMapping("/edit/{id}")
|
||||
public String showUpdateForm(@PathVariable("id") long id, Model model) {
|
||||
User user = userRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));
|
||||
model.addAttribute("user", user);
|
||||
return "update-user";
|
||||
}
|
||||
|
||||
@PostMapping("/update/{id}")
|
||||
public String updateUser(@PathVariable("id") long id, @Valid User user, BindingResult result, Model model) {
|
||||
if (result.hasErrors()) {
|
||||
user.setId(id);
|
||||
return "update-user";
|
||||
}
|
||||
|
||||
userRepository.save(user);
|
||||
model.addAttribute("users", userRepository.findAll());
|
||||
return "index";
|
||||
}
|
||||
|
||||
@GetMapping("/delete/{id}")
|
||||
public String deleteUser(@PathVariable("id") long id, Model model) {
|
||||
User user = userRepository.findById(id).orElseThrow(() -> new IllegalArgumentException("Invalid user Id:" + id));
|
||||
userRepository.delete(user);
|
||||
model.addAttribute("users", userRepository.findAll());
|
||||
return "index";
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package com.baeldung.springbootcrudapp.application.entities;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@Entity
|
||||
public class User {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private long id;
|
||||
@NotBlank(message = "Name is mandatory")
|
||||
private String name;
|
||||
|
||||
@NotBlank(message = "Email is mandatory")
|
||||
private String email;
|
||||
|
||||
public User() {}
|
||||
|
||||
public User(String name, String email) {
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "User{" + "id=" + id + ", name=" + name + ", email=" + email + '}';
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package com.baeldung.springbootcrudapp.application.repositories;
|
||||
|
||||
import com.baeldung.springbootcrudapp.application.entities.User;
|
||||
import java.util.List;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface UserRepository extends CrudRepository<User, Long> {
|
||||
|
||||
List<User> findByName(String name);
|
||||
|
||||
}
|
2
persistence-modules/spring-boot-persistence/src/main/resources/css/shards.min.css
vendored
Normal file
2
persistence-modules/spring-boot-persistence/src/main/resources/css/shards.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<title>Add User</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.1/css/all.css" integrity="sha384-5sAR7xN1Nv6T6+dT2mhtzEpVJvfS3NScPQTrOxhwjIuvcA67KV2R5Jz6kr4abQsz" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="../css/shards.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container my-5">
|
||||
<h2 class="mb-5">New User</h2>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<form action="#" th:action="@{/adduser}" th:object="${user}" method="post">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="name" class="col-form-label">Name</label>
|
||||
<input type="text" th:field="*{name}" class="form-control" id="name" placeholder="Name">
|
||||
<span th:if="${#fields.hasErrors('name')}" th:errors="*{name}" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="email" class="col-form-label">Email</label>
|
||||
<input type="text" th:field="*{email}" class="form-control" id="email" placeholder="Email">
|
||||
<span th:if="${#fields.hasErrors('email')}" th:errors="*{email}" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mt-5">
|
||||
<input type="submit" class="btn btn-primary" value="Add User">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<title>Users</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.1/css/all.css" integrity="sha384-5sAR7xN1Nv6T6+dT2mhtzEpVJvfS3NScPQTrOxhwjIuvcA67KV2R5Jz6kr4abQsz" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="../css/shards.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div th:switch="${users}" class="container my-5">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<h2 th:case="null">No users yet!</h2>
|
||||
<div th:case="*">
|
||||
<h2 class="my-5">Users</h2>
|
||||
<table class="table table-striped table-responsive-md">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Email</th>
|
||||
<th>Edit</th>
|
||||
<th>Delete</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="user : ${users}">
|
||||
<td th:text="${user.name}"></td>
|
||||
<td th:text="${user.email}"></td>
|
||||
<td><a th:href="@{/edit/{id}(id=${user.id})}" class="btn btn-primary"><i class="fas fa-user-edit ml-2"></i></a></td>
|
||||
<td><a th:href="@{/delete/{id}(id=${user.id})}" class="btn btn-primary"><i class="fas fa-user-times ml-2"></i></a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="my-5"><a href="/signup" class="btn btn-primary"><i class="fas fa-user-plus ml-2"></i></a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<title>Update User</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.4.1/css/all.css" integrity="sha384-5sAR7xN1Nv6T6+dT2mhtzEpVJvfS3NScPQTrOxhwjIuvcA67KV2R5Jz6kr4abQsz" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="../css/shards.min.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container my-5">
|
||||
<h2 class="mb-5">Update User</h2>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<form action="#" th:action="@{/update/{id}(id=${user.id})}" th:object="${user}" method="post">
|
||||
<div class="row">
|
||||
<div class="form-group col-md-6">
|
||||
<label for="name" class="col-form-label">Name</label>
|
||||
<input type="text" th:field="*{name}" class="form-control" id="name" placeholder="Name">
|
||||
<span th:if="${#fields.hasErrors('name')}" th:errors="*{name}" class="text-danger"></span>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label for="email" class="col-form-label">Email</label>
|
||||
<input type="text" th:field="*{email}" class="form-control" id="email" placeholder="Email">
|
||||
<span th:if="${#fields.hasErrors('email')}" th:errors="*{email}" class="text-danger"></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 mt-5">
|
||||
<input type="submit" class="btn btn-primary" value="Update User">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,81 @@
|
||||
package com.baeldung.springbootcrudapp.application.tests;
|
||||
|
||||
import com.baeldung.springbootcrudapp.application.controllers.UserController;
|
||||
import com.baeldung.springbootcrudapp.application.entities.User;
|
||||
import com.baeldung.springbootcrudapp.application.repositories.UserRepository;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.BindingResult;
|
||||
|
||||
public class UserControllerUnitTest {
|
||||
|
||||
private static UserController userController;
|
||||
private static UserRepository mockedUserRepository;
|
||||
private static BindingResult mockedBindingResult;
|
||||
private static Model mockedModel;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpUserControllerInstance() {
|
||||
mockedUserRepository = mock(UserRepository.class);
|
||||
mockedBindingResult = mock(BindingResult.class);
|
||||
mockedModel = mock(Model.class);
|
||||
userController = new UserController(mockedUserRepository);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCalledshowSignUpForm_thenCorrect() {
|
||||
User user = new User("John", "john@domain.com");
|
||||
|
||||
assertThat(userController.showSignUpForm(user)).isEqualTo("add-user");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCalledaddUserAndValidUser_thenCorrect() {
|
||||
User user = new User("John", "john@domain.com");
|
||||
|
||||
when(mockedBindingResult.hasErrors()).thenReturn(false);
|
||||
|
||||
assertThat(userController.addUser(user, mockedBindingResult, mockedModel)).isEqualTo("index");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCalledaddUserAndInValidUser_thenCorrect() {
|
||||
User user = new User("John", "john@domain.com");
|
||||
|
||||
when(mockedBindingResult.hasErrors()).thenReturn(true);
|
||||
|
||||
assertThat(userController.addUser(user, mockedBindingResult, mockedModel)).isEqualTo("add-user");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void whenCalledshowUpdateForm_thenIllegalArgumentException() {
|
||||
assertThat(userController.showUpdateForm(0, mockedModel)).isEqualTo("update-user");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCalledupdateUserAndValidUser_thenCorrect() {
|
||||
User user = new User("John", "john@domain.com");
|
||||
|
||||
when(mockedBindingResult.hasErrors()).thenReturn(false);
|
||||
|
||||
assertThat(userController.updateUser(1l, user, mockedBindingResult, mockedModel)).isEqualTo("index");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCalledupdateUserAndInValidUser_thenCorrect() {
|
||||
User user = new User("John", "john@domain.com");
|
||||
|
||||
when(mockedBindingResult.hasErrors()).thenReturn(true);
|
||||
|
||||
assertThat(userController.updateUser(1l, user, mockedBindingResult, mockedModel)).isEqualTo("update-user");
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void whenCalleddeleteUser_thenIllegalArgumentException() {
|
||||
assertThat(userController.deleteUser(1l, mockedModel)).isEqualTo("index");
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
package com.baeldung.springbootcrudapp.application.tests;
|
||||
|
||||
import com.baeldung.springbootcrudapp.application.entities.User;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import org.junit.Test;
|
||||
|
||||
public class UserUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenCalledGetName_thenCorrect() {
|
||||
User user = new User("Julie", "julie@domain.com");
|
||||
|
||||
assertThat(user.getName()).isEqualTo("Julie");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCalledGetEmail_thenCorrect() {
|
||||
User user = new User("Julie", "julie@domain.com");
|
||||
|
||||
assertThat(user.getEmail()).isEqualTo("julie@domain.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCalledSetName_thenCorrect() {
|
||||
User user = new User("Julie", "julie@domain.com");
|
||||
|
||||
user.setName("John");
|
||||
|
||||
assertThat(user.getName()).isEqualTo("John");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCalledSetEmail_thenCorrect() {
|
||||
User user = new User("Julie", "julie@domain.com");
|
||||
|
||||
user.setEmail("john@domain.com");
|
||||
|
||||
assertThat(user.getEmail()).isEqualTo("john@domain.com");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCalledtoString_thenCorrect() {
|
||||
User user = new User("Julie", "julie@domain.com");
|
||||
assertThat(user.toString()).isEqualTo("User{id=0, name=Julie, email=julie@domain.com}");
|
||||
}
|
||||
}
|
@ -16,5 +16,6 @@ public class CollectionInjectionDemo {
|
||||
collectionsBean.printNameSet();
|
||||
collectionsBean.printNameMap();
|
||||
collectionsBean.printBeanList();
|
||||
collectionsBean.printNameListWithDefaults();
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,14 @@
|
||||
package com.baeldung.collection;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
|
||||
/**
|
||||
* Created by Gebruiker on 5/18/2018.
|
||||
*/
|
||||
@ -24,6 +25,9 @@ public class CollectionsBean {
|
||||
@Qualifier("CollectionsBean")
|
||||
private List<BaeldungBean> beanList = new ArrayList<>();
|
||||
|
||||
@Value("${names.list:}#{T(java.util.Collections).emptyList()}")
|
||||
private List<String> nameListWithDefaultValue;
|
||||
|
||||
public CollectionsBean() {
|
||||
}
|
||||
|
||||
@ -51,4 +55,8 @@ public class CollectionsBean {
|
||||
public void printBeanList() {
|
||||
System.out.println(beanList);
|
||||
}
|
||||
|
||||
public void printNameListWithDefaults() {
|
||||
System.out.println(nameListWithDefaultValue);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,45 @@
|
||||
package org.baeldung.security;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class SessionFilter implements Filter{
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
System.out.println("init filter");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
HttpServletRequest req = (HttpServletRequest) request;
|
||||
HttpServletResponse res = (HttpServletResponse) response;
|
||||
Cookie[] allCookies = req.getCookies();
|
||||
if (allCookies != null) {
|
||||
Cookie session = Arrays.stream(allCookies).filter(x -> x.getName().equals("JSESSIONID")).findFirst().orElse(null);
|
||||
|
||||
if (session != null) {
|
||||
session.setHttpOnly(true);
|
||||
session.setSecure(true);
|
||||
res.addCookie(session);
|
||||
}
|
||||
}
|
||||
chain.doFilter(req, res);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
System.out.println("destroy filter");
|
||||
}
|
||||
|
||||
}
|
@ -8,6 +8,10 @@
|
||||
|
||||
<session-config>
|
||||
<session-timeout>1</session-timeout>
|
||||
<!-- <cookie-config>
|
||||
<http-only>true</http-only>
|
||||
<secure>true</secure>
|
||||
</cookie-config> -->
|
||||
</session-config>
|
||||
<listener>
|
||||
<listener-class>org.baeldung.web.SessionListenerWithMetrics</listener-class>
|
||||
@ -52,6 +56,15 @@
|
||||
<filter-name>springSecurityFilterChain</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<!-- <filter>
|
||||
<filter-name>SessionFilter</filter-name>
|
||||
<filter-class>org.baeldung.security.SessionFilter</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>SessionFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping> -->
|
||||
|
||||
<!-- <welcome-file-list> -->
|
||||
<!-- <welcome-file>index.html</welcome-file> -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user