Merge branch 'master' into master
This commit is contained in:
commit
fed95f4857
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
|||||||
[submodule "testgitrepo"]
|
|
||||||
path = testgitrepo
|
|
||||||
url = /home/prd/Development/projects/idea/tutorials/spring-boot/src/main/resources/testgitrepo/
|
|
57
apache-meecrowave/pom.xml
Normal file
57
apache-meecrowave/pom.xml
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>apache-meecrowave</artifactId>
|
||||||
|
<version>0.0.1</version>
|
||||||
|
<name>apache-meecrowave</name>
|
||||||
|
<description>A sample REST API application with Meecrowave</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.apache.meecrowave/meecrowave-core -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.meecrowave</groupId>
|
||||||
|
<artifactId>meecrowave-core</artifactId>
|
||||||
|
<version>1.2.1</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.apache.meecrowave/meecrowave-jpa -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.meecrowave</groupId>
|
||||||
|
<artifactId>meecrowave-jpa</artifactId>
|
||||||
|
<version>1.2.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>3.10.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.meecrowave</groupId>
|
||||||
|
<artifactId>meecrowave-junit</artifactId>
|
||||||
|
<version>1.2.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/junit/junit -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.10</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.meecrowave</groupId>
|
||||||
|
<artifactId>meecrowave-maven-plugin</artifactId>
|
||||||
|
<version>1.2.1</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.baeldung.meecrowave;
|
||||||
|
|
||||||
|
public class Article {
|
||||||
|
private String name;
|
||||||
|
private String author;
|
||||||
|
|
||||||
|
public Article() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Article(String name, String author) {
|
||||||
|
this.author = author;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthor(String author) {
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.baeldung.meecrowave;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
|
@RequestScoped
|
||||||
|
@Path("article")
|
||||||
|
public class ArticleEndpoints {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ArticleService articleService;
|
||||||
|
|
||||||
|
@GET
|
||||||
|
public Response getArticle() {
|
||||||
|
return Response.ok()
|
||||||
|
.entity(new Article("name", "author"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
public Response createArticle(Article article) {
|
||||||
|
return Response.status(Status.CREATED)
|
||||||
|
.entity(articleService.createArticle(article))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.baeldung.meecrowave;
|
||||||
|
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ArticleService {
|
||||||
|
public Article createArticle(Article article) {
|
||||||
|
return article;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package com.baeldung.meecrowave;
|
||||||
|
|
||||||
|
import org.apache.meecrowave.Meecrowave;
|
||||||
|
|
||||||
|
public class Server {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
final Meecrowave.Builder builder = new Meecrowave.Builder();
|
||||||
|
builder.setScanningPackageIncludes("com.baeldung.meecrowave");
|
||||||
|
builder.setJaxrsMapping("/api/*");
|
||||||
|
builder.setJsonpPrettify(true);
|
||||||
|
|
||||||
|
try (Meecrowave meecrowave = new Meecrowave(builder)) {
|
||||||
|
meecrowave.bake().await();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.baeldung.meecrowave;
|
||||||
|
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.meecrowave.Meecrowave;
|
||||||
|
import org.apache.meecrowave.junit.MonoMeecrowave;
|
||||||
|
import org.apache.meecrowave.testing.ConfigurationInject;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
@RunWith(MonoMeecrowave.Runner.class)
|
||||||
|
public class ArticleEndpointsTest {
|
||||||
|
|
||||||
|
@ConfigurationInject
|
||||||
|
private Meecrowave.Builder config;
|
||||||
|
private static OkHttpClient client;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setup() {
|
||||||
|
client = new OkHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRetunedArticle_thenCorrect() throws IOException {
|
||||||
|
final String base = "http://localhost:"+config.getHttpPort();
|
||||||
|
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(base+"/article")
|
||||||
|
.build();
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
|
assertEquals(200, response.code());
|
||||||
|
}
|
||||||
|
}
|
@ -12,7 +12,7 @@ import org.apache.solr.common.SolrDocumentList;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class SolrJavaIntegrationTest {
|
public class SolrJavaLiveTest {
|
||||||
|
|
||||||
private SolrJavaIntegration solrJavaIntegration;
|
private SolrJavaIntegration solrJavaIntegration;
|
||||||
|
|
3
aws-lambda/README.md
Normal file
3
aws-lambda/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
### Relevant Articles:
|
||||||
|
- [Using AWS Lambda with API Gateway](http://www.baeldung.com/aws-lambda-api-gateway)
|
||||||
|
- [Introduction to AWS Serverless Application Model](http://www.baeldung.com/aws-serverless)
|
@ -0,0 +1,54 @@
|
|||||||
|
package com.baeldung.datetime;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.time.DateUtils;
|
||||||
|
|
||||||
|
public class AddHoursToDate {
|
||||||
|
|
||||||
|
public Date addHoursToJavaUtilDate(Date date, int hours) {
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTime(date);
|
||||||
|
calendar.add(Calendar.HOUR_OF_DAY, hours);
|
||||||
|
return calendar.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date addHoursToDateUsingInstant(Date date, int hours) {
|
||||||
|
return Date.from(date.toInstant()
|
||||||
|
.plus(Duration.ofHours(hours)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime addHoursToLocalDateTime(LocalDateTime localDateTime, int hours) {
|
||||||
|
return localDateTime.plusHours(hours);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDateTime subtractHoursToLocalDateTime(LocalDateTime localDateTime, int hours) {
|
||||||
|
return localDateTime.minusHours(hours);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZonedDateTime addHoursToZonedDateTime(ZonedDateTime zonedDateTime, int hours) {
|
||||||
|
return zonedDateTime.plusHours(hours);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZonedDateTime subtractHoursToZonedDateTime(ZonedDateTime zonedDateTime, int hours) {
|
||||||
|
return zonedDateTime.minusHours(hours);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant addHoursToInstant(Instant instant, int hours) {
|
||||||
|
return instant.plus(hours, ChronoUnit.HOURS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Instant subtractHoursToInstant(Instant instant, int hours) {
|
||||||
|
return instant.minus(hours, ChronoUnit.HOURS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date addHoursWithApacheCommons(Date date, int hours) {
|
||||||
|
return DateUtils.addHours(date, hours);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,116 @@
|
|||||||
|
package com.baeldung.datetime;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.Month;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class AddHoursToDateUnitTest {
|
||||||
|
|
||||||
|
private final AddHoursToDate addHoursToDateObj = new AddHoursToDate();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenJavaUtilDate_whenPositiveHours_thenAddHours() {
|
||||||
|
Date actualDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 5, 0).getTime();
|
||||||
|
Date expectedDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 7, 0).getTime();
|
||||||
|
|
||||||
|
assertThat(addHoursToDateObj.addHoursToJavaUtilDate(actualDate, 2)).isEqualTo(expectedDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenJavaUtilDate_whenNegativeHours_thenMinusHours() {
|
||||||
|
Date actualDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 5, 0).getTime();
|
||||||
|
Date expectedDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 3, 0).getTime();
|
||||||
|
|
||||||
|
assertThat(addHoursToDateObj.addHoursToJavaUtilDate(actualDate, -2)).isEqualTo(expectedDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenJavaUtilDate_whenUsingToInstantAndPostiveHours_thenAddHours() {
|
||||||
|
Date actualDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 5, 0).getTime();
|
||||||
|
Date expectedDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 7, 0).getTime();
|
||||||
|
|
||||||
|
assertThat(addHoursToDateObj.addHoursToDateUsingInstant(actualDate, 2)).isEqualTo(expectedDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenJavaUtilDate_whenUsingToInstantAndNegativeHours_thenAddHours() {
|
||||||
|
Date actualDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 5, 0).getTime();
|
||||||
|
Date expectedDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 3, 0).getTime();
|
||||||
|
|
||||||
|
assertThat(addHoursToDateObj.addHoursToDateUsingInstant(actualDate, -2)).isEqualTo(expectedDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenLocalDateTime_whenUsingAddHoursToLocalDateTime_thenAddHours() {
|
||||||
|
LocalDateTime actualDateTime = LocalDateTime.of(2018, Month.JUNE, 25, 5, 0);
|
||||||
|
LocalDateTime expectedDateTime = LocalDateTime.of(2018, Month.JUNE, 25, 7, 0);
|
||||||
|
|
||||||
|
assertThat(addHoursToDateObj.addHoursToLocalDateTime(actualDateTime, 2)).isEqualTo(expectedDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenLocalDateTime_whenUsingMinusHoursToLocalDateTime_thenMinusHours() {
|
||||||
|
LocalDateTime actualDateTime = LocalDateTime.of(2018, Month.JUNE, 25, 5, 0);
|
||||||
|
LocalDateTime expectedDateTime = LocalDateTime.of(2018, Month.JUNE, 25, 3, 0);
|
||||||
|
|
||||||
|
assertThat(addHoursToDateObj.subtractHoursToLocalDateTime(actualDateTime, 2)).isEqualTo(expectedDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenZonedDateTime_whenUsingAddHoursToZonedDateTime_thenAddHours() {
|
||||||
|
ZonedDateTime actualZonedDateTime = ZonedDateTime.of(LocalDateTime.of(2018, Month.JUNE, 25, 5, 0), ZoneId.systemDefault());
|
||||||
|
ZonedDateTime expectedZonedDateTime = ZonedDateTime.of(LocalDateTime.of(2018, Month.JUNE, 25, 7, 0), ZoneId.systemDefault());
|
||||||
|
|
||||||
|
assertThat(addHoursToDateObj.addHoursToZonedDateTime(actualZonedDateTime, 2)).isEqualTo(expectedZonedDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenZonedDateTime_whenUsingMinusHoursToZonedDateTime_thenMinusHours() {
|
||||||
|
ZonedDateTime actualZonedDateTime = ZonedDateTime.of(LocalDateTime.of(2018, Month.JUNE, 25, 5, 0), ZoneId.systemDefault());
|
||||||
|
ZonedDateTime expectedZonedDateTime = ZonedDateTime.of(LocalDateTime.of(2018, Month.JUNE, 25, 3, 0), ZoneId.systemDefault());
|
||||||
|
|
||||||
|
assertThat(addHoursToDateObj.subtractHoursToZonedDateTime(actualZonedDateTime, 2)).isEqualTo(expectedZonedDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenJavaUtilDate_whenUsingPositiveHrsAndAddHoursWithApacheCommons_thenAddHours() {
|
||||||
|
Date actualDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 5, 0).getTime();
|
||||||
|
Date expectedDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 7, 0).getTime();
|
||||||
|
|
||||||
|
assertThat(addHoursToDateObj.addHoursWithApacheCommons(actualDate, 2)).isEqualTo(expectedDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenJavaUtilDate_whenUsingNegativeHrsAndAddHoursWithApacheCommons_thenMinusHours() {
|
||||||
|
Date actualDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 7, 0).getTime();
|
||||||
|
Date expectedDate = new GregorianCalendar(2018, Calendar.JUNE, 25, 5, 0).getTime();
|
||||||
|
|
||||||
|
assertThat(addHoursToDateObj.addHoursWithApacheCommons(actualDate, -2)).isEqualTo(expectedDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenInstant_whenUsingAddHoursToInstant_thenAddHours() {
|
||||||
|
Instant actualValue = Instant.parse("2018-06-25T05:12:35Z");
|
||||||
|
Instant expectedValue = Instant.parse("2018-06-25T07:12:35Z");
|
||||||
|
|
||||||
|
assertThat(addHoursToDateObj.addHoursToInstant(actualValue, 2)).isEqualTo(expectedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenInstant_whenUsingSubtractHoursToInstant_thenMinusHours() {
|
||||||
|
Instant actualValue = Instant.parse("2018-06-25T07:12:35Z");
|
||||||
|
Instant expectedValue = Instant.parse("2018-06-25T05:12:35Z");
|
||||||
|
|
||||||
|
assertThat(addHoursToDateObj.subtractHoursToInstant(actualValue, 2)).isEqualTo(expectedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -166,3 +166,4 @@
|
|||||||
- [Convert a String to Title Case](http://www.baeldung.com/java-string-title-case)
|
- [Convert a String to Title Case](http://www.baeldung.com/java-string-title-case)
|
||||||
- [How to Get the File Extension of a File in Java](http://www.baeldung.com/java-file-extension)
|
- [How to Get the File Extension of a File in Java](http://www.baeldung.com/java-file-extension)
|
||||||
- [Immutable Objects in Java](http://www.baeldung.com/java-immutable-object)
|
- [Immutable Objects in Java](http://www.baeldung.com/java-immutable-object)
|
||||||
|
- [Console I/O in Java](http://www.baeldung.com/java-console-input-output)
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
package com.baeldung.encrypt;
|
||||||
|
|
||||||
|
import javax.crypto.*;
|
||||||
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
import java.io.*;
|
||||||
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
class FileEncrypterDecrypter {
|
||||||
|
|
||||||
|
private SecretKey secretKey;
|
||||||
|
private Cipher cipher;
|
||||||
|
|
||||||
|
FileEncrypterDecrypter(SecretKey secretKey, String cipher) throws NoSuchPaddingException, NoSuchAlgorithmException {
|
||||||
|
this.secretKey = secretKey;
|
||||||
|
this.cipher = Cipher.getInstance(cipher);
|
||||||
|
}
|
||||||
|
|
||||||
|
void encrypt(String content, String fileName) throws InvalidKeyException, IOException {
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
|
||||||
|
byte[] iv = cipher.getIV();
|
||||||
|
|
||||||
|
try (
|
||||||
|
FileOutputStream fileOut = new FileOutputStream(fileName);
|
||||||
|
CipherOutputStream cipherOut = new CipherOutputStream(fileOut, cipher)
|
||||||
|
) {
|
||||||
|
fileOut.write(iv);
|
||||||
|
cipherOut.write(content.getBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
String decrypt(String fileName) throws InvalidAlgorithmParameterException, InvalidKeyException, IOException {
|
||||||
|
|
||||||
|
String content;
|
||||||
|
|
||||||
|
try (FileInputStream fileIn = new FileInputStream(fileName)) {
|
||||||
|
byte[] fileIv = new byte[16];
|
||||||
|
fileIn.read(fileIv);
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(fileIv));
|
||||||
|
|
||||||
|
try (
|
||||||
|
CipherInputStream cipherIn = new CipherInputStream(fileIn, cipher);
|
||||||
|
InputStreamReader inputReader = new InputStreamReader(cipherIn);
|
||||||
|
BufferedReader reader = new BufferedReader(inputReader)
|
||||||
|
) {
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
sb.append(line);
|
||||||
|
}
|
||||||
|
content = sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class Arithmetic {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(Arithmetic.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
int result = 30 / 0; // Trying to divide by zero
|
||||||
|
} catch (ArithmeticException e) {
|
||||||
|
LOGGER.error("ArithmeticException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class ArrayIndexOutOfBounds {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(ArrayIndexOutOfBounds.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
int[] nums = new int[] { 1, 2, 3 };
|
||||||
|
|
||||||
|
try {
|
||||||
|
int numFromNegativeIndex = nums[-1]; // Trying to access at negative index
|
||||||
|
int numFromGreaterIndex = nums[4]; // Trying to access at greater index
|
||||||
|
int numFromLengthIndex = nums[3]; // Trying to access at index equal to size of the array
|
||||||
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
|
LOGGER.error("ArrayIndexOutOfBoundsException caught");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
class Animal {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Dog extends Animal {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Lion extends Animal {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ClassCast {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(ClassCast.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Animal animalOne = new Dog(); // At runtime the instance is dog
|
||||||
|
Dog bruno = (Dog) animalOne; // Downcasting
|
||||||
|
|
||||||
|
Animal animalTwo = new Lion(); // At runtime the instance is animal
|
||||||
|
Dog tommy = (Dog) animalTwo; // Downcasting
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
LOGGER.error("ClassCastException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileReader;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class FileNotFound {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(FileNotFound.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
BufferedReader reader = null;
|
||||||
|
try {
|
||||||
|
reader = new BufferedReader(new FileReader(new File("/invalid/file/location")));
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
LOGGER.error("FileNotFoundException caught!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
Handler globalExceptionHandler = new Handler();
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(globalExceptionHandler);
|
||||||
|
new GlobalExceptionHandler().performArithmeticOperation(10, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int performArithmeticOperation(int num1, int num2) {
|
||||||
|
return num1/num2;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Handler implements Thread.UncaughtExceptionHandler {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(Handler.class);
|
||||||
|
|
||||||
|
public void uncaughtException(Thread t, Throwable e) {
|
||||||
|
LOGGER.info("Unhandled exception caught!");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class IllegalArgument {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(IllegalArgument.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(-1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOGGER.error("IllegalArgumentException caught!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class IllegalState {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(IllegalState.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
List<Integer> intList = new ArrayList<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
intList.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator<Integer> intListIterator = intList.iterator(); // Initialized with index at -1
|
||||||
|
|
||||||
|
try {
|
||||||
|
intListIterator.remove(); // IllegalStateException
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
LOGGER.error("IllegalStateException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
class ChildThread extends Thread {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(ChildThread.class);
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOGGER.error("InterruptedException caught!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InterruptedExceptionExample {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
ChildThread childThread = new ChildThread();
|
||||||
|
childThread.start();
|
||||||
|
childThread.interrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class MalformedURL {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(MalformedURL.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
URL baeldungURL = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
baeldungURL = new URL("malformedurl");
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
LOGGER.error("MalformedURLException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class NullPointer {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(NullPointer.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
Person personObj = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
String name = personObj.personName; // Accessing the field of a null object
|
||||||
|
personObj.personName = "Jon Doe"; // Modifying the field of a null object
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
LOGGER.error("NullPointerException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Person {
|
||||||
|
|
||||||
|
public String personName;
|
||||||
|
|
||||||
|
public String getPersonName() {
|
||||||
|
return personName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPersonName(String personName) {
|
||||||
|
this.personName = personName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class NumberFormat {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(NumberFormat.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
String str1 = "100ABCD";
|
||||||
|
|
||||||
|
try {
|
||||||
|
int x = Integer.parseInt(str1); // Converting string with inappropriate format
|
||||||
|
int y = Integer.valueOf(str1);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
LOGGER.error("NumberFormatException caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class ParseExceptionExample {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(ParseExceptionExample.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
DateFormat format = new SimpleDateFormat("MM, dd, yyyy");
|
||||||
|
|
||||||
|
try {
|
||||||
|
format.parse("01, , 2010");
|
||||||
|
} catch (ParseException e) {
|
||||||
|
LOGGER.error("ParseException caught!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class StringIndexOutOfBounds {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(StringIndexOutOfBounds.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
String str = "Hello World";
|
||||||
|
|
||||||
|
try {
|
||||||
|
char charAtNegativeIndex = str.charAt(-1); // Trying to access at negative index
|
||||||
|
char charAtLengthIndex = str.charAt(11); // Trying to access at index equal to size of the string
|
||||||
|
} catch (StringIndexOutOfBoundsException e) {
|
||||||
|
LOGGER.error("StringIndexOutOfBoundsException caught");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
package com.baeldung.gregorian.calendar;
|
||||||
|
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import javax.xml.datatype.DatatypeConfigurationException;
|
||||||
|
import javax.xml.datatype.DatatypeFactory;
|
||||||
|
import javax.xml.datatype.XMLGregorianCalendar;
|
||||||
|
|
||||||
|
public class GregorianCalendarExample {
|
||||||
|
|
||||||
|
|
||||||
|
public Date setMonth(GregorianCalendar calendar, int amount) {
|
||||||
|
calendar.set(Calendar.MONTH, amount);
|
||||||
|
return calendar.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Date rollAdd(GregorianCalendar calendar, int amount) {
|
||||||
|
calendar.roll(GregorianCalendar.MONTH, amount);
|
||||||
|
return calendar.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLeapYearExample(int year) {
|
||||||
|
GregorianCalendar cal = (GregorianCalendar) GregorianCalendar.getInstance();
|
||||||
|
return cal.isLeapYear(year);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Date subtractDays(GregorianCalendar calendar, int daysToSubtract) {
|
||||||
|
GregorianCalendar cal = calendar;
|
||||||
|
cal.add(Calendar.DATE, -daysToSubtract);
|
||||||
|
return cal.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date addDays(GregorianCalendar calendar, int daysToAdd) {
|
||||||
|
GregorianCalendar cal = calendar;
|
||||||
|
cal.add(Calendar.DATE, daysToAdd);
|
||||||
|
return cal.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public XMLGregorianCalendar toXMLGregorianCalendar(GregorianCalendar calendar) throws DatatypeConfigurationException {
|
||||||
|
DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
|
||||||
|
return datatypeFactory.newXMLGregorianCalendar(calendar);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date toDate(XMLGregorianCalendar calendar) {
|
||||||
|
return calendar.toGregorianCalendar()
|
||||||
|
.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compareDates(GregorianCalendar firstDate, GregorianCalendar secondDate) {
|
||||||
|
return firstDate.compareTo(secondDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String formatDate(GregorianCalendar calendar) {
|
||||||
|
return calendar.toZonedDateTime()
|
||||||
|
.format(DateTimeFormatter.ofPattern("d MMM uuuu"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.baeldung.encrypt;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.crypto.KeyGenerator;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
public class FileEncrypterDecrypterIntegrationTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenStringAndFilename_whenEncryptingIntoFile_andDecryptingFileAgain_thenOriginalStringIsReturned() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, InvalidAlgorithmParameterException {
|
||||||
|
String originalContent = "foobar";
|
||||||
|
SecretKey secretKey = KeyGenerator.getInstance("AES").generateKey();
|
||||||
|
|
||||||
|
FileEncrypterDecrypter fileEncrypterDecrypter = new FileEncrypterDecrypter(secretKey, "AES/CBC/PKCS5Padding");
|
||||||
|
fileEncrypterDecrypter.encrypt(originalContent, "baz.enc");
|
||||||
|
|
||||||
|
String decryptedContent = fileEncrypterDecrypter.decrypt("baz.enc");
|
||||||
|
assertThat(decryptedContent, is(originalContent));
|
||||||
|
|
||||||
|
new File("baz.enc").delete(); // cleanup
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
package com.baeldung.exceptions;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Captor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import ch.qos.logback.classic.Level;
|
||||||
|
import ch.qos.logback.classic.Logger;
|
||||||
|
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||||
|
import ch.qos.logback.classic.spi.LoggingEvent;
|
||||||
|
import ch.qos.logback.core.Appender;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class GlobalExceptionHandlerUnitTest {
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private Appender<ILoggingEvent> mockAppender;
|
||||||
|
|
||||||
|
@Captor
|
||||||
|
private ArgumentCaptor<LoggingEvent> captorLoggingEvent;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||||
|
logger.addAppender(mockAppender);
|
||||||
|
|
||||||
|
Handler globalExceptionHandler = new Handler();
|
||||||
|
Thread.setDefaultUncaughtExceptionHandler(globalExceptionHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void teardown() {
|
||||||
|
final Logger logger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||||
|
logger.detachAppender(mockAppender);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenArithmeticException_thenUseUncaughtExceptionHandler() throws InterruptedException {
|
||||||
|
|
||||||
|
Thread globalExceptionHandlerThread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
GlobalExceptionHandler globalExceptionHandlerObj = new GlobalExceptionHandler();
|
||||||
|
globalExceptionHandlerObj.performArithmeticOperation(99, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
globalExceptionHandlerThread.start();
|
||||||
|
globalExceptionHandlerThread.join();
|
||||||
|
|
||||||
|
verify(mockAppender).doAppend(captorLoggingEvent.capture());
|
||||||
|
LoggingEvent loggingEvent = captorLoggingEvent.getValue();
|
||||||
|
|
||||||
|
assertThat(loggingEvent.getLevel()).isEqualTo(Level.INFO);
|
||||||
|
assertThat(loggingEvent.getFormattedMessage()).isEqualTo("Unhandled exception caught!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,228 @@
|
|||||||
|
package com.baeldung.gregorian.calendar;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import javax.xml.datatype.DatatypeConfigurationException;
|
||||||
|
import javax.xml.datatype.DatatypeFactory;
|
||||||
|
import javax.xml.datatype.XMLGregorianCalendar;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.baeldung.gregorian.calendar.GregorianCalendarExample;
|
||||||
|
|
||||||
|
public class GregorianCalendarTester {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Calendar_Return_Type_Valid() {
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
assert ("gregory".equals(calendar.getCalendarType()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Calendar_Return_Type_InValid() {
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
assertNotEquals("gregorys", calendar.getCalendarType());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = ClassCastException.class)
|
||||||
|
public void test_Class_Cast_Exception() {
|
||||||
|
TimeZone tz = TimeZone.getTimeZone("GMT+9:00");
|
||||||
|
Locale loc = new Locale("ja", "JP", "JP");
|
||||||
|
Calendar calendar = Calendar.getInstance(loc);
|
||||||
|
GregorianCalendar gc = (GregorianCalendar) calendar;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Getting_Calendar_information() {
|
||||||
|
GregorianCalendar calendar = new GregorianCalendar(2018, 5, 28);
|
||||||
|
assertTrue(false == calendar.isLeapYear(calendar.YEAR));
|
||||||
|
assertTrue(52 == calendar.getWeeksInWeekYear());
|
||||||
|
assertTrue(2018 == calendar.getWeekYear());
|
||||||
|
assertTrue(30 == calendar.getActualMaximum(calendar.DAY_OF_MONTH));
|
||||||
|
assertTrue(1 == calendar.getActualMinimum(calendar.DAY_OF_MONTH));
|
||||||
|
assertTrue(1 == calendar.getGreatestMinimum(calendar.DAY_OF_MONTH));
|
||||||
|
assertTrue(28 == calendar.getLeastMaximum(calendar.DAY_OF_MONTH));
|
||||||
|
assertTrue(31 == calendar.getMaximum(calendar.DAY_OF_MONTH));
|
||||||
|
assertTrue(1 == calendar.getMinimum(calendar.DAY_OF_MONTH));
|
||||||
|
assertTrue(52 == calendar.getWeeksInWeekYear());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Compare_Date_FirstDate_Greater_SecondDate() {
|
||||||
|
GregorianCalendar firstDate = new GregorianCalendar(2018, 6, 28);
|
||||||
|
GregorianCalendar secondDate = new GregorianCalendar(2018, 5, 28);
|
||||||
|
assertTrue(1 == firstDate.compareTo(secondDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Compare_Date_FirstDate_Smaller_SecondDate() {
|
||||||
|
GregorianCalendar firstDate = new GregorianCalendar(2018, 5, 28);
|
||||||
|
GregorianCalendar secondDate = new GregorianCalendar(2018, 6, 28);
|
||||||
|
assertTrue(-1 == firstDate.compareTo(secondDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Compare_Date_Both_Dates_Equal() {
|
||||||
|
GregorianCalendar firstDate = new GregorianCalendar(2018, 6, 28);
|
||||||
|
GregorianCalendar secondDate = new GregorianCalendar(2018, 6, 28);
|
||||||
|
assertTrue(0 == firstDate.compareTo(secondDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_date_format() {
|
||||||
|
GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
|
||||||
|
GregorianCalendar calendar = new GregorianCalendar(2018, 6, 28);
|
||||||
|
assertEquals("28 Jul 2018", calendarDemo.formatDate(calendar));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_dateFormatdMMMuuuu() {
|
||||||
|
String expectedDate = new GregorianCalendar(2018, 6, 28).toZonedDateTime()
|
||||||
|
.format(DateTimeFormatter.ofPattern("d MMM uuuu"));
|
||||||
|
assertEquals("28 Jul 2018", expectedDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_addDays() {
|
||||||
|
GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
|
||||||
|
GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
|
||||||
|
GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
|
||||||
|
calendarExpected.add(Calendar.DATE, 1);
|
||||||
|
Date expectedDate = calendarExpected.getTime();
|
||||||
|
assertEquals(expectedDate, calendarDemo.addDays(calendarActual, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_whenAddOneDay_thenMonthIsChanged() {
|
||||||
|
final int finalDay1 = 1;
|
||||||
|
final int finalMonthJul = 6;
|
||||||
|
GregorianCalendar calendarExpected = new GregorianCalendar(2018, 5, 30);
|
||||||
|
calendarExpected.add(Calendar.DATE, 1);
|
||||||
|
System.out.println(calendarExpected.getTime());
|
||||||
|
assertEquals(calendarExpected.get(Calendar.DATE), finalDay1);
|
||||||
|
assertEquals(calendarExpected.get(Calendar.MONTH), finalMonthJul);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_whenSubtractOneDay_thenMonthIsChanged() {
|
||||||
|
final int finalDay31 = 31;
|
||||||
|
final int finalMonthMay = 4;
|
||||||
|
GregorianCalendar calendarExpected = new GregorianCalendar(2018, 5, 1);
|
||||||
|
calendarExpected.add(Calendar.DATE, -1);
|
||||||
|
assertEquals(calendarExpected.get(Calendar.DATE), finalDay31);
|
||||||
|
assertEquals(calendarExpected.get(Calendar.MONTH), finalMonthMay);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_subDays() {
|
||||||
|
GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
|
||||||
|
GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
|
||||||
|
GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
|
||||||
|
calendarExpected.add(Calendar.DATE, -1);
|
||||||
|
Date expectedDate = calendarExpected.getTime();
|
||||||
|
assertEquals(expectedDate, calendarDemo.subtractDays(calendarActual, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_rollAdd() {
|
||||||
|
GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
|
||||||
|
GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
|
||||||
|
GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
|
||||||
|
calendarExpected.roll(Calendar.MONTH, 8);
|
||||||
|
Date expectedDate = calendarExpected.getTime();
|
||||||
|
assertEquals(expectedDate, calendarDemo.rollAdd(calendarActual, 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_whenRollUpOneMonth_thenYearIsUnchanged() {
|
||||||
|
final int rolledUpMonthJuly = 7, orginalYear2018 = 2018;
|
||||||
|
GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
|
||||||
|
calendarExpected.roll(Calendar.MONTH, 1);
|
||||||
|
assertEquals(calendarExpected.get(Calendar.MONTH), rolledUpMonthJuly);
|
||||||
|
assertEquals(calendarExpected.get(Calendar.YEAR), orginalYear2018);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_whenRollDownOneMonth_thenYearIsUnchanged() {
|
||||||
|
final int rolledDownMonthJune = 5, orginalYear2018 = 2018;
|
||||||
|
GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
|
||||||
|
calendarExpected.roll(Calendar.MONTH, -1);
|
||||||
|
assertEquals(calendarExpected.get(Calendar.MONTH), rolledDownMonthJune);
|
||||||
|
assertEquals(calendarExpected.get(Calendar.YEAR), orginalYear2018);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_rollSubtract() {
|
||||||
|
GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
|
||||||
|
GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
|
||||||
|
GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
|
||||||
|
calendarExpected.roll(Calendar.MONTH, -8);
|
||||||
|
Date expectedDate = calendarExpected.getTime();
|
||||||
|
assertEquals(expectedDate, calendarDemo.rollAdd(calendarActual, -8));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_setMonth() {
|
||||||
|
GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
|
||||||
|
GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
|
||||||
|
GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
|
||||||
|
calendarExpected.set(Calendar.MONTH, 3);
|
||||||
|
Date expectedDate = calendarExpected.getTime();
|
||||||
|
assertEquals(expectedDate, calendarDemo.setMonth(calendarActual, 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_setMonthApril() {
|
||||||
|
final int setMonthApril = 3, orginalYear2018 = 2018, originalDate28 = 28;
|
||||||
|
GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
|
||||||
|
calendarExpected.set(Calendar.MONTH, 3);
|
||||||
|
assertEquals(calendarExpected.get(Calendar.MONTH), setMonthApril);
|
||||||
|
assertEquals(calendarExpected.get(Calendar.YEAR), orginalYear2018);
|
||||||
|
assertEquals(calendarExpected.get(Calendar.DATE), originalDate28);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_toXMLGregorianCalendar() throws DatatypeConfigurationException {
|
||||||
|
GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
|
||||||
|
DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
|
||||||
|
GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
|
||||||
|
GregorianCalendar calendarExpected = new GregorianCalendar(2018, 6, 28);
|
||||||
|
XMLGregorianCalendar expectedXMLGregorianCalendar = datatypeFactory
|
||||||
|
.newXMLGregorianCalendar(calendarExpected);
|
||||||
|
assertEquals(expectedXMLGregorianCalendar,
|
||||||
|
calendarDemo.toXMLGregorianCalendar(calendarActual));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_isLeapYear_True() {
|
||||||
|
GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
|
||||||
|
assertEquals(true, calendarDemo.isLeapYearExample(2016));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_isLeapYear_False() {
|
||||||
|
GregorianCalendarExample calendarDemo = new GregorianCalendarExample();
|
||||||
|
assertEquals(false, calendarDemo.isLeapYearExample(2018));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_toDate() throws DatatypeConfigurationException {
|
||||||
|
GregorianCalendar calendarActual = new GregorianCalendar(2018, 6, 28);
|
||||||
|
DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
|
||||||
|
XMLGregorianCalendar expectedXMLGregorianCalendar = datatypeFactory
|
||||||
|
.newXMLGregorianCalendar(calendarActual);
|
||||||
|
expectedXMLGregorianCalendar.toGregorianCalendar().getTime();
|
||||||
|
assertEquals(calendarActual.getTime(),
|
||||||
|
expectedXMLGregorianCalendar.toGregorianCalendar().getTime() );
|
||||||
|
}
|
||||||
|
}
|
@ -32,3 +32,4 @@
|
|||||||
- [Processing JSON with Kotlin and Klaxson](http://www.baeldung.com/kotlin-json-klaxson)
|
- [Processing JSON with Kotlin and Klaxson](http://www.baeldung.com/kotlin-json-klaxson)
|
||||||
- [Kotlin String Templates](http://www.baeldung.com/kotlin-string-template)
|
- [Kotlin String Templates](http://www.baeldung.com/kotlin-string-template)
|
||||||
- [Java EE 8 Security API](http://www.baeldung.com/java-ee-8-security)
|
- [Java EE 8 Security API](http://www.baeldung.com/java-ee-8-security)
|
||||||
|
- [Kotlin with Ktor](http://www.baeldung.com/kotlin-ktor)
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package com.baeldung.trie;
|
package com.baeldung.trie;
|
||||||
|
|
||||||
public class Trie {
|
class Trie {
|
||||||
private TrieNode root;
|
private TrieNode root;
|
||||||
|
|
||||||
Trie() {
|
Trie() {
|
||||||
root = new TrieNode();
|
root = new TrieNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void insert(String word) {
|
void insert(String word) {
|
||||||
TrieNode current = root;
|
TrieNode current = root;
|
||||||
|
|
||||||
for (int i = 0; i < word.length(); i++) {
|
for (int i = 0; i < word.length(); i++) {
|
||||||
@ -16,11 +16,11 @@ public class Trie {
|
|||||||
current.setEndOfWord(true);
|
current.setEndOfWord(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean delete(String word) {
|
boolean delete(String word) {
|
||||||
return delete(root, word, 0);
|
return delete(root, word, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean containsNode(String word) {
|
boolean containsNode(String word) {
|
||||||
TrieNode current = root;
|
TrieNode current = root;
|
||||||
|
|
||||||
for (int i = 0; i < word.length(); i++) {
|
for (int i = 0; i < word.length(); i++) {
|
||||||
@ -34,7 +34,7 @@ public class Trie {
|
|||||||
return current.isEndOfWord();
|
return current.isEndOfWord();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEmpty() {
|
boolean isEmpty() {
|
||||||
return root == null;
|
return root == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ public class Trie {
|
|||||||
if (node == null) {
|
if (node == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean shouldDeleteCurrentNode = delete(node, word, index + 1);
|
boolean shouldDeleteCurrentNode = delete(node, word, index + 1) && !node.isEndOfWord();
|
||||||
|
|
||||||
if (shouldDeleteCurrentNode) {
|
if (shouldDeleteCurrentNode) {
|
||||||
current.getChildren().remove(ch);
|
current.getChildren().remove(ch);
|
||||||
|
@ -4,28 +4,18 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
class TrieNode {
|
class TrieNode {
|
||||||
private Map<Character, TrieNode> children;
|
private final Map<Character, TrieNode> children = new HashMap<>();
|
||||||
private boolean endOfWord;
|
private boolean endOfWord;
|
||||||
|
|
||||||
public TrieNode() {
|
Map<Character, TrieNode> getChildren() {
|
||||||
children = new HashMap<>();
|
|
||||||
endOfWord = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Character, TrieNode> getChildren() {
|
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setChildren(Map<Character, TrieNode> children) {
|
boolean isEndOfWord() {
|
||||||
this.children = children;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEndOfWord() {
|
|
||||||
return endOfWord;
|
return endOfWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEndOfWord(boolean endOfWord) {
|
void setEndOfWord(boolean endOfWord) {
|
||||||
this.endOfWord = endOfWord;
|
this.endOfWord = endOfWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package com.baeldung.trie;
|
package com.baeldung.trie;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
@ -53,6 +54,19 @@ public class TrieTest {
|
|||||||
assertFalse(trie.containsNode("Programming"));
|
assertFalse(trie.containsNode("Programming"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenATrie_whenDeletingOverlappingElements_thenDontDeleteSubElement() {
|
||||||
|
|
||||||
|
Trie trie1 = new Trie();
|
||||||
|
|
||||||
|
trie1.insert("pie");
|
||||||
|
trie1.insert("pies");
|
||||||
|
|
||||||
|
trie1.delete("pies");
|
||||||
|
|
||||||
|
Assertions.assertTrue(trie1.containsNode("pie"));
|
||||||
|
}
|
||||||
|
|
||||||
private Trie createExampleTrie() {
|
private Trie createExampleTrie() {
|
||||||
Trie trie = new Trie();
|
Trie trie = new Trie();
|
||||||
|
|
||||||
|
@ -6,42 +6,12 @@
|
|||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<name>ethereum</name>
|
<name>ethereum</name>
|
||||||
|
|
||||||
<!-- Don't Use This - Use the BOM or direct dependency rather than parent -->
|
<parent>
|
||||||
<!--<parent>
|
<artifactId>parent-spring-5</artifactId>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<version>1.5.6.RELEASE</version>
|
<relativePath>../parent-spring-5</relativePath>
|
||||||
</parent>-->
|
</parent>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
<java.version>1.8</java.version>
|
|
||||||
<tomcat.version>8.5.4</tomcat.version>
|
|
||||||
<ethereumj-core.version>1.5.0-RELEASE</ethereumj-core.version>
|
|
||||||
<web3j.core.version>3.3.1</web3j.core.version>
|
|
||||||
<springframework.version>5.0.5.RELEASE</springframework.version>
|
|
||||||
<spring.boot.version>1.5.6.RELEASE</spring.boot.version>
|
|
||||||
<maven-surefire.version>2.18.1</maven-surefire.version>
|
|
||||||
<mockito.version>1.10.19</mockito.version>
|
|
||||||
<jackson-databind.version>2.5.0</jackson-databind.version>
|
|
||||||
<hamcrest.version>1.3</hamcrest.version>
|
|
||||||
<jackson.version>2.9.3</jackson.version>
|
|
||||||
<javax-jsp.version>2.3.1</javax-jsp.version>
|
|
||||||
<javax-servlet.version>3.1.0</javax-servlet.version>
|
|
||||||
<jsonpath.version>2.4.0</jsonpath.version>
|
|
||||||
<jstl.version>1.2</jstl.version>
|
|
||||||
<junit.version>4.12</junit.version>
|
|
||||||
<logback.version>1.2.3</logback.version>
|
|
||||||
<slf4j.version>1.7.25</slf4j.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>Ethereum</id>
|
|
||||||
<name>Ethereum</name>
|
|
||||||
<url>https://dl.bintray.com/ethereum/maven/</url>
|
|
||||||
</repository>
|
|
||||||
</repositories>
|
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
@ -199,7 +169,9 @@
|
|||||||
<version>${jsonpath.version}</version>
|
<version>${jsonpath.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
<finalName>ethereum</finalName>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
@ -222,21 +194,36 @@
|
|||||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<version>${maven-surefire.version}</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>install</id>
|
|
||||||
<phase>install</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>test</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
<finalName>ethereum</finalName>
|
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>Ethereum</id>
|
||||||
|
<name>Ethereum</name>
|
||||||
|
<url>https://dl.bintray.com/ethereum/maven/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<tomcat.version>8.5.4</tomcat.version>
|
||||||
|
<ethereumj-core.version>1.5.0-RELEASE</ethereumj-core.version>
|
||||||
|
<web3j.core.version>3.3.1</web3j.core.version>
|
||||||
|
<springframework.version>5.0.5.RELEASE</springframework.version>
|
||||||
|
<spring.boot.version>1.5.6.RELEASE</spring.boot.version>
|
||||||
|
<mockito.version>1.10.19</mockito.version>
|
||||||
|
<jackson-databind.version>2.5.0</jackson-databind.version>
|
||||||
|
<hamcrest.version>1.3</hamcrest.version>
|
||||||
|
<jackson.version>2.9.3</jackson.version>
|
||||||
|
<javax-jsp.version>2.3.1</javax-jsp.version>
|
||||||
|
<javax-servlet.version>3.1.0</javax-servlet.version>
|
||||||
|
<jsonpath.version>2.4.0</jsonpath.version>
|
||||||
|
<jstl.version>1.2</jstl.version>
|
||||||
|
<junit.version>4.12</junit.version>
|
||||||
|
<logback.version>1.2.3</logback.version>
|
||||||
|
<slf4j.version>1.7.25</slf4j.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<groupId>com.baeldung.javax-servlet-init-params</groupId>
|
|
||||||
<artifactId>javax-servlet-init-params</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>parent-modules</artifactId>
|
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<version>4.12</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.assertj</groupId>
|
|
||||||
<artifactId>assertj-core</artifactId>
|
|
||||||
<version>3.9.1</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hamcrest</groupId>
|
|
||||||
<artifactId>hamcrest-core</artifactId>
|
|
||||||
<version>1.3</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mockito</groupId>
|
|
||||||
<artifactId>mockito-core</artifactId>
|
|
||||||
<version>2.18.3</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax</groupId>
|
|
||||||
<artifactId>javaee-web-api</artifactId>
|
|
||||||
<version>7.0</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>jstl</groupId>
|
|
||||||
<artifactId>jstl</artifactId>
|
|
||||||
<version>1.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>javax.el</groupId>
|
|
||||||
<artifactId>el-api</artifactId>
|
|
||||||
<version>2.2</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
|
||||||
version="3.1">
|
|
||||||
<context-param>
|
|
||||||
<param-name>province</param-name>
|
|
||||||
<param-value>Mendoza</param-value>
|
|
||||||
</context-param>
|
|
||||||
<context-param>
|
|
||||||
<param-name>country</param-name>
|
|
||||||
<param-value>Argentina</param-value>
|
|
||||||
</context-param>
|
|
||||||
</web-app>
|
|
@ -2,16 +2,41 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.baeldung.javax-servlets</groupId>
|
||||||
<artifactId>javax-servlets</artifactId>
|
<artifactId>javax-servlets</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>war</packaging>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.assertj</groupId>
|
||||||
|
<artifactId>assertj-core</artifactId>
|
||||||
|
<version>3.9.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest-core</artifactId>
|
||||||
|
<version>1.3</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<version>2.18.3</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- File Uploading -->
|
<!-- File Uploading -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-fileupload</groupId>
|
<groupId>commons-fileupload</groupId>
|
||||||
@ -70,8 +95,8 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
<javax.servlet.version>3.1.0</javax.servlet.version>
|
||||||
<org.apache.httpcomponents.version>4.5.3</org.apache.httpcomponents.version>
|
<org.apache.httpcomponents.version>4.5.3</org.apache.httpcomponents.version>
|
||||||
<spring-test.version>5.0.5.RELEASE</spring-test.version>
|
<spring-test.version>5.0.5.RELEASE</spring-test.version>
|
||||||
<gson.version>2.8.2</gson.version>
|
<gson.version>2.8.2</gson.version>
|
||||||
|
@ -1,9 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
|
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
|
||||||
http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd"
|
http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd"
|
||||||
version="3.1">
|
version="3.1">
|
||||||
|
<context-param>
|
||||||
|
<param-name>province</param-name>
|
||||||
|
<param-value>Mendoza</param-value>
|
||||||
|
</context-param>
|
||||||
|
<context-param>
|
||||||
|
<param-name>country</param-name>
|
||||||
|
<param-value>Argentina</param-value>
|
||||||
|
</context-param>
|
||||||
<error-page>
|
<error-page>
|
||||||
<error-code>404</error-code>
|
<error-code>404</error-code>
|
||||||
<location>/error-404.html</location> <!-- /src/main/webapp/error-404.html-->
|
<location>/error-404.html</location> <!-- /src/main/webapp/error-404.html-->
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Context and Initialization Servlet Parameters</title>
|
<title>Context and Servlet Initialization Parameters</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
@ -1,4 +1,4 @@
|
|||||||
package com.baeldung.test;
|
package com.baeldung.servlets;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
@ -705,6 +705,37 @@
|
|||||||
<version>${jctools.version}</version>
|
<version>${jctools.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- resilience4j -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.resilience4j</groupId>
|
||||||
|
<artifactId>resilience4j-circuitbreaker</artifactId>
|
||||||
|
<version>${resilience4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.resilience4j</groupId>
|
||||||
|
<artifactId>resilience4j-ratelimiter</artifactId>
|
||||||
|
<version>${resilience4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.resilience4j</groupId>
|
||||||
|
<artifactId>resilience4j-bulkhead</artifactId>
|
||||||
|
<version>${resilience4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.resilience4j</groupId>
|
||||||
|
<artifactId>resilience4j-retry</artifactId>
|
||||||
|
<version>${resilience4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.resilience4j</groupId>
|
||||||
|
<artifactId>resilience4j-cache</artifactId>
|
||||||
|
<version>${resilience4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.resilience4j</groupId>
|
||||||
|
<artifactId>resilience4j-timelimiter</artifactId>
|
||||||
|
<version>${resilience4j.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-math3</artifactId>
|
<artifactId>commons-math3</artifactId>
|
||||||
@ -951,6 +982,7 @@
|
|||||||
<jets3t-version>0.9.4.0006L</jets3t-version>
|
<jets3t-version>0.9.4.0006L</jets3t-version>
|
||||||
<jctools.version>2.1.2</jctools.version>
|
<jctools.version>2.1.2</jctools.version>
|
||||||
<typesafe-akka.version>2.5.11</typesafe-akka.version>
|
<typesafe-akka.version>2.5.11</typesafe-akka.version>
|
||||||
|
<resilience4j.version>0.12.1</resilience4j.version>
|
||||||
<common-math3-version>3.6.1</common-math3-version>
|
<common-math3-version>3.6.1</common-math3-version>
|
||||||
<xchart-version>3.5.2</xchart-version>
|
<xchart-version>3.5.2</xchart-version>
|
||||||
<commons-net.version>3.6</commons-net.version>
|
<commons-net.version>3.6</commons-net.version>
|
||||||
|
@ -0,0 +1,126 @@
|
|||||||
|
package com.baeldung.resilience4j;
|
||||||
|
|
||||||
|
import io.github.resilience4j.bulkhead.Bulkhead;
|
||||||
|
import io.github.resilience4j.bulkhead.BulkheadConfig;
|
||||||
|
import io.github.resilience4j.bulkhead.BulkheadRegistry;
|
||||||
|
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
|
||||||
|
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
|
||||||
|
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
|
||||||
|
import io.github.resilience4j.retry.Retry;
|
||||||
|
import io.github.resilience4j.retry.RetryConfig;
|
||||||
|
import io.github.resilience4j.retry.RetryRegistry;
|
||||||
|
import io.github.resilience4j.timelimiter.TimeLimiter;
|
||||||
|
import io.github.resilience4j.timelimiter.TimeLimiterConfig;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.Mockito.*;
|
||||||
|
|
||||||
|
public class Resilience4jUnitTest {
|
||||||
|
|
||||||
|
interface RemoteService {
|
||||||
|
|
||||||
|
int process(int i);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RemoteService service;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
service = mock(RemoteService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenCircuitBreakerIsUsed_thenItWorksAsExpected() {
|
||||||
|
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
|
||||||
|
// Percentage of failures to start short-circuit
|
||||||
|
.failureRateThreshold(20)
|
||||||
|
// Min number of call attempts
|
||||||
|
.ringBufferSizeInClosedState(5)
|
||||||
|
.build();
|
||||||
|
CircuitBreakerRegistry registry = CircuitBreakerRegistry.of(config);
|
||||||
|
CircuitBreaker circuitBreaker = registry.circuitBreaker("my");
|
||||||
|
Function<Integer, Integer> decorated = CircuitBreaker.decorateFunction(circuitBreaker, service::process);
|
||||||
|
|
||||||
|
when(service.process(anyInt())).thenThrow(new RuntimeException());
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
try {
|
||||||
|
decorated.apply(i);
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
verify(service, times(5)).process(any(Integer.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenBulkheadIsUsed_thenItWorksAsExpected() throws InterruptedException {
|
||||||
|
BulkheadConfig config = BulkheadConfig.custom().maxConcurrentCalls(1).build();
|
||||||
|
BulkheadRegistry registry = BulkheadRegistry.of(config);
|
||||||
|
Bulkhead bulkhead = registry.bulkhead("my");
|
||||||
|
Function<Integer, Integer> decorated = Bulkhead.decorateFunction(bulkhead, service::process);
|
||||||
|
|
||||||
|
Future<?> taskInProgress = callAndBlock(decorated);
|
||||||
|
try {
|
||||||
|
assertThat(bulkhead.isCallPermitted()).isFalse();
|
||||||
|
} finally {
|
||||||
|
taskInProgress.cancel(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Future<?> callAndBlock(Function<Integer, Integer> decoratedService) throws InterruptedException {
|
||||||
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
when(service.process(anyInt())).thenAnswer(invocation -> {
|
||||||
|
latch.countDown();
|
||||||
|
Thread.currentThread().join();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
ForkJoinTask<?> result = ForkJoinPool.commonPool().submit(() -> {
|
||||||
|
decoratedService.apply(1);
|
||||||
|
});
|
||||||
|
latch.await();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRetryIsUsed_thenItWorksAsExpected() {
|
||||||
|
RetryConfig config = RetryConfig.custom().maxAttempts(2).build();
|
||||||
|
RetryRegistry registry = RetryRegistry.of(config);
|
||||||
|
Retry retry = registry.retry("my");
|
||||||
|
Function<Integer, Void> decorated = Retry.decorateFunction(retry, (Integer s) -> {
|
||||||
|
service.process(s);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
when(service.process(anyInt())).thenThrow(new RuntimeException());
|
||||||
|
try {
|
||||||
|
decorated.apply(1);
|
||||||
|
fail("Expected an exception to be thrown if all retries failed");
|
||||||
|
} catch (Exception e) {
|
||||||
|
verify(service, times(2)).process(any(Integer.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Test
|
||||||
|
public void whenTimeLimiterIsUsed_thenItWorksAsExpected() throws Exception {
|
||||||
|
long ttl = 1;
|
||||||
|
TimeLimiterConfig config = TimeLimiterConfig.custom().timeoutDuration(Duration.ofMillis(ttl)).build();
|
||||||
|
TimeLimiter timeLimiter = TimeLimiter.of(config);
|
||||||
|
|
||||||
|
Future futureMock = mock(Future.class);
|
||||||
|
Callable restrictedCall = TimeLimiter.decorateFutureSupplier(timeLimiter, () -> futureMock);
|
||||||
|
restrictedCall.call();
|
||||||
|
|
||||||
|
verify(futureMock).get(ttl, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
}
|
57
meecrowave/pom.xml
Normal file
57
meecrowave/pom.xml
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>apache-meecrowave</artifactId>
|
||||||
|
<version>0.0.1</version>
|
||||||
|
<name>apache-meecrowave</name>
|
||||||
|
<description>A sample REST API application with Meecrowave</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.apache.meecrowave/meecrowave-core -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.meecrowave</groupId>
|
||||||
|
<artifactId>meecrowave-core</artifactId>
|
||||||
|
<version>1.2.1</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.apache.meecrowave/meecrowave-jpa -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.meecrowave</groupId>
|
||||||
|
<artifactId>meecrowave-jpa</artifactId>
|
||||||
|
<version>1.2.1</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>3.10.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.meecrowave</groupId>
|
||||||
|
<artifactId>meecrowave-junit</artifactId>
|
||||||
|
<version>1.2.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- https://mvnrepository.com/artifact/junit/junit -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.10</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.meecrowave</groupId>
|
||||||
|
<artifactId>meecrowave-maven-plugin</artifactId>
|
||||||
|
<version>1.2.1</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.baeldung.meecrowave;
|
||||||
|
|
||||||
|
public class Article {
|
||||||
|
private String name;
|
||||||
|
private String author;
|
||||||
|
|
||||||
|
public Article() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Article(String name, String author) {
|
||||||
|
this.author = author;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthor(String author) {
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.baeldung.meecrowave;
|
||||||
|
|
||||||
|
import javax.enterprise.context.RequestScoped;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
|
@RequestScoped
|
||||||
|
@Path("article")
|
||||||
|
public class ArticleEndpoints {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ArticleService articleService;
|
||||||
|
|
||||||
|
@GET
|
||||||
|
public Response getArticle() {
|
||||||
|
return Response.ok()
|
||||||
|
.entity(new Article("name", "author"))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@POST
|
||||||
|
public Response createArticle(Article article) {
|
||||||
|
return Response.status(Status.CREATED)
|
||||||
|
.entity(articleService.createArticle(article))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.baeldung.meecrowave;
|
||||||
|
|
||||||
|
import javax.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ArticleService {
|
||||||
|
public Article createArticle(Article article) {
|
||||||
|
return article;
|
||||||
|
}
|
||||||
|
}
|
16
meecrowave/src/main/java/com/baeldung/meecrowave/Server.java
Normal file
16
meecrowave/src/main/java/com/baeldung/meecrowave/Server.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package com.baeldung.meecrowave;
|
||||||
|
|
||||||
|
import org.apache.meecrowave.Meecrowave;
|
||||||
|
|
||||||
|
public class Server {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
final Meecrowave.Builder builder = new Meecrowave.Builder();
|
||||||
|
builder.setScanningPackageIncludes("com.baeldung.meecrowave");
|
||||||
|
builder.setJaxrsMapping("/api/*");
|
||||||
|
builder.setJsonpPrettify(true);
|
||||||
|
|
||||||
|
try (Meecrowave meecrowave = new Meecrowave(builder)) {
|
||||||
|
meecrowave.bake().await();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package com.baeldung.meecrowave;
|
||||||
|
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.apache.meecrowave.Meecrowave;
|
||||||
|
import org.apache.meecrowave.junit.MonoMeecrowave;
|
||||||
|
import org.apache.meecrowave.testing.ConfigurationInject;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.Request;
|
||||||
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
@RunWith(MonoMeecrowave.Runner.class)
|
||||||
|
public class ArticleEndpointsTest {
|
||||||
|
|
||||||
|
@ConfigurationInject
|
||||||
|
private Meecrowave.Builder config;
|
||||||
|
private static OkHttpClient client;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setup() {
|
||||||
|
client = new OkHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRetunedArticle_thenCorrect() throws IOException {
|
||||||
|
final String base = "http://localhost:"+config.getHttpPort();
|
||||||
|
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(base+"/article")
|
||||||
|
.build();
|
||||||
|
Response response = client.newCall(request).execute();
|
||||||
|
assertEquals(200, response.code());
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,7 @@ import static org.junit.Assert.assertEquals;
|
|||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
public class ArticleRepositoryIntegrationTest {
|
public class ArticleRepositoryLiveTest {
|
||||||
|
|
||||||
private static final String TABLE_NAME = "articles";
|
private static final String TABLE_NAME = "articles";
|
||||||
|
|
32
persistence-modules/java-jpa/pom.xml
Normal file
32
persistence-modules/java-jpa/pom.xml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?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">
|
||||||
|
<parent>
|
||||||
|
<artifactId>parent-modules</artifactId>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>java-jpa</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate</groupId>
|
||||||
|
<artifactId>hibernate-core</artifactId>
|
||||||
|
<version>${hibernate.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.h2database</groupId>
|
||||||
|
<artifactId>h2</artifactId>
|
||||||
|
<version>${h2.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<hibernate.version>5.3.1.Final</hibernate.version>
|
||||||
|
<h2.version>1.4.197</h2.version>
|
||||||
|
</properties>
|
||||||
|
</project>
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.baeldung.sqlresultsetmapping;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
|
||||||
|
@SqlResultSetMapping(
|
||||||
|
name="EmployeeResult",
|
||||||
|
entities={
|
||||||
|
@EntityResult(
|
||||||
|
entityClass = com.baeldung.sqlresultsetmapping.Employee.class,
|
||||||
|
fields={@FieldResult(name="id",column="employeeNumber"),
|
||||||
|
@FieldResult(name="name", column="name")}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@NamedNativeQuery(
|
||||||
|
name="Employees",
|
||||||
|
query="SELECT id as employeeNumber, name FROM EMPLOYEE",
|
||||||
|
resultSetMapping = "EmployeeResult"
|
||||||
|
)
|
||||||
|
@Entity
|
||||||
|
public class Employee {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
package com.baeldung.sqlresultsetmapping;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
|
||||||
|
@SqlResultSetMappings(value = {
|
||||||
|
@SqlResultSetMapping(name = "ScheduleResult",
|
||||||
|
classes = { @ConstructorResult(targetClass = com.baeldung.sqlresultsetmapping.ScheduledDay.class,
|
||||||
|
columns = { @ColumnResult(name = "id", type = Long.class),
|
||||||
|
@ColumnResult(name = "employeeId", type = Long.class),
|
||||||
|
@ColumnResult(name = "hourIn"),
|
||||||
|
@ColumnResult(name = "hourOut"),
|
||||||
|
@ColumnResult(name = "dayOfWeek") }) }),
|
||||||
|
@SqlResultSetMapping(name = "FridayEmployeeResult",
|
||||||
|
columns = { @ColumnResult(name = "employeeId") }),
|
||||||
|
@SqlResultSetMapping(name = "EmployeeScheduleResults",
|
||||||
|
entities = { @EntityResult(entityClass = com.baeldung.sqlresultsetmapping.Employee.class),
|
||||||
|
@EntityResult(entityClass = com.baeldung.sqlresultsetmapping.ScheduledDay.class)
|
||||||
|
}) })
|
||||||
|
@NamedNativeQuery(name = "FridayEmployees",
|
||||||
|
query = "SELECT employeeId FROM schedule_days WHERE dayOfWeek = 'FRIDAY'",
|
||||||
|
resultSetMapping = "FridayEmployeeResult")
|
||||||
|
|
||||||
|
@NamedNativeQuery(name = "Schedules",
|
||||||
|
query = "SELECT * FROM schedule_days WHERE hourIn = 8",
|
||||||
|
resultSetMapping = "ScheduleResult")
|
||||||
|
@Entity
|
||||||
|
@Table(name = "SCHEDULE_DAYS")
|
||||||
|
public class ScheduledDay {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
private Long employeeId;
|
||||||
|
private Integer hourIn;
|
||||||
|
private Integer hourOut;
|
||||||
|
private String dayOfWeek;
|
||||||
|
|
||||||
|
public ScheduledDay() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ScheduledDay(Long id, Long employeeId, Integer hourIn, Integer hourOut, String dayofWeek) {
|
||||||
|
this.id = id;
|
||||||
|
this.employeeId = employeeId;
|
||||||
|
this.hourIn = hourIn;
|
||||||
|
this.hourOut = hourOut;
|
||||||
|
this.dayOfWeek = dayofWeek;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getEmployeeId() {
|
||||||
|
return employeeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmployeeId(Long employeeId) {
|
||||||
|
this.employeeId = employeeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getHourIn() {
|
||||||
|
return hourIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHourIn(Integer hourIn) {
|
||||||
|
this.hourIn = hourIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getHourOut() {
|
||||||
|
return hourOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHourOut(Integer hourOut) {
|
||||||
|
this.hourOut = hourOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDayOfWeek() {
|
||||||
|
return dayOfWeek;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDayOfWeek(String dayOfWeek) {
|
||||||
|
this.dayOfWeek = dayOfWeek;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
|
||||||
|
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
|
||||||
|
version="2.1">
|
||||||
|
|
||||||
|
<persistence-unit name="java-jpa-scheduled-day">
|
||||||
|
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
|
||||||
|
<class>com.baeldung.sqlresultsetmapping.ScheduledDay</class>
|
||||||
|
<properties>
|
||||||
|
<property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
|
||||||
|
<property name="javax.persistence.jdbc.url"
|
||||||
|
value="jdbc:h2:mem:test;INIT=RUNSCRIPT FROM 'classpath:database.sql'" />
|
||||||
|
<property name="javax.persistence.jdbc.user" value="sa" />
|
||||||
|
<property name="javax.persistence.jdbc.password" value="" />
|
||||||
|
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
|
||||||
|
<!--<property name="hibernate.hbm2ddl.auto" value="create-drop" />-->
|
||||||
|
<property name="show_sql" value="true"/>
|
||||||
|
<property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/>
|
||||||
|
</properties>
|
||||||
|
</persistence-unit>
|
||||||
|
</persistence>
|
19
persistence-modules/java-jpa/src/main/resources/database.sql
Normal file
19
persistence-modules/java-jpa/src/main/resources/database.sql
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
CREATE TABLE EMPLOYEE
|
||||||
|
(id BIGINT,
|
||||||
|
name VARCHAR(10));
|
||||||
|
|
||||||
|
INSERT INTO EMPLOYEE VALUES (1, 'JOHN');
|
||||||
|
INSERT INTO EMPLOYEE VALUES (2, 'MARY');
|
||||||
|
INSERT INTO EMPLOYEE VALUES (3, 'FRANK');
|
||||||
|
|
||||||
|
CREATE TABLE SCHEDULE_DAYS
|
||||||
|
(id IDENTITY,
|
||||||
|
employeeId BIGINT,
|
||||||
|
hourIn int,
|
||||||
|
hourOut int,
|
||||||
|
dayOfWeek VARCHAR(10));
|
||||||
|
|
||||||
|
INSERT INTO SCHEDULE_DAYS (employeeId, hourIn, hourOut, dayOfWeek) VALUES (1, 13, 21, 'FRIDAY');
|
||||||
|
INSERT INTO SCHEDULE_DAYS (employeeId, hourIn, hourOut, dayOfWeek) VALUES (2, 8, 4, 'SATURDAY');
|
||||||
|
INSERT INTO SCHEDULE_DAYS (employeeId, hourIn, hourOut, dayOfWeek) VALUES (3, 8, 4, 'MONDAY');
|
||||||
|
INSERT INTO SCHEDULE_DAYS (employeeId, hourIn, hourOut, dayOfWeek) VALUES (3, 8, 4, 'FRIDAY');
|
@ -0,0 +1,71 @@
|
|||||||
|
package com.baeldung.sqlresultsetmapping;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
import javax.persistence.Persistence;
|
||||||
|
import javax.persistence.Query;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class SqlResultSetMappingUnitTest {
|
||||||
|
|
||||||
|
private static EntityManager em;
|
||||||
|
private static EntityManagerFactory emFactory;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void setup() {
|
||||||
|
emFactory = Persistence.createEntityManagerFactory("java-jpa-scheduled-day");
|
||||||
|
em = emFactory.createEntityManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNamedQuery_thenColumnResult() {
|
||||||
|
List<Long> employeeIds = em.createNamedQuery("FridayEmployees").getResultList();
|
||||||
|
assertEquals(2, employeeIds.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNamedQuery_thenConstructorResult() {
|
||||||
|
List<ScheduledDay> scheduleDays = Collections.checkedList(em.createNamedQuery("Schedules", ScheduledDay.class).getResultList(), ScheduledDay.class);
|
||||||
|
assertEquals(3, scheduleDays.size());
|
||||||
|
assertTrue(scheduleDays.stream().allMatch(c -> c.getHourIn().longValue() == 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNamedQuery_thenSingleEntityResult() {
|
||||||
|
List<Employee> employees = Collections.checkedList(em.createNamedQuery("Employees").getResultList(), Employee.class);
|
||||||
|
assertEquals(3, employees.size());
|
||||||
|
assertTrue(employees.stream().allMatch(c -> c.getClass() == Employee.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenNamedQuery_thenMultipleEntityResult() {
|
||||||
|
final Query query = em.createNativeQuery("SELECT e.id, e.name, d.id, d.employeeId, "
|
||||||
|
+ " d.dayOfWeek, d.hourIn, d.hourOut "
|
||||||
|
+ " FROM employee e, schedule_days d "
|
||||||
|
+ " WHERE e.id = d.employeeId", "EmployeeScheduleResults");
|
||||||
|
List<Object[]> results = query.getResultList();
|
||||||
|
assertEquals(4, results.size());
|
||||||
|
assertTrue(results.get(0).length == 2);
|
||||||
|
|
||||||
|
Employee emp = (Employee) results.get(1)[0];
|
||||||
|
ScheduledDay day = (ScheduledDay) results.get(1)[1];
|
||||||
|
|
||||||
|
assertTrue(day.getEmployeeId() == emp.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void destroy() {
|
||||||
|
|
||||||
|
if (em != null) {
|
||||||
|
em.close();
|
||||||
|
}
|
||||||
|
if (emFactory != null) {
|
||||||
|
emFactory.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,3 @@
|
|||||||
|
INSERT INTO employee (1, "JOHN");
|
||||||
|
INSERT INTO employee (2, "MARY");
|
||||||
|
INSERT INTO employee (3, "FRANK");
|
@ -0,0 +1,10 @@
|
|||||||
|
INSERT INTO SCHEDULE_DAYS (1, 13, 21, 'FRIDAY');
|
||||||
|
INSERT INTO SCHEDULE_DAYS (2, 8, 4, 'SATURDAY');
|
||||||
|
INSERT INTO SCHEDULE_DAYS (3, 8, 4, 'FRIDAY');
|
||||||
|
|
||||||
|
|
||||||
|
-- private Long id;
|
||||||
|
-- private Long employeeId;
|
||||||
|
-- private Time in;
|
||||||
|
-- private Time out;
|
||||||
|
-- private DayOfWeek dayOfWeek;
|
@ -5,8 +5,8 @@
|
|||||||
<artifactId>spring-boot-dynamodb</artifactId>
|
<artifactId>spring-boot-dynamodb</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>Spring Boot Actuator</name>
|
<name>spring-boot-dynamodb</name>
|
||||||
<description>This is simple boot application for Spring boot actuator test</description>
|
<description>This is simple boot application for Spring boot dynamodb test</description>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<artifactId>parent-boot-1</artifactId>
|
<artifactId>parent-boot-1</artifactId>
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
package com.baeldung.spring.data.dynamodb.config;
|
package com.baeldung.spring.data.dynamodb.config;
|
||||||
|
|
||||||
|
import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
|
||||||
|
|
||||||
import com.amazonaws.auth.AWSCredentials;
|
import com.amazonaws.auth.AWSCredentials;
|
||||||
import com.amazonaws.auth.BasicAWSCredentials;
|
import com.amazonaws.auth.BasicAWSCredentials;
|
||||||
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
|
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
|
||||||
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
|
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
|
||||||
import org.socialsignin.spring.data.dynamodb.repository.config.EnableDynamoDBRepositories;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableDynamoDBRepositories(basePackages = "com.baeldung.spring.data.dynamodb.repositories")
|
@EnableDynamoDBRepositories(basePackages = "com.baeldung.spring.data.dynamodb.repositories")
|
||||||
@ -23,6 +27,9 @@ public class DynamoDBConfig {
|
|||||||
@Value("${amazon.aws.secretkey}")
|
@Value("${amazon.aws.secretkey}")
|
||||||
private String amazonAWSSecretKey;
|
private String amazonAWSSecretKey;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ApplicationContext context;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public AmazonDynamoDB amazonDynamoDB() {
|
public AmazonDynamoDB amazonDynamoDB() {
|
||||||
AmazonDynamoDB amazonDynamoDB = new AmazonDynamoDBClient(amazonAWSCredentials());
|
AmazonDynamoDB amazonDynamoDB = new AmazonDynamoDBClient(amazonAWSCredentials());
|
||||||
@ -37,4 +44,8 @@ public class DynamoDBConfig {
|
|||||||
return new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey);
|
return new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean(name = "mvcHandlerMappingIntrospector")
|
||||||
|
public HandlerMappingIntrospector mvcHandlerMappingIntrospector() {
|
||||||
|
return new HandlerMappingIntrospector(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,11 @@
|
|||||||
<artifactId>spring-data-commons</artifactId>
|
<artifactId>spring-data-commons</artifactId>
|
||||||
<version>${spring-data-commons.version}</version>
|
<version>${spring-data-commons.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.kstyrc</groupId>
|
||||||
|
<artifactId>embedded-redis</artifactId>
|
||||||
|
<version>${embedded-redis.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
@ -79,6 +84,7 @@
|
|||||||
<jedis.version>2.9.0</jedis.version>
|
<jedis.version>2.9.0</jedis.version>
|
||||||
<nosqlunit.version>0.10.0</nosqlunit.version>
|
<nosqlunit.version>0.10.0</nosqlunit.version>
|
||||||
<spring-data-commons.version>2.0.3.RELEASE</spring-data-commons.version>
|
<spring-data-commons.version>2.0.3.RELEASE</spring-data-commons.version>
|
||||||
|
<embedded-redis.version>0.6</embedded-redis.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
package com.baeldung.spring.data.redis.config;
|
package com.baeldung.spring.data.redis.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.PropertySource;
|
||||||
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.data.redis.listener.ChannelTopic;
|
import org.springframework.data.redis.listener.ChannelTopic;
|
||||||
@ -18,6 +20,7 @@ import com.baeldung.spring.data.redis.queue.RedisMessageSubscriber;
|
|||||||
@Configuration
|
@Configuration
|
||||||
@ComponentScan("com.baeldung.spring.data.redis")
|
@ComponentScan("com.baeldung.spring.data.redis")
|
||||||
@EnableRedisRepositories(basePackages = "com.baeldung.spring.data.redis.repo")
|
@EnableRedisRepositories(basePackages = "com.baeldung.spring.data.redis.repo")
|
||||||
|
@PropertySource("classpath:application.properties")
|
||||||
public class RedisConfig {
|
public class RedisConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
|
@ -0,0 +1,2 @@
|
|||||||
|
spring.redis.host=localhost
|
||||||
|
spring.redis.port=6379
|
@ -1,25 +1,45 @@
|
|||||||
package com.baeldung.spring.data.redis;
|
package com.baeldung.spring.data.redis;
|
||||||
|
|
||||||
import com.baeldung.spring.data.redis.config.RedisConfig;
|
|
||||||
import com.baeldung.spring.data.redis.queue.RedisMessageSubscriber;
|
|
||||||
import com.baeldung.spring.data.redis.queue.RedisMessagePublisher;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext.ClassMode;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
|
import com.baeldung.spring.data.redis.config.RedisConfig;
|
||||||
|
import com.baeldung.spring.data.redis.queue.RedisMessagePublisher;
|
||||||
|
import com.baeldung.spring.data.redis.queue.RedisMessageSubscriber;
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration(classes = RedisConfig.class)
|
@ContextConfiguration(classes = RedisConfig.class)
|
||||||
|
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
|
||||||
public class RedisMessageListenerIntegrationTest {
|
public class RedisMessageListenerIntegrationTest {
|
||||||
|
|
||||||
|
private static redis.embedded.RedisServer redisServer;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisMessagePublisher redisMessagePublisher;
|
private RedisMessagePublisher redisMessagePublisher;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void startRedisServer() throws IOException {
|
||||||
|
redisServer = new redis.embedded.RedisServer(6379);
|
||||||
|
redisServer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void stopRedisServer() throws IOException {
|
||||||
|
redisServer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOnMessage() throws Exception {
|
public void testOnMessage() throws Exception {
|
||||||
String message = "Message " + UUID.randomUUID();
|
String message = "Message " + UUID.randomUUID();
|
||||||
|
@ -3,13 +3,17 @@ package com.baeldung.spring.data.redis.repo;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
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;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext.ClassMode;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
@ -18,11 +22,25 @@ import com.baeldung.spring.data.redis.model.Student;
|
|||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration(classes = RedisConfig.class)
|
@ContextConfiguration(classes = RedisConfig.class)
|
||||||
|
@DirtiesContext(classMode = ClassMode.AFTER_CLASS)
|
||||||
public class StudentRepositoryIntegrationTest {
|
public class StudentRepositoryIntegrationTest {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private StudentRepository studentRepository;
|
private StudentRepository studentRepository;
|
||||||
|
|
||||||
|
private static redis.embedded.RedisServer redisServer;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void startRedisServer() throws IOException {
|
||||||
|
redisServer = new redis.embedded.RedisServer(6379);
|
||||||
|
redisServer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void stopRedisServer() throws IOException {
|
||||||
|
redisServer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenSavingStudent_thenAvailableOnRetrieval() throws Exception {
|
public void whenSavingStudent_thenAvailableOnRetrieval() throws Exception {
|
||||||
final Student student = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1);
|
final Student student = new Student("Eng2015001", "John Doe", Student.Gender.MALE, 1);
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<context:annotation-config />
|
<context:annotation-config />
|
||||||
<context:component-scan base-package="org.baeldung.persistence" />
|
<context:component-scan base-package="org.baeldung.persistence" />
|
||||||
<context:property-placeholder location="classpath:persistence-mysql.properties"/>
|
<context:property-placeholder location="classpath:persistence-h2.properties"/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"
|
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd"
|
||||||
>
|
>
|
||||||
|
|
||||||
<context:property-placeholder location="classpath:persistence-mysql.properties"/>
|
<context:property-placeholder location="classpath:persistence-h2.properties"/>
|
||||||
|
|
||||||
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
|
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
|
||||||
<property name="dataSource" ref="dataSource"/>
|
<property name="dataSource" ref="dataSource"/>
|
||||||
|
3
pom.xml
3
pom.xml
@ -184,14 +184,12 @@
|
|||||||
<module>spring-katharsis</module>
|
<module>spring-katharsis</module>
|
||||||
<module>spring-ldap</module>
|
<module>spring-ldap</module>
|
||||||
<module>spring-mockito</module>
|
<module>spring-mockito</module>
|
||||||
<module>spring-mvc-email</module>
|
|
||||||
<module>spring-mvc-forms-jsp</module>
|
<module>spring-mvc-forms-jsp</module>
|
||||||
<module>spring-mvc-forms-thymeleaf</module>
|
<module>spring-mvc-forms-thymeleaf</module>
|
||||||
<module>spring-mvc-java</module>
|
<module>spring-mvc-java</module>
|
||||||
<module>spring-mvc-velocity</module>
|
<module>spring-mvc-velocity</module>
|
||||||
<module>spring-mvc-webflow</module>
|
<module>spring-mvc-webflow</module>
|
||||||
<module>spring-mvc-xml</module>
|
<module>spring-mvc-xml</module>
|
||||||
<module>spring-mvc-simple</module>
|
|
||||||
<module>spring-mvc-kotlin</module>
|
<module>spring-mvc-kotlin</module>
|
||||||
<module>spring-security-openid</module>
|
<module>spring-security-openid</module>
|
||||||
<module>spring-protobuf</module>
|
<module>spring-protobuf</module>
|
||||||
@ -273,6 +271,7 @@
|
|||||||
<module>antlr</module>
|
<module>antlr</module>
|
||||||
<module>maven-archetype</module>
|
<module>maven-archetype</module>
|
||||||
<module>maven-java-kotlin</module>
|
<module>maven-java-kotlin</module>
|
||||||
|
<module>apache-meecrowave</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
package com.baeldung.rxjava;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import rx.Observable;
|
||||||
|
import rx.Subscription;
|
||||||
|
import rx.observables.ConnectableObservable;
|
||||||
|
import rx.subscriptions.Subscriptions;
|
||||||
|
|
||||||
|
public class MultipleSubscribersColdObs {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(MultipleSubscribersColdObs.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) throws InterruptedException {
|
||||||
|
defaultBehaviour();
|
||||||
|
// subscribeBeforeConnect();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void defaultBehaviour() {
|
||||||
|
Observable obs = getObservable();
|
||||||
|
|
||||||
|
LOGGER.info("Subscribing");
|
||||||
|
Subscription s1 = obs.subscribe(i -> LOGGER.info("subscriber#1 is printing " + i));
|
||||||
|
Subscription s2 = obs.subscribe(i -> LOGGER.info("subscriber#2 is printing " + i));
|
||||||
|
|
||||||
|
s1.unsubscribe();
|
||||||
|
s2.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void subscribeBeforeConnect() throws InterruptedException {
|
||||||
|
ConnectableObservable obs = getObservable().publish();
|
||||||
|
|
||||||
|
LOGGER.info("Subscribing");
|
||||||
|
obs.subscribe(i -> LOGGER.info("subscriber #1 is printing " + i));
|
||||||
|
obs.subscribe(i -> LOGGER.info("subscriber #2 is printing " + i));
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("Connecting");
|
||||||
|
Subscription s = obs.connect();
|
||||||
|
s.unsubscribe();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Observable getObservable() {
|
||||||
|
return Observable.create(subscriber -> {
|
||||||
|
subscriber.onNext(gettingValue(1));
|
||||||
|
subscriber.onNext(gettingValue(2));
|
||||||
|
|
||||||
|
subscriber.add(Subscriptions.create(() -> {
|
||||||
|
LOGGER.info("Clear resources");
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Integer gettingValue(int i) {
|
||||||
|
LOGGER.info("Getting " + i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,152 @@
|
|||||||
|
package com.baeldung.rxjava;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.event.MouseListener;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
import javax.swing.JFrame;
|
||||||
|
import rx.Observable;
|
||||||
|
import rx.Subscription;
|
||||||
|
import rx.observables.ConnectableObservable;
|
||||||
|
import rx.subscriptions.Subscriptions;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public class MultipleSubscribersHotObs {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(MultipleSubscribersHotObs.class);
|
||||||
|
private static JFrame frame;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws InterruptedException, InvocationTargetException {
|
||||||
|
|
||||||
|
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
createAndShowGUI();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
defaultBehaviour();
|
||||||
|
// subscribeBeforeConnect();
|
||||||
|
// connectBeforeSubscribe();
|
||||||
|
// autoConnectAndSubscribe();
|
||||||
|
// refCountAndSubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createAndShowGUI() {
|
||||||
|
frame = new JFrame("Hot Observable Demo");
|
||||||
|
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
frame.getContentPane().setBackground(Color.GRAY);
|
||||||
|
frame.setPreferredSize(new Dimension(500, 500));
|
||||||
|
frame.pack();
|
||||||
|
frame.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void defaultBehaviour() throws InterruptedException {
|
||||||
|
Observable obs = getObservable();
|
||||||
|
|
||||||
|
LOGGER.info("subscribing #1");
|
||||||
|
Subscription subscription1 = obs.subscribe((i) -> LOGGER.info("subscriber#1 is printing x-coordinate " + i));
|
||||||
|
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("subscribing #2");
|
||||||
|
Subscription subscription2 = obs.subscribe((i) -> LOGGER.info("subscriber#2 is printing x-coordinate " + i));
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("unsubscribe#1");
|
||||||
|
subscription1.unsubscribe();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("unsubscribe#2");
|
||||||
|
subscription2.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void subscribeBeforeConnect() throws InterruptedException {
|
||||||
|
|
||||||
|
ConnectableObservable obs = getObservable().publish();
|
||||||
|
|
||||||
|
LOGGER.info("subscribing #1");
|
||||||
|
Subscription subscription1 = obs.subscribe((i) -> LOGGER.info("subscriber#1 is printing x-coordinate " + i));
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("subscribing #2");
|
||||||
|
Subscription subscription2 = obs.subscribe((i) -> LOGGER.info("subscriber#2 is printing x-coordinate " + i));
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("connecting:");
|
||||||
|
Subscription s = obs.connect();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("unsubscribe connected");
|
||||||
|
s.unsubscribe();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void connectBeforeSubscribe() throws InterruptedException {
|
||||||
|
|
||||||
|
ConnectableObservable obs = getObservable().doOnNext(x -> LOGGER.info("saving " + x)).publish();
|
||||||
|
LOGGER.info("connecting:");
|
||||||
|
Subscription s = obs.connect();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("subscribing #1");
|
||||||
|
obs.subscribe((i) -> LOGGER.info("subscriber#1 is printing x-coordinate " + i));
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("subscribing #2");
|
||||||
|
obs.subscribe((i) -> LOGGER.info("subscriber#2 is printing x-coordinate " + i));
|
||||||
|
Thread.sleep(1000);
|
||||||
|
s.unsubscribe();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void autoConnectAndSubscribe() throws InterruptedException {
|
||||||
|
Observable obs = getObservable().doOnNext(x -> LOGGER.info("saving " + x)).publish().autoConnect();
|
||||||
|
|
||||||
|
LOGGER.info("autoconnect()");
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("subscribing #1");
|
||||||
|
Subscription s1 = obs.subscribe((i) -> LOGGER.info("subscriber#1 is printing x-coordinate " + i));
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("subscribing #2");
|
||||||
|
Subscription s2 = obs.subscribe((i) -> LOGGER.info("subscriber#2 is printing x-coordinate " + i));
|
||||||
|
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("unsubscribe 1");
|
||||||
|
s1.unsubscribe();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("unsubscribe 2");
|
||||||
|
s2.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void refCountAndSubscribe() throws InterruptedException {
|
||||||
|
Observable obs = getObservable().doOnNext(x -> LOGGER.info("saving " + x)).publish().refCount();
|
||||||
|
|
||||||
|
LOGGER.info("refcount()");
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("subscribing #1");
|
||||||
|
Subscription subscription1 = obs.subscribe((i) -> LOGGER.info("subscriber#1 is printing x-coordinate " + i));
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("subscribing #2");
|
||||||
|
Subscription subscription2 = obs.subscribe((i) -> LOGGER.info("subscriber#2 is printing x-coordinate " + i));
|
||||||
|
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("unsubscribe#1");
|
||||||
|
subscription1.unsubscribe();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
LOGGER.info("unsubscribe#2");
|
||||||
|
subscription2.unsubscribe();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Observable getObservable() {
|
||||||
|
return Observable.create(subscriber -> {
|
||||||
|
frame.addMouseListener(new MouseAdapter() {
|
||||||
|
@Override
|
||||||
|
public void mouseClicked(MouseEvent e) {
|
||||||
|
subscriber.onNext(e.getX());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
subscriber.add(Subscriptions.create(() -> {
|
||||||
|
LOGGER.info("Clear resources");
|
||||||
|
for (MouseListener listener : frame.getListeners(MouseListener.class)) {
|
||||||
|
frame.removeMouseListener(listener);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
21
spring-5-mvc/src/main/java/com/baeldung/Constants.java
Normal file
21
spring-5-mvc/src/main/java/com/baeldung/Constants.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package com.baeldung;
|
||||||
|
|
||||||
|
public class Constants {
|
||||||
|
|
||||||
|
public static final String GENERIC_EXCEPTION = "Exception encountered!";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API endpoints.
|
||||||
|
*/
|
||||||
|
public static final String API_RBE = "/rbe";
|
||||||
|
public static final String API_SSE = "/sse";
|
||||||
|
public static final String API_SRB = "/srb";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API Responses.
|
||||||
|
*/
|
||||||
|
public static final String API_RBE_MSG = "I Was Sent From a Response Body Emitter!";
|
||||||
|
public static final String API_SSE_MSG = "I Was Sent From a Sse!";
|
||||||
|
public static final String API_SRB_MSG = "I Was Sent From a Streaming Response Body!";
|
||||||
|
|
||||||
|
}
|
@ -49,8 +49,6 @@ public class Foo {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
final int prime = 31;
|
final int prime = 31;
|
||||||
|
@ -16,8 +16,6 @@ public class DataSetupBean implements InitializingBean {
|
|||||||
@Autowired
|
@Autowired
|
||||||
private FooRepository repo;
|
private FooRepository repo;
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterPropertiesSet() throws Exception {
|
public void afterPropertiesSet() throws Exception {
|
||||||
IntStream.range(1, 5).forEach(i -> repo.save(new Foo(randomAlphabetic(8))));
|
IntStream.range(1, 5).forEach(i -> repo.save(new Foo(randomAlphabetic(8))));
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.baeldung.web;
|
||||||
|
|
||||||
|
import com.baeldung.Constants;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class ResponseBodyEmitterController {
|
||||||
|
|
||||||
|
@GetMapping(Constants.API_RBE)
|
||||||
|
public ResponseEntity<ResponseBodyEmitter> handleRbe() {
|
||||||
|
ResponseBodyEmitter emitter = new ResponseBodyEmitter();
|
||||||
|
ExecutorService nonBlockingService = Executors.newSingleThreadExecutor();
|
||||||
|
|
||||||
|
nonBlockingService.execute(() -> {
|
||||||
|
try {
|
||||||
|
emitter.send(Constants.API_RBE_MSG + " @ " + new Date(), MediaType.TEXT_PLAIN);
|
||||||
|
emitter.complete();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
System.out.println(Constants.GENERIC_EXCEPTION);
|
||||||
|
emitter.completeWithError(ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return new ResponseEntity(emitter, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package com.baeldung.web;
|
||||||
|
|
||||||
|
import com.baeldung.Constants;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class SseEmitterController {
|
||||||
|
|
||||||
|
@GetMapping(Constants.API_SSE)
|
||||||
|
public SseEmitter handleSse() {
|
||||||
|
SseEmitter emitter = new SseEmitter();
|
||||||
|
|
||||||
|
ExecutorService nonBlockingService = Executors.newSingleThreadExecutor();
|
||||||
|
nonBlockingService.execute(() -> {
|
||||||
|
try {
|
||||||
|
emitter.send(Constants.API_SSE_MSG + " @ " + new Date());
|
||||||
|
emitter.complete();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
System.out.println(Constants.GENERIC_EXCEPTION);
|
||||||
|
emitter.completeWithError(ex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return emitter;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.baeldung.web;
|
||||||
|
|
||||||
|
import com.baeldung.Constants;
|
||||||
|
import java.util.Date;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class StreamingResponseBodyController {
|
||||||
|
|
||||||
|
@GetMapping(Constants.API_SRB)
|
||||||
|
public ResponseEntity<StreamingResponseBody> handleRbe() {
|
||||||
|
StreamingResponseBody stream = out -> {
|
||||||
|
String msg = Constants.API_SRB_MSG + " @ " + new Date();
|
||||||
|
out.write(msg.getBytes());
|
||||||
|
};
|
||||||
|
return new ResponseEntity(stream, HttpStatus.OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
86
spring-5-mvc/src/main/webapp/WEB-INF/jsp/index.jsp
Normal file
86
spring-5-mvc/src/main/webapp/WEB-INF/jsp/index.jsp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<%@taglib uri="http://www.springframework.org/tags" prefix="spring" %>
|
||||||
|
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
|
||||||
|
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
|
||||||
|
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1" %>
|
||||||
|
|
||||||
|
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Spring MVC Async</title>
|
||||||
|
<link href="<c:url value="/resources/styles/style.css"/>" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<h2>Spring MVC Async</h2>
|
||||||
|
<div id="rbe"></div>
|
||||||
|
<div id="sse"></div>
|
||||||
|
<div id="srb"></div>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AJAX Helpers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var xhr = function(url) {
|
||||||
|
return new Promise(function(resolve, reject) {
|
||||||
|
try {
|
||||||
|
var xmhr = new XMLHttpRequest();
|
||||||
|
|
||||||
|
//Listen for API Response
|
||||||
|
xmhr.onreadystatechange = function() {
|
||||||
|
if (xmhr.readyState == XMLHttpRequest.DONE && xmhr.status == 200) return resolve(xmhr.responseText);
|
||||||
|
};
|
||||||
|
|
||||||
|
//Open connection
|
||||||
|
xmhr.open("GET", url, true);
|
||||||
|
//Additional headers as needed
|
||||||
|
//x.withCredentials = true;
|
||||||
|
//x.setRequestHeader("Accept", "application/json");
|
||||||
|
//x.setRequestHeader("Content-Type", "text/plain");
|
||||||
|
|
||||||
|
//Perform the actual AJAX call
|
||||||
|
xmhr.send();
|
||||||
|
|
||||||
|
} catch (ex) {
|
||||||
|
reject("Exception: Oh CORS's you've made a mistake!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RBE
|
||||||
|
*/
|
||||||
|
|
||||||
|
xhr('http://localhost:8080/rbe').then(function(success){
|
||||||
|
var el = document.getElementById('rbe');
|
||||||
|
el.appendChild(document.createTextNode(success));
|
||||||
|
el.appendChild(document.createElement('br'))
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SSE
|
||||||
|
*/
|
||||||
|
|
||||||
|
var sse = new EventSource('http://localhost:8080/sse');
|
||||||
|
sse.onmessage = function (evt) {
|
||||||
|
var el = document.getElementById('sse');
|
||||||
|
el.appendChild(document.createTextNode(evt.data));
|
||||||
|
el.appendChild(document.createElement('br'))
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SRB
|
||||||
|
*/
|
||||||
|
|
||||||
|
xhr('http://localhost:8080/srb').then(function(success){
|
||||||
|
var el = document.getElementById('srb');
|
||||||
|
el.appendChild(document.createTextNode(success));
|
||||||
|
el.appendChild(document.createElement('br'))
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</html>
|
@ -0,0 +1,55 @@
|
|||||||
|
|
||||||
|
package com.baeldung.reactive.errorhandling;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import org.springframework.boot.web.reactive.error.DefaultErrorAttributes;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class GlobalErrorAttributes extends DefaultErrorAttributes{
|
||||||
|
|
||||||
|
private HttpStatus status = HttpStatus.BAD_REQUEST;
|
||||||
|
private String message = "please provide a name";
|
||||||
|
|
||||||
|
public GlobalErrorAttributes() {
|
||||||
|
super(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
|
||||||
|
Map<String, Object> map = super.getErrorAttributes(request, includeStackTrace);
|
||||||
|
map.put("status", getStatus());
|
||||||
|
map.put("message", getMessage());
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the status
|
||||||
|
*/
|
||||||
|
public HttpStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param status the status to set
|
||||||
|
*/
|
||||||
|
public void setStatus(HttpStatus status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the message
|
||||||
|
*/
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message the message to set
|
||||||
|
*/
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
package com.baeldung.reactive.errorhandling;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import org.springframework.boot.autoconfigure.web.ResourceProperties;
|
||||||
|
import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
|
||||||
|
import org.springframework.boot.web.reactive.error.ErrorAttributes;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.codec.ServerCodecConfigurer;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.BodyInserters;
|
||||||
|
import org.springframework.web.reactive.function.server.RequestPredicates;
|
||||||
|
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||||
|
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Order(-2)
|
||||||
|
public class GlobalErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
|
||||||
|
|
||||||
|
public GlobalErrorWebExceptionHandler(GlobalErrorAttributes g, ApplicationContext applicationContext,
|
||||||
|
ServerCodecConfigurer serverCodecConfigurer) {
|
||||||
|
super(g, new ResourceProperties(), applicationContext);
|
||||||
|
super.setMessageWriters(serverCodecConfigurer.getWriters());
|
||||||
|
super.setMessageReaders(serverCodecConfigurer.getReaders());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected RouterFunction<ServerResponse> getRoutingFunction(final ErrorAttributes errorAttributes) {
|
||||||
|
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<ServerResponse> renderErrorResponse(final ServerRequest request) {
|
||||||
|
|
||||||
|
final Map<String, Object> errorPropertiesMap = getErrorAttributes(request, false);
|
||||||
|
|
||||||
|
return ServerResponse.status(HttpStatus.BAD_REQUEST)
|
||||||
|
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||||
|
.body(BodyInserters.fromObject(errorPropertiesMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
package com.baeldung.reactive.errorhandling;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
|
||||||
|
public class NameRequiredException extends ResponseStatusException {
|
||||||
|
|
||||||
|
public NameRequiredException(HttpStatus status, String message, Throwable e) {
|
||||||
|
super(status, message, e);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
|
||||||
|
package com.baeldung.reactive.errorhandling.handlers;
|
||||||
|
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class Handler1 {
|
||||||
|
|
||||||
|
public Mono<ServerResponse> handleRequest1(ServerRequest request) {
|
||||||
|
return sayHello(request).onErrorReturn("Hello, Stranger")
|
||||||
|
.flatMap(s -> ServerResponse.ok()
|
||||||
|
.contentType(MediaType.TEXT_PLAIN)
|
||||||
|
.syncBody(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<String> sayHello(ServerRequest request) {
|
||||||
|
try {
|
||||||
|
return Mono.just("Hello, " + request.queryParam("name")
|
||||||
|
.get());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Mono.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
package com.baeldung.reactive.errorhandling.handlers;
|
||||||
|
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class Handler2 {
|
||||||
|
|
||||||
|
public Mono<ServerResponse> handleRequest2(ServerRequest request) {
|
||||||
|
return
|
||||||
|
sayHello(request)
|
||||||
|
.flatMap(s -> ServerResponse.ok()
|
||||||
|
.contentType(MediaType.TEXT_PLAIN)
|
||||||
|
.syncBody(s))
|
||||||
|
.onErrorResume(e -> sayHelloFallback()
|
||||||
|
.flatMap(s -> ServerResponse.ok()
|
||||||
|
.contentType(MediaType.TEXT_PLAIN)
|
||||||
|
.syncBody(s)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<String> sayHello(ServerRequest request) {
|
||||||
|
try {
|
||||||
|
return Mono.just("Hello, " + request.queryParam("name")
|
||||||
|
.get());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Mono.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<String> sayHelloFallback() {
|
||||||
|
return Mono.just("Hello, Stranger");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
package com.baeldung.reactive.errorhandling.handlers;
|
||||||
|
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class Handler3 {
|
||||||
|
|
||||||
|
public Mono<ServerResponse> handleRequest3(ServerRequest request) {
|
||||||
|
return
|
||||||
|
sayHello(request)
|
||||||
|
.flatMap(s -> ServerResponse.ok()
|
||||||
|
.contentType(MediaType.TEXT_PLAIN)
|
||||||
|
.syncBody(s))
|
||||||
|
.onErrorResume(e -> (Mono.just("Hi, I looked around for your name but found: " +
|
||||||
|
e.getMessage())).flatMap(s -> ServerResponse.ok()
|
||||||
|
.contentType(MediaType.TEXT_PLAIN)
|
||||||
|
.syncBody(s)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<String> sayHello(ServerRequest request) {
|
||||||
|
try {
|
||||||
|
return Mono.just("Hello, " + request.queryParam("name")
|
||||||
|
.get());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Mono.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
package com.baeldung.reactive.errorhandling.handlers;
|
||||||
|
|
||||||
|
import com.baeldung.reactive.errorhandling.NameRequiredException;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class Handler4 {
|
||||||
|
|
||||||
|
public Mono<ServerResponse> handleRequest4(ServerRequest request) {
|
||||||
|
return ServerResponse.ok()
|
||||||
|
.body(sayHello(request)
|
||||||
|
.onErrorResume(e ->
|
||||||
|
Mono.error(new NameRequiredException(
|
||||||
|
HttpStatus.BAD_REQUEST, "please provide a name", e))), String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<String> sayHello(ServerRequest request) {
|
||||||
|
try {
|
||||||
|
return Mono.just("Hello, " + request.queryParam("name").get());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Mono.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
package com.baeldung.reactive.errorhandling.handlers;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class Handler5 {
|
||||||
|
|
||||||
|
public Mono<ServerResponse> handleRequest5(ServerRequest request) {
|
||||||
|
return ServerResponse.ok()
|
||||||
|
.body(sayHello(request), String.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Mono<String> sayHello(ServerRequest request) {
|
||||||
|
return Mono.just("Hello, " + request.queryParam("name").get());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
package com.baeldung.reactive.errorhandling.routers;
|
||||||
|
|
||||||
|
import com.baeldung.reactive.errorhandling.handlers.Handler1;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.server.RequestPredicates;
|
||||||
|
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||||
|
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class Router1 {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RouterFunction<ServerResponse> routeRequest1(Handler1 handler) {
|
||||||
|
return RouterFunctions.route(RequestPredicates.GET("/api/endpoint1")
|
||||||
|
.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), handler::handleRequest1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
package com.baeldung.reactive.errorhandling.routers;
|
||||||
|
|
||||||
|
import com.baeldung.reactive.errorhandling.handlers.Handler2;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.server.RequestPredicates;
|
||||||
|
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||||
|
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class Router2 {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RouterFunction<ServerResponse> routeRequest2(Handler2 handler) {
|
||||||
|
return RouterFunctions.route(RequestPredicates.GET("/api/endpoint2")
|
||||||
|
.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), handler::handleRequest2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
package com.baeldung.reactive.errorhandling.routers;
|
||||||
|
|
||||||
|
import com.baeldung.reactive.errorhandling.handlers.Handler3;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.server.RequestPredicates;
|
||||||
|
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||||
|
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class Router3 {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RouterFunction<ServerResponse> routeRequest3(Handler3 handler) {
|
||||||
|
return RouterFunctions.route(RequestPredicates.GET("/api/endpoint3")
|
||||||
|
.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), handler::handleRequest3);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
package com.baeldung.reactive.errorhandling.routers;
|
||||||
|
|
||||||
|
import com.baeldung.reactive.errorhandling.handlers.Handler4;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.server.RequestPredicates;
|
||||||
|
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||||
|
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class Router4 {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RouterFunction<ServerResponse> routeRequest4(Handler4 handler) {
|
||||||
|
return RouterFunctions.route(RequestPredicates.GET("/api/endpoint4")
|
||||||
|
.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), handler::handleRequest4);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
|
||||||
|
package com.baeldung.reactive.errorhandling.routers;
|
||||||
|
|
||||||
|
import com.baeldung.reactive.errorhandling.handlers.Handler5;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.server.RequestPredicates;
|
||||||
|
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||||
|
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class Router5 {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RouterFunction<ServerResponse> routeRequest5(Handler5 handler) {
|
||||||
|
return RouterFunctions.route(RequestPredicates.GET("/api/endpoint5")
|
||||||
|
.and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), handler::handleRequest5);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
package com.baeldung.reactive.responseheaders.controllers;
|
||||||
|
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/response-header")
|
||||||
|
public class ResponseHeaderController {
|
||||||
|
|
||||||
|
@GetMapping("/response-entity")
|
||||||
|
public Mono<ResponseEntity<String>> usingResponseEntityBuilder() {
|
||||||
|
String responseHeaderKey = "Baeldung-Example-Header";
|
||||||
|
String responseHeaderValue = "Value-ResponseEntityBuilder";
|
||||||
|
String responseBody = "Response with header using ResponseEntity (builder)";
|
||||||
|
|
||||||
|
return Mono.just(ResponseEntity.ok()
|
||||||
|
.header(responseHeaderKey, responseHeaderValue)
|
||||||
|
.body(responseBody));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/server-http-response")
|
||||||
|
public Mono<String> usingServerHttpResponse(ServerHttpResponse response) {
|
||||||
|
String responseHeaderKey = "Baeldung-Example-Header";
|
||||||
|
String responseHeaderValue = "Value-ServerHttpResponse";
|
||||||
|
String responseBody = "Response with header using ServerHttpResponse";
|
||||||
|
|
||||||
|
response.getHeaders().add(responseHeaderKey, responseHeaderValue);
|
||||||
|
return Mono.just(responseBody);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.baeldung.reactive.responseheaders.filter;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
import org.springframework.web.server.WebFilter;
|
||||||
|
import org.springframework.web.server.WebFilterChain;
|
||||||
|
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class AddResponseHeaderWebFilter implements WebFilter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
|
||||||
|
exchange.getResponse()
|
||||||
|
.getHeaders()
|
||||||
|
.add("Baeldung-Example-Filter-Header", "Value-Filter");
|
||||||
|
return chain.filter(exchange);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.baeldung.reactive.responseheaders.functional.handlers;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
|
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ResponseHeaderHandler {
|
||||||
|
|
||||||
|
public Mono<ServerResponse> useHandler(final ServerRequest request) {
|
||||||
|
String responseHeaderKey = "Baeldung-Example-Header";
|
||||||
|
String responseHeaderValue = "Value-Handler";
|
||||||
|
String responseBody = "Response with header using Handler";
|
||||||
|
|
||||||
|
return ServerResponse.ok()
|
||||||
|
.header(responseHeaderKey, responseHeaderValue)
|
||||||
|
.body(Mono.just(responseBody),String.class);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
package com.baeldung.reactive.responseheaders.functional.routers;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.reactive.function.server.RequestPredicates;
|
||||||
|
import org.springframework.web.reactive.function.server.RouterFunction;
|
||||||
|
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||||
|
|
||||||
|
import com.baeldung.reactive.responseheaders.functional.handlers.ResponseHeaderHandler;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class ResponseHeadersRouterFunctions {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RouterFunction<ServerResponse> responseHeaderRoute(@Autowired ResponseHeaderHandler handler) {
|
||||||
|
return RouterFunctions.route(RequestPredicates.GET("/functional-response-header/single-handler"), handler::useHandler);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,168 @@
|
|||||||
|
package com.baeldung.reactive.errorhandling;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
|
||||||
|
public class ErrorHandlingIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WebTestClient webTestClient;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenErrorReturn_whenUsernamePresent_thenOk() throws IOException {
|
||||||
|
|
||||||
|
String s = webTestClient.get()
|
||||||
|
.uri("/api/endpoint1?name={username}", "Tony")
|
||||||
|
.accept(MediaType.TEXT_PLAIN)
|
||||||
|
.exchange()
|
||||||
|
.returnResult(String.class)
|
||||||
|
.getResponseBody()
|
||||||
|
.blockFirst();
|
||||||
|
|
||||||
|
assertEquals("Hello, Tony", s);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenErrorReturn_whenNoUsername_thenOk() throws IOException {
|
||||||
|
|
||||||
|
String s = webTestClient.get()
|
||||||
|
.uri("/api/endpoint1")
|
||||||
|
.accept(MediaType.TEXT_PLAIN)
|
||||||
|
.exchange()
|
||||||
|
.returnResult(String.class)
|
||||||
|
.getResponseBody()
|
||||||
|
.blockFirst();
|
||||||
|
|
||||||
|
assertEquals("Hello, Stranger", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenResumeFallback_whenUsernamePresent_thenOk() throws IOException {
|
||||||
|
|
||||||
|
String s = webTestClient.get()
|
||||||
|
.uri("/api/endpoint2?name={username}", "Tony")
|
||||||
|
.accept(MediaType.TEXT_PLAIN)
|
||||||
|
.exchange()
|
||||||
|
.returnResult(String.class)
|
||||||
|
.getResponseBody()
|
||||||
|
.blockFirst();
|
||||||
|
|
||||||
|
assertEquals("Hello, Tony", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenResumeFallback_whenNoUsername_thenOk() throws IOException {
|
||||||
|
String s = webTestClient.get()
|
||||||
|
.uri("/api/endpoint2")
|
||||||
|
.accept(MediaType.TEXT_PLAIN)
|
||||||
|
.exchange()
|
||||||
|
.returnResult(String.class)
|
||||||
|
.getResponseBody()
|
||||||
|
.blockFirst();
|
||||||
|
|
||||||
|
assertEquals("Hello, Stranger", s);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenResumeDynamicValue_whenUsernamePresent_thenOk() throws IOException {
|
||||||
|
|
||||||
|
String s = webTestClient.get()
|
||||||
|
.uri("/api/endpoint3?name={username}", "Tony")
|
||||||
|
.accept(MediaType.TEXT_PLAIN)
|
||||||
|
.exchange()
|
||||||
|
.returnResult(String.class)
|
||||||
|
.getResponseBody()
|
||||||
|
.blockFirst();
|
||||||
|
|
||||||
|
assertEquals("Hello, Tony", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenResumeDynamicValue_whenNoUsername_thenOk() throws IOException {
|
||||||
|
String s = webTestClient.get()
|
||||||
|
.uri("/api/endpoint3")
|
||||||
|
.accept(MediaType.TEXT_PLAIN)
|
||||||
|
.exchange()
|
||||||
|
.returnResult(String.class)
|
||||||
|
.getResponseBody()
|
||||||
|
.blockFirst();
|
||||||
|
|
||||||
|
assertEquals("Hi, I looked around for your name but found: No value present", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenResumeRethrow_whenUsernamePresent_thenOk() throws IOException {
|
||||||
|
String s = webTestClient.get()
|
||||||
|
.uri("/api/endpoint4?name={username}", "Tony")
|
||||||
|
.accept(MediaType.TEXT_PLAIN)
|
||||||
|
.exchange()
|
||||||
|
.returnResult(String.class)
|
||||||
|
.getResponseBody()
|
||||||
|
.blockFirst();
|
||||||
|
|
||||||
|
assertEquals("Hello, Tony", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenResumeRethrow_whenNoUsername_thenOk() throws IOException {
|
||||||
|
|
||||||
|
webTestClient.get()
|
||||||
|
.uri("/api/endpoint4")
|
||||||
|
.accept(MediaType.TEXT_PLAIN)
|
||||||
|
.exchange()
|
||||||
|
.expectStatus()
|
||||||
|
.isBadRequest()
|
||||||
|
.expectHeader()
|
||||||
|
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||||
|
.expectBody()
|
||||||
|
.jsonPath("$.message")
|
||||||
|
.isNotEmpty()
|
||||||
|
.jsonPath("$.message")
|
||||||
|
.isEqualTo("please provide a name");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenGlobalErrorHandling_whenUsernamePresent_thenOk() throws IOException {
|
||||||
|
|
||||||
|
String s = webTestClient.get()
|
||||||
|
.uri("/api/endpoint5?name={username}", "Tony")
|
||||||
|
.accept(MediaType.TEXT_PLAIN)
|
||||||
|
.exchange()
|
||||||
|
.returnResult(String.class)
|
||||||
|
.getResponseBody()
|
||||||
|
.blockFirst();
|
||||||
|
|
||||||
|
assertEquals("Hello, Tony", s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenGlobalErrorHandling_whenNoUsername_thenOk() throws IOException {
|
||||||
|
webTestClient.get()
|
||||||
|
.uri("/api/endpoint5")
|
||||||
|
.accept(MediaType.TEXT_PLAIN)
|
||||||
|
.exchange()
|
||||||
|
.expectStatus()
|
||||||
|
.isBadRequest()
|
||||||
|
.expectHeader()
|
||||||
|
.contentType(MediaType.APPLICATION_JSON_UTF8)
|
||||||
|
.expectBody()
|
||||||
|
.jsonPath("$.message")
|
||||||
|
.isNotEmpty()
|
||||||
|
.jsonPath("$.message")
|
||||||
|
.isEqualTo("please provide a name");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package com.baeldung.reactive.responseheaders;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
|
import org.springframework.test.web.reactive.server.WebTestClient.ResponseSpec;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||||
|
public class ResponseHeaderLiveTest {
|
||||||
|
|
||||||
|
private static final String BASE_URL = "http://localhost:8080";
|
||||||
|
private static final String ANNOTATION_BASE_URL = BASE_URL + "/response-header";
|
||||||
|
private static final String FUNCTIONAL_BASE_URL = BASE_URL + "/functional-response-header";
|
||||||
|
private static final String SERVICE_SINGLE_RESPONSE_HEADER = "Baeldung-Example-Header";
|
||||||
|
private static final String SERVICE_FILTER_RESPONSE_HEADER = "Baeldung-Example-Filter-Header";
|
||||||
|
private static final String SERVICE_FILTER_RESPONSE_HEADER_VALUE = "Value-Filter";
|
||||||
|
|
||||||
|
private static WebTestClient client;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void setup() {
|
||||||
|
client = WebTestClient.bindToServer()
|
||||||
|
.baseUrl(BASE_URL)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingResponseEntityBuilderRequest_thenObtainResponseWithCorrectHeaders() {
|
||||||
|
client = WebTestClient.bindToServer()
|
||||||
|
.baseUrl(BASE_URL)
|
||||||
|
.build();
|
||||||
|
ResponseSpec response = client.get()
|
||||||
|
.uri(ANNOTATION_BASE_URL + "/response-entity")
|
||||||
|
.exchange();
|
||||||
|
|
||||||
|
response.expectHeader().valueEquals(SERVICE_SINGLE_RESPONSE_HEADER, "Value-ResponseEntityBuilder")
|
||||||
|
.expectHeader().valueEquals(SERVICE_FILTER_RESPONSE_HEADER, SERVICE_FILTER_RESPONSE_HEADER_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingServerHttpResponseRequest_thenObtainResponseWithCorrectHeaders() {
|
||||||
|
ResponseSpec response = client.get()
|
||||||
|
.uri(ANNOTATION_BASE_URL + "/server-http-response")
|
||||||
|
.exchange();
|
||||||
|
|
||||||
|
response.expectHeader().valueEquals(SERVICE_SINGLE_RESPONSE_HEADER, "Value-ServerHttpResponse")
|
||||||
|
.expectHeader().valueEquals(SERVICE_FILTER_RESPONSE_HEADER, SERVICE_FILTER_RESPONSE_HEADER_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingFunctionalHandlerRequest_thenObtainResponseWithCorrectHeaders() {
|
||||||
|
ResponseSpec response = client.get()
|
||||||
|
.uri(FUNCTIONAL_BASE_URL + "/single-handler")
|
||||||
|
.exchange();
|
||||||
|
|
||||||
|
response.expectHeader().valueEquals(SERVICE_SINGLE_RESPONSE_HEADER, "Value-Handler")
|
||||||
|
.expectHeader().valueEquals(SERVICE_FILTER_RESPONSE_HEADER, SERVICE_FILTER_RESPONSE_HEADER_VALUE);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,172 @@
|
|||||||
|
package org.baeldung.batchscheduler;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.IdentityHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import org.baeldung.batchscheduler.model.Book;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.batch.core.Job;
|
||||||
|
import org.springframework.batch.core.JobExecution;
|
||||||
|
import org.springframework.batch.core.JobParametersBuilder;
|
||||||
|
import org.springframework.batch.core.Step;
|
||||||
|
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
|
||||||
|
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
|
||||||
|
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
|
||||||
|
import org.springframework.batch.core.launch.JobLauncher;
|
||||||
|
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
|
||||||
|
import org.springframework.batch.core.repository.JobRepository;
|
||||||
|
import org.springframework.batch.core.repository.support.MapJobRepositoryFactoryBean;
|
||||||
|
import org.springframework.batch.item.ItemWriter;
|
||||||
|
import org.springframework.batch.item.file.FlatFileItemReader;
|
||||||
|
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
|
||||||
|
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
|
||||||
|
import org.springframework.batch.support.transaction.ResourcelessTransactionManager;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.scheduling.TaskScheduler;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||||
|
import org.springframework.scheduling.support.ScheduledMethodRunnable;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableBatchProcessing
|
||||||
|
@EnableScheduling
|
||||||
|
public class SpringBatchScheduler {
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(SpringBatchScheduler.class);
|
||||||
|
|
||||||
|
private AtomicBoolean enabled = new AtomicBoolean(true);
|
||||||
|
|
||||||
|
private Date currentLaunchDate;
|
||||||
|
|
||||||
|
private final Map<Object, ScheduledFuture<?>> scheduledTasks = new IdentityHashMap<>();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JobBuilderFactory jobBuilderFactory;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private StepBuilderFactory stepBuilderFactory;
|
||||||
|
|
||||||
|
@Scheduled(fixedRate = 2000)
|
||||||
|
public void launchJob() throws Exception {
|
||||||
|
Date date = new Date();
|
||||||
|
logger.debug("scheduler starts at " + date);
|
||||||
|
if (enabled.get()) {
|
||||||
|
currentLaunchDate = date;
|
||||||
|
JobExecution jobExecution = jobLauncher().run(job(), new JobParametersBuilder().addDate("launchDate", currentLaunchDate)
|
||||||
|
.toJobParameters());
|
||||||
|
logger.debug("Batch job ends with status as " + jobExecution.getStatus());
|
||||||
|
}
|
||||||
|
logger.debug("scheduler ends ");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCurrentLaunchDate() {
|
||||||
|
return currentLaunchDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
enabled.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start() {
|
||||||
|
enabled.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public TaskScheduler poolScheduler() {
|
||||||
|
return new CustomTaskScheduler();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CustomTaskScheduler extends ThreadPoolTaskScheduler {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -7142624085505040603L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
|
||||||
|
ScheduledFuture<?> future = super.scheduleAtFixedRate(task, period);
|
||||||
|
|
||||||
|
ScheduledMethodRunnable runnable = (ScheduledMethodRunnable) task;
|
||||||
|
scheduledTasks.put(runnable.getTarget(), future);
|
||||||
|
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void cancelFutureSchedulerTasks() {
|
||||||
|
scheduledTasks.forEach((k, v) -> {
|
||||||
|
if (k instanceof SpringBatchScheduler) {
|
||||||
|
v.cancel(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Job job() {
|
||||||
|
return jobBuilderFactory.get("job")
|
||||||
|
.start(readBooks())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JobLauncher jobLauncher() throws Exception {
|
||||||
|
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
|
||||||
|
jobLauncher.setJobRepository(jobRepository());
|
||||||
|
jobLauncher.afterPropertiesSet();
|
||||||
|
return jobLauncher;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public JobRepository jobRepository() throws Exception {
|
||||||
|
MapJobRepositoryFactoryBean factory = new MapJobRepositoryFactoryBean();
|
||||||
|
factory.setTransactionManager(new ResourcelessTransactionManager());
|
||||||
|
return (JobRepository) factory.getObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
protected Step readBooks() {
|
||||||
|
return stepBuilderFactory.get("readBooks")
|
||||||
|
.<Book, Book> chunk(2)
|
||||||
|
.reader(reader())
|
||||||
|
.writer(writer())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public FlatFileItemReader<Book> reader() {
|
||||||
|
return new FlatFileItemReaderBuilder<Book>().name("bookItemReader")
|
||||||
|
.resource(new ClassPathResource("books.csv"))
|
||||||
|
.delimited()
|
||||||
|
.names(new String[] { "id", "name" })
|
||||||
|
.fieldSetMapper(new BeanWrapperFieldSetMapper<Book>() {
|
||||||
|
{
|
||||||
|
setTargetType(Book.class);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ItemWriter<Book> writer() {
|
||||||
|
return new ItemWriter<Book>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(List<? extends Book> items) throws Exception {
|
||||||
|
logger.debug("writer..." + items.size());
|
||||||
|
for (Book item : items) {
|
||||||
|
logger.debug(item.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user