Merge branch 'master' of https://github.com/eugenp/tutorials into BAEL-3817
This commit is contained in:
commit
c2e96d07f6
core-java-modules/core-java/src
main/java/com/baeldung/timer
test/java/com/baeldung/timer
libraries-3
pom.xml
src
main/java/com/baeldung
cache2k
ProductHelper.javaProductHelperUsingLoader.javaProductHelperWithEventListener.javaProductHelperWithExpiry.java
jcabi
test/java/com/baeldung
lombok-custom
spring-5
spring-batch
src
main
java/org/baeldung/batch
resources
test
java/org/baeldung/batch
resources/output/batchRetry
xml
spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/swagger2boot
spring-boot-rest
pom.xml
src
main
java/com/baeldung
persistence
requestresponsebody
web/controller
resources
test/java/com/baeldung/test
spring-cloud-bus
spring-cloud-config-client/src/test/java/com/baeldung
spring-cloud-config-server/src/test/java/com/baeldung
spring-cloud-data-flow
batch-job
spring-cloud-data-flow-stream-processing
data-flow-server/src
main/java/com/baeldung/spring/cloud
test/java/com/baeldung
data-flow-shell/src
main/java/com/baeldung/spring/cloud
test/java/com/baeldung
log-sink/src
main/java/com/baeldung/spring/cloud
test/java/com/baeldung
time-processor/src
main/java/com/baeldung/spring/cloud
test/java/com/baeldung
time-source/src
main/java/com/baeldung/spring/cloud
test/java/com/baeldung
spring-cloud
spring-cloud-archaius
basic-config/src/test/java/com/baeldung
extra-configs/src/test/java/com/baeldung
spring-cloud-bootstrap
config/src/test/java/com/baeldung
discovery/src/test/java/com/baeldung
gateway/src/test/java/com/baeldung
svc-book/src/test/java/com/baeldung
svc-rating/src/test/java/com/baeldung
zipkin/src/test/java/com/baeldung
spring-cloud-consul
spring-cloud-contract
spring-cloud-contract-consumer/src/test/java/com/baeldung
spring-cloud-contract-producer/src/test/java/com/baeldung
spring-cloud-kubernetes
kubernetes-guide/client-service/src/test/java/com/baeldung
kubernetes-minikube
demo-backend/src/test/java/com/baeldung
demo-frontend/src/test/java/com/baeldung
spring-cloud-rest
@ -1,4 +1,4 @@
|
||||
package com.baeldung;
|
||||
package com.baeldung.timer;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.slf4j.Logger;
|
@ -73,6 +73,28 @@
|
||||
<version>${cache2k.version}</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.moshi</groupId>
|
||||
<artifactId>moshi</artifactId>
|
||||
<version>${moshi.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.squareup.moshi</groupId>
|
||||
<artifactId>moshi-adapters</artifactId>
|
||||
<version>${moshi.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.jcabi</groupId>
|
||||
<artifactId>jcabi-aspects</artifactId>
|
||||
<version>${jcabi-aspects.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjrt</artifactId>
|
||||
<version>${aspectjrt.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
@ -81,6 +103,36 @@
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<build>
|
||||
<finalName>libraries-3</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.jcabi</groupId>
|
||||
<artifactId>jcabi-maven-plugin</artifactId>
|
||||
<version>${jcabi-maven-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>ajc</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjtools</artifactId>
|
||||
<version>${aspectjtools.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
<version>${aspectjweaver.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<jcommander.version>1.78</jcommander.version>
|
||||
@ -93,5 +145,11 @@
|
||||
<cactoos.version>0.43</cactoos.version>
|
||||
<airline.version>2.7.2</airline.version>
|
||||
<cache2k.version>1.2.3.Final</cache2k.version>
|
||||
<moshi.version>1.9.2</moshi.version>
|
||||
<jcabi-aspects.version>0.22.6</jcabi-aspects.version>
|
||||
<aspectjrt.version>1.9.2</aspectjrt.version>
|
||||
<jcabi-maven-plugin.version>0.14.1</jcabi-maven-plugin.version>
|
||||
<aspectjtools.version>1.9.2</aspectjtools.version>
|
||||
<aspectjweaver.version>1.9.2</aspectjweaver.version>
|
||||
</properties>
|
||||
</project>
|
||||
|
@ -4,38 +4,33 @@ import java.util.Objects;
|
||||
|
||||
import org.cache2k.Cache;
|
||||
import org.cache2k.Cache2kBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ProductHelper {
|
||||
|
||||
final Logger LOGGER = LoggerFactory.getLogger(ProductHelper.class);
|
||||
|
||||
private Cache<String, Integer> cachedDiscounts;
|
||||
|
||||
private int cacheMissCount = 0;
|
||||
|
||||
public ProductHelper() {
|
||||
cachedDiscounts = Cache2kBuilder.of(String.class, Integer.class)
|
||||
.name("discount")
|
||||
.eternal(true)
|
||||
.entryCapacity(100)
|
||||
.build();
|
||||
|
||||
initDiscountCache("Sports", 20);
|
||||
}
|
||||
|
||||
public void initDiscountCache(String productType, Integer value) {
|
||||
cachedDiscounts.put(productType, value);
|
||||
}
|
||||
|
||||
public Integer getDiscount(String productType) {
|
||||
Integer discount = cachedDiscounts.get(productType);
|
||||
if (Objects.isNull(discount)) {
|
||||
LOGGER.info("Discount for {} not found.", productType);
|
||||
discount = 0;
|
||||
} else {
|
||||
LOGGER.info("Discount for {} found.", productType);
|
||||
cacheMissCount++;
|
||||
discount = "Sports".equalsIgnoreCase(productType) ? 20 : 10;
|
||||
cachedDiscounts.put(productType, discount);
|
||||
}
|
||||
return discount;
|
||||
}
|
||||
|
||||
public int getCacheMissCount() {
|
||||
return cacheMissCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.baeldung.cache2k;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.cache2k.Cache;
|
||||
@ -14,28 +13,26 @@ public class ProductHelperUsingLoader {
|
||||
|
||||
private Cache<String, Integer> cachedDiscounts;
|
||||
|
||||
private int cacheMissCount = 0;
|
||||
|
||||
public ProductHelperUsingLoader() {
|
||||
cachedDiscounts = Cache2kBuilder.of(String.class, Integer.class)
|
||||
.name("discount-loader")
|
||||
.eternal(false)
|
||||
.expireAfterWrite(10, TimeUnit.MILLISECONDS)
|
||||
.entryCapacity(100)
|
||||
.loader((key) -> {
|
||||
LOGGER.info("Calculating discount for {}.", key);
|
||||
cacheMissCount++;
|
||||
return "Sports".equalsIgnoreCase(key) ? 20 : 10;
|
||||
})
|
||||
.build();
|
||||
}
|
||||
|
||||
public Integer getDiscount(String productType) {
|
||||
Integer discount = cachedDiscounts.get(productType);
|
||||
if (Objects.isNull(discount)) {
|
||||
LOGGER.info("Discount for {} not found.", productType);
|
||||
discount = 0;
|
||||
} else {
|
||||
LOGGER.info("Discount for {} found.", productType);
|
||||
}
|
||||
return discount;
|
||||
return cachedDiscounts.get(productType);
|
||||
}
|
||||
|
||||
public int getCacheMissCount() {
|
||||
return cacheMissCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.baeldung.cache2k;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.cache2k.Cache;
|
||||
@ -16,14 +15,15 @@ public class ProductHelperWithEventListener {
|
||||
|
||||
private Cache<String, Integer> cachedDiscounts;
|
||||
|
||||
private int cacheMissCount = 0;
|
||||
|
||||
public ProductHelperWithEventListener() {
|
||||
cachedDiscounts = Cache2kBuilder.of(String.class, Integer.class)
|
||||
.name("discount-listener")
|
||||
.eternal(false)
|
||||
.expireAfterWrite(10, TimeUnit.MILLISECONDS)
|
||||
.entryCapacity(100)
|
||||
.loader((key) -> {
|
||||
LOGGER.info("Calculating discount for {}.", key);
|
||||
cacheMissCount++;
|
||||
return "Sports".equalsIgnoreCase(key) ? 20 : 10;
|
||||
})
|
||||
.addListener(new CacheEntryCreatedListener<String, Integer>() {
|
||||
@ -36,14 +36,11 @@ public class ProductHelperWithEventListener {
|
||||
}
|
||||
|
||||
public Integer getDiscount(String productType) {
|
||||
Integer discount = cachedDiscounts.get(productType);
|
||||
if (Objects.isNull(discount)) {
|
||||
LOGGER.info("Discount for {} not found.", productType);
|
||||
discount = 0;
|
||||
} else {
|
||||
LOGGER.info("Discount for {} found.", productType);
|
||||
}
|
||||
return discount;
|
||||
return cachedDiscounts.get(productType);
|
||||
}
|
||||
|
||||
public int getCacheMissCount() {
|
||||
return cacheMissCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,39 +5,34 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.cache2k.Cache;
|
||||
import org.cache2k.Cache2kBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class ProductHelperWithExpiry {
|
||||
|
||||
final Logger LOGGER = LoggerFactory.getLogger(ProductHelperWithExpiry.class);
|
||||
|
||||
private Cache<String, Integer> cachedDiscounts;
|
||||
|
||||
private int cacheMissCount = 0;
|
||||
|
||||
public ProductHelperWithExpiry() {
|
||||
cachedDiscounts = Cache2kBuilder.of(String.class, Integer.class)
|
||||
.name("discount-expiry")
|
||||
.eternal(false)
|
||||
.expireAfterWrite(5, TimeUnit.MILLISECONDS)
|
||||
.entryCapacity(100)
|
||||
.build();
|
||||
|
||||
initDiscountCache("Sports", 20);
|
||||
}
|
||||
|
||||
public void initDiscountCache(String productType, Integer value) {
|
||||
cachedDiscounts.put(productType, value);
|
||||
}
|
||||
|
||||
public Integer getDiscount(String productType) {
|
||||
Integer discount = cachedDiscounts.get(productType);
|
||||
if (Objects.isNull(discount)) {
|
||||
LOGGER.info("Discount for {} not found.", productType);
|
||||
discount = 0;
|
||||
} else {
|
||||
LOGGER.info("Discount for {} found.", productType);
|
||||
cacheMissCount++;
|
||||
discount = "Sports".equalsIgnoreCase(productType) ? 20 : 10;
|
||||
cachedDiscounts.put(productType, discount);
|
||||
}
|
||||
return discount;
|
||||
}
|
||||
|
||||
public int getCacheMissCount() {
|
||||
return cacheMissCount;
|
||||
}
|
||||
|
||||
}
|
||||
|
112
libraries-3/src/main/java/com/baeldung/jcabi/JcabiAspectJ.java
Normal file
112
libraries-3/src/main/java/com/baeldung/jcabi/JcabiAspectJ.java
Normal file
@ -0,0 +1,112 @@
|
||||
package com.baeldung.jcabi;
|
||||
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.jcabi.aspects.Async;
|
||||
import com.jcabi.aspects.Cacheable;
|
||||
import com.jcabi.aspects.LogExceptions;
|
||||
import com.jcabi.aspects.Loggable;
|
||||
import com.jcabi.aspects.Quietly;
|
||||
import com.jcabi.aspects.RetryOnFailure;
|
||||
import com.jcabi.aspects.UnitedThrow;
|
||||
|
||||
public class JcabiAspectJ {
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
displayFactorial(10);
|
||||
getFactorial(10).get();
|
||||
|
||||
String result = cacheExchangeRates();
|
||||
if (result != cacheExchangeRates()) {
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
divideByZero();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
divideByZeroQuietly();
|
||||
try {
|
||||
processFile();
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Loggable
|
||||
@Async
|
||||
public static void displayFactorial(int number) {
|
||||
long result = factorial(number);
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
@Loggable
|
||||
@Async
|
||||
public static Future<Long> getFactorial(int number) {
|
||||
Future<Long> factorialFuture = CompletableFuture.supplyAsync(() -> factorial(number));
|
||||
return factorialFuture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds factorial of a number
|
||||
* @param number
|
||||
* @return
|
||||
*/
|
||||
public static long factorial(int number) {
|
||||
long result = 1;
|
||||
for(int i=number;i>0;i--) {
|
||||
result *= i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Loggable
|
||||
@Cacheable(lifetime = 2, unit = TimeUnit.SECONDS)
|
||||
public static String cacheExchangeRates() {
|
||||
String result = null;
|
||||
try {
|
||||
URL exchangeRateUrl = new URL("https://api.exchangeratesapi.io/latest");
|
||||
URLConnection con = exchangeRateUrl.openConnection();
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
|
||||
result = in.readLine();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@LogExceptions
|
||||
public static void divideByZero() {
|
||||
int x = 1/0;
|
||||
}
|
||||
|
||||
@RetryOnFailure(attempts = 2, types = {java.lang.NumberFormatException.class})
|
||||
@Quietly
|
||||
public static void divideByZeroQuietly() {
|
||||
int x = 1/0;
|
||||
}
|
||||
|
||||
@UnitedThrow(IllegalStateException.class)
|
||||
public static void processFile() throws IOException, InterruptedException {
|
||||
BufferedReader reader = new BufferedReader(new FileReader("baeldung.txt"));
|
||||
reader.readLine();
|
||||
|
||||
Thread thread = new Thread();
|
||||
thread.wait(2000);
|
||||
}
|
||||
|
||||
}
|
@ -6,12 +6,13 @@ import org.junit.Test;
|
||||
|
||||
public class ProductHelperUnitTest {
|
||||
|
||||
ProductHelper productHelper = new ProductHelper();
|
||||
|
||||
@Test
|
||||
public void whenInvokedGetDiscount_thenGetItFromCache() {
|
||||
public void whenInvokedGetDiscountTwice_thenGetItFromCache() {
|
||||
ProductHelper productHelper = new ProductHelper();
|
||||
assertTrue(productHelper.getCacheMissCount() == 0);
|
||||
assertTrue(productHelper.getDiscount("Sports") == 20);
|
||||
assertTrue(productHelper.getDiscount("Electronics") == 0);
|
||||
assertTrue(productHelper.getDiscount("Sports") == 20);
|
||||
assertTrue(productHelper.getCacheMissCount() == 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,12 +6,16 @@ import org.junit.Test;
|
||||
|
||||
public class ProductHelperUsingLoaderUnitTest {
|
||||
|
||||
ProductHelperUsingLoader productHelper = new ProductHelperUsingLoader();
|
||||
|
||||
@Test
|
||||
public void whenInvokedGetDiscount_thenPopulateCache() {
|
||||
public void whenInvokedGetDiscount_thenPopulateCacheUsingLoader() {
|
||||
ProductHelperUsingLoader productHelper = new ProductHelperUsingLoader();
|
||||
assertTrue(productHelper.getCacheMissCount() == 0);
|
||||
|
||||
assertTrue(productHelper.getDiscount("Sports") == 20);
|
||||
assertTrue(productHelper.getCacheMissCount() == 1);
|
||||
|
||||
assertTrue(productHelper.getDiscount("Electronics") == 10);
|
||||
assertTrue(productHelper.getCacheMissCount() == 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,10 +6,9 @@ import org.junit.Test;
|
||||
|
||||
public class ProductHelperWithEventListenerUnitTest {
|
||||
|
||||
ProductHelperWithEventListener productHelper = new ProductHelperWithEventListener();
|
||||
|
||||
@Test
|
||||
public void whenEntryAddedInCache_thenEventListenerCalled() {
|
||||
ProductHelperWithEventListener productHelper = new ProductHelperWithEventListener();
|
||||
assertTrue(productHelper.getDiscount("Sports") == 20);
|
||||
}
|
||||
|
||||
|
@ -6,13 +6,17 @@ import org.junit.Test;
|
||||
|
||||
public class ProductHelperWithExpiryUnitTest {
|
||||
|
||||
ProductHelperWithExpiry productHelper = new ProductHelperWithExpiry();
|
||||
|
||||
@Test
|
||||
public void whenInvokedGetDiscountForExpiredProduct_thenNoDiscount() throws InterruptedException {
|
||||
public void whenInvokedGetDiscountAfterExpiration_thenDiscountCalculatedAgain() throws InterruptedException {
|
||||
ProductHelperWithExpiry productHelper = new ProductHelperWithExpiry();
|
||||
assertTrue(productHelper.getCacheMissCount() == 0);
|
||||
assertTrue(productHelper.getDiscount("Sports") == 20);
|
||||
assertTrue(productHelper.getCacheMissCount() == 1);
|
||||
|
||||
Thread.sleep(20);
|
||||
assertTrue(productHelper.getDiscount("Sports") == 0);
|
||||
|
||||
assertTrue(productHelper.getDiscount("Sports") == 20);
|
||||
assertTrue(productHelper.getCacheMissCount() == 2);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,105 @@
|
||||
package com.baeldung.moshi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.time.Instant;
|
||||
|
||||
import com.squareup.moshi.FromJson;
|
||||
import com.squareup.moshi.JsonAdapter;
|
||||
import com.squareup.moshi.JsonQualifier;
|
||||
import com.squareup.moshi.Moshi;
|
||||
import com.squareup.moshi.ToJson;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.junit.Test;
|
||||
|
||||
public class AlternativeAdapterUnitTest {
|
||||
@Test
|
||||
public void whenSerializing_thenAlternativeAdapterUsed() {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.add(new EpochMillisAdapter())
|
||||
.build();
|
||||
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
|
||||
|
||||
String json = jsonAdapter.toJson(new Post("Introduction to Moshi Json", "Baeldung", Instant.now()));
|
||||
System.out.println(json);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDeserializing_thenAlternativeAdapterUsed() throws IOException {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.add(new EpochMillisAdapter())
|
||||
.build();
|
||||
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
|
||||
|
||||
String json = "{\"author\":\"Baeldung\",\"posted\":1582095269204,\"title\":\"Introduction to Moshi Json\"}";
|
||||
Post post = jsonAdapter.fromJson(json);
|
||||
System.out.println(post);
|
||||
|
||||
}
|
||||
|
||||
public static class Post {
|
||||
String title;
|
||||
String author;
|
||||
@EpochMillis Instant posted;
|
||||
|
||||
public Post() {
|
||||
}
|
||||
|
||||
public Post(String title, String author, Instant posted) {
|
||||
this.title = title;
|
||||
this.author = author;
|
||||
this.posted = posted;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public Instant getPosted() {
|
||||
return posted;
|
||||
}
|
||||
|
||||
public void setPosted(Instant posted) {
|
||||
this.posted = posted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this).append("title", title).append("author", author).append("posted", posted)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
|
||||
@JsonQualifier
|
||||
public @interface EpochMillis {
|
||||
}
|
||||
|
||||
public static class EpochMillisAdapter {
|
||||
@ToJson
|
||||
public Long toJson(@EpochMillis Instant input) {
|
||||
return input.toEpochMilli();
|
||||
}
|
||||
@FromJson
|
||||
@EpochMillis
|
||||
public Instant fromJson(Long input) {
|
||||
return Instant.ofEpochMilli(input);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package com.baeldung.moshi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import com.squareup.moshi.JsonAdapter;
|
||||
import com.squareup.moshi.Moshi;
|
||||
import com.squareup.moshi.Types;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ArrayUnitTest {
|
||||
@Test
|
||||
public void whenSerializingList_thenJsonArrayProduced() {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.build();
|
||||
Type type = Types.newParameterizedType(List.class, String.class);
|
||||
JsonAdapter<List<String>> jsonAdapter = moshi.adapter(type);
|
||||
|
||||
String json = jsonAdapter.toJson(Arrays.asList("One", "Two", "Three"));
|
||||
System.out.println(json);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDeserializingJsonArray_thenListProduced() throws IOException {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.build();
|
||||
Type type = Types.newParameterizedType(List.class, String.class);
|
||||
JsonAdapter<List<String>> jsonAdapter = moshi.adapter(type);
|
||||
|
||||
String json = "[\"One\",\"Two\",\"Three\"]";
|
||||
List<String> result = jsonAdapter.fromJson(json);
|
||||
System.out.println(result);
|
||||
}
|
||||
}
|
@ -0,0 +1,94 @@
|
||||
package com.baeldung.moshi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import com.squareup.moshi.FromJson;
|
||||
import com.squareup.moshi.JsonAdapter;
|
||||
import com.squareup.moshi.Moshi;
|
||||
import com.squareup.moshi.ToJson;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ComplexAdapterUnitTest {
|
||||
@Test
|
||||
public void whenSerializing_thenCorrectJsonProduced() {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.add(new JsonDateTimeAdapter())
|
||||
.build();
|
||||
JsonAdapter<ZonedDateTime> jsonAdapter = moshi.adapter(ZonedDateTime.class);
|
||||
|
||||
String json = jsonAdapter.toJson(ZonedDateTime.now());
|
||||
System.out.println(json);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDeserializing_thenCorrectJsonConsumed() throws IOException {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.add(new JsonDateTimeAdapter())
|
||||
.build();
|
||||
JsonAdapter<ZonedDateTime> jsonAdapter = moshi.adapter(ZonedDateTime.class);
|
||||
|
||||
String json = "{\"date\":\"2020-02-17\",\"time\":\"07:53:27.064\",\"timezone\":\"Europe/London\"}";
|
||||
ZonedDateTime now = jsonAdapter.fromJson(json);
|
||||
System.out.println(now);
|
||||
|
||||
}
|
||||
|
||||
public static class JsonDateTimeAdapter {
|
||||
@ToJson
|
||||
public JsonDateTime toJson(ZonedDateTime input) {
|
||||
String date = input.toLocalDate().toString();
|
||||
String time = input.toLocalTime().toString();
|
||||
String timezone = input.getZone().toString();
|
||||
return new JsonDateTime(date, time, timezone);
|
||||
}
|
||||
@FromJson
|
||||
public ZonedDateTime fromJson(JsonDateTime input) {
|
||||
LocalDate date = LocalDate.parse(input.getDate());
|
||||
LocalTime time = LocalTime.parse(input.getTime());
|
||||
ZoneId timezone = ZoneId.of(input.getTimezone());
|
||||
return ZonedDateTime.of(date, time, timezone);
|
||||
}
|
||||
}
|
||||
public static class JsonDateTime {
|
||||
private String date;
|
||||
private String time;
|
||||
private String timezone;
|
||||
|
||||
public JsonDateTime() {
|
||||
}
|
||||
|
||||
public JsonDateTime(String date, String time, String timezone) {
|
||||
this.date = date;
|
||||
this.time = time;
|
||||
this.timezone = timezone;
|
||||
}
|
||||
|
||||
public String getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(String date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public String getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(String time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getTimezone() {
|
||||
return timezone;
|
||||
}
|
||||
|
||||
public void setTimezone(String timezone) {
|
||||
this.timezone = timezone;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.baeldung.moshi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Instant;
|
||||
|
||||
import com.squareup.moshi.JsonAdapter;
|
||||
import com.squareup.moshi.Moshi;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.junit.Test;
|
||||
|
||||
public class DefaultUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenDeserializing_thenFieldsGetDefaultValues() throws IOException {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.build();
|
||||
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
|
||||
|
||||
String json = "{\"title\":\"My Post\"}";
|
||||
Post post = jsonAdapter.fromJson(json);
|
||||
System.out.println(post);
|
||||
}
|
||||
public static class Post {
|
||||
private String title;
|
||||
private String author;
|
||||
private String posted;
|
||||
|
||||
public Post() {
|
||||
posted = Instant.now().toString();
|
||||
}
|
||||
|
||||
public Post(String title, String author, String posted) {
|
||||
this.title = title;
|
||||
this.author = author;
|
||||
this.posted = posted;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public String getPosted() {
|
||||
return posted;
|
||||
}
|
||||
|
||||
public void setPosted(String posted) {
|
||||
this.posted = posted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this).append("title", title).append("author", author).append("posted", posted)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package com.baeldung.moshi;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.squareup.moshi.JsonAdapter;
|
||||
import com.squareup.moshi.Moshi;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.junit.Test;
|
||||
|
||||
public class PrimitiveUnitTest {
|
||||
@Test
|
||||
public void whenSerializing_thenCorrectJsonProduced() {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.build();
|
||||
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
|
||||
|
||||
Post post = new Post("My Post", "Baeldung", "This is my post");
|
||||
String json = jsonAdapter.toJson(post);
|
||||
System.out.println(json);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDeserializing_thenCorrectJsonConsumed() throws IOException {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.build();
|
||||
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
|
||||
|
||||
String json = "{\"author\":\"Baeldung\",\"text\":\"This is my post\",\"title\":\"My Post\"}";
|
||||
Post post = jsonAdapter.fromJson(json);
|
||||
System.out.println(post);
|
||||
}
|
||||
|
||||
public static class Post {
|
||||
private String title;
|
||||
private String author;
|
||||
private String text;
|
||||
|
||||
public Post() {
|
||||
}
|
||||
|
||||
public Post(String title, String author, String text) {
|
||||
this.title = title;
|
||||
this.author = author;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this).append("title", title).append("author", author).append("text", text)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.baeldung.moshi;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.squareup.moshi.Json;
|
||||
import com.squareup.moshi.JsonAdapter;
|
||||
import com.squareup.moshi.Moshi;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class RenameUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenSerializing_thenFieldsGetRenamed() {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.build();
|
||||
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
|
||||
|
||||
Post post = new Post("My Post", "Baeldung");
|
||||
String json = jsonAdapter.toJson(post);
|
||||
System.out.println(json);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenSerializing_thenRenamedFieldsGetConsumed() throws IOException {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.build();
|
||||
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
|
||||
|
||||
String json = "{\"authored_by\":\"Baeldung\",\"title\":\"My Post\"}";
|
||||
Post post = jsonAdapter.fromJson(json);
|
||||
System.out.println(post);
|
||||
}
|
||||
public static class Post {
|
||||
private String title;
|
||||
@Json(name = "authored_by")
|
||||
private String author;
|
||||
|
||||
public Post() {
|
||||
}
|
||||
|
||||
public Post(String title, String author) {
|
||||
this.title = title;
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this).append("title", title).append("author", author).toString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
package com.baeldung.moshi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.squareup.moshi.FromJson;
|
||||
import com.squareup.moshi.JsonAdapter;
|
||||
import com.squareup.moshi.Moshi;
|
||||
import com.squareup.moshi.ToJson;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SimpleAdapterUnitTest {
|
||||
@Test
|
||||
public void whenSerializing_thenAdapterUsed() {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.add(new AuthorAdapter())
|
||||
.build();
|
||||
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
|
||||
|
||||
Post post = new Post("My Post", new Author("Baeldung", "baeldung@example.com"), "This is my post");
|
||||
String json = jsonAdapter.toJson(post);
|
||||
System.out.println(json);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDeserializing_thenAdapterUsed() throws IOException {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.add(new AuthorAdapter())
|
||||
.build();
|
||||
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
|
||||
|
||||
String json = "{\"author\":\"Baeldung <baeldung@example.com>\",\"text\":\"This is my post\",\"title\":\"My Post\"}";
|
||||
Post post = jsonAdapter.fromJson(json);
|
||||
System.out.println(post);
|
||||
}
|
||||
public static class AuthorAdapter {
|
||||
private Pattern pattern = Pattern.compile("^(.*) <(.*)>$");
|
||||
@ToJson
|
||||
public String toJson(Author author) {
|
||||
return author.name + " <" + author.email + ">";
|
||||
}
|
||||
|
||||
@FromJson
|
||||
public Author fromJson(String author) {
|
||||
Matcher matcher = pattern.matcher(author);
|
||||
return matcher.find() ? new Author(matcher.group(1), matcher.group(2)) : null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Author {
|
||||
private String name;
|
||||
private String email;
|
||||
|
||||
public Author() {
|
||||
}
|
||||
|
||||
public Author(String name, String email) {
|
||||
this.name = name;
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this).append("name", name).append("email", email).toString();
|
||||
}
|
||||
}
|
||||
public static class Post {
|
||||
private String title;
|
||||
private Author author;
|
||||
private String text;
|
||||
|
||||
public Post() {
|
||||
}
|
||||
|
||||
public Post(String title, Author author, String text) {
|
||||
this.title = title;
|
||||
this.author = author;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public Author getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(Author author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public void setText(String text) {
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this).append("title", title).append("author", author).append("text", text)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package com.baeldung.moshi;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.squareup.moshi.JsonAdapter;
|
||||
import com.squareup.moshi.Moshi;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class TransientUnitTest {
|
||||
|
||||
@Test
|
||||
public void whenSerializing_thenTransientFieldIgnored() {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.build();
|
||||
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
|
||||
|
||||
Post post = new Post("My Post", "Baeldung");
|
||||
String json = jsonAdapter.toJson(post);
|
||||
System.out.println(json);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDeserializing_thenTransientFieldIgnored() throws IOException {
|
||||
Moshi moshi = new Moshi.Builder()
|
||||
.build();
|
||||
JsonAdapter<Post> jsonAdapter = moshi.adapter(Post.class);
|
||||
|
||||
String json = "{\"authored_by\":\"Baeldung\",\"title\":\"My Post\"}";
|
||||
Post post = jsonAdapter.fromJson(json);
|
||||
System.out.println(post);
|
||||
}
|
||||
public static class Post {
|
||||
private String title;
|
||||
private transient String author;
|
||||
|
||||
public Post() {
|
||||
}
|
||||
|
||||
public Post(String title, String author) {
|
||||
this.title = title;
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getAuthor() {
|
||||
return author;
|
||||
}
|
||||
|
||||
public void setAuthor(String author) {
|
||||
this.author = author;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this).append("title", title).append("author", author).toString();
|
||||
}
|
||||
}
|
||||
}
|
@ -36,12 +36,12 @@
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>default-tools.jar</id>
|
||||
<id>default-profile</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>java.vendor</name>
|
||||
<value>Oracle Corporation</value>
|
||||
</property>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
<file>
|
||||
<exists>${java.home}/../lib/tools.jar</exists>
|
||||
</file>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@ -53,6 +53,24 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>mac-profile</id>
|
||||
<activation>
|
||||
<activeByDefault>false</activeByDefault>
|
||||
<file>
|
||||
<exists>${java.home}/../Classes/classes.jar</exists>
|
||||
</file>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.sun</groupId>
|
||||
<artifactId>tools</artifactId>
|
||||
<version>${java.version}</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${java.home}/../Classes/classes.jar</systemPath>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<properties>
|
||||
|
@ -149,7 +149,6 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<spring-boot.version>2.1.9.RELEASE</spring-boot.version>
|
||||
<geronimo-json_1.1_spec.version>1.0</geronimo-json_1.1_spec.version>
|
||||
<asciidoctor-plugin.version>1.5.6</asciidoctor-plugin.version>
|
||||
<commons-collections4.version>4.1</commons-collections4.version>
|
||||
|
@ -1,6 +1,6 @@
|
||||
package com.baeldung.restdocs;
|
||||
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -1,21 +1,25 @@
|
||||
package com.baeldung.restdocs;
|
||||
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.RepresentationModel;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/")
|
||||
public class IndexController {
|
||||
|
||||
@GetMapping
|
||||
public ResourceSupport index() {
|
||||
ResourceSupport index = new ResourceSupport();
|
||||
index.add(linkTo(CRUDController.class).withRel("crud"));
|
||||
return index;
|
||||
static class CustomRepresentationModel extends RepresentationModel<CustomRepresentationModel> {
|
||||
public CustomRepresentationModel(Link initialLink) {
|
||||
super(initialLink);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public CustomRepresentationModel index() {
|
||||
return new CustomRepresentationModel(linkTo(CRUDController.class).withRel("crud"));
|
||||
}
|
||||
}
|
@ -18,6 +18,8 @@ public class App {
|
||||
final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
context.register(SpringConfig.class);
|
||||
context.register(SpringBatchConfig.class);
|
||||
context.register(SpringBatchRetryConfig.class);
|
||||
|
||||
context.refresh();
|
||||
|
||||
// Spring xml config
|
||||
@ -26,6 +28,8 @@ public class App {
|
||||
runJob(context, "firstBatchJob");
|
||||
runJob(context, "skippingBatchJob");
|
||||
runJob(context, "skipPolicyBatchJob");
|
||||
runJob(context, "retryBatchJob");
|
||||
|
||||
}
|
||||
|
||||
private static void runJob(AnnotationConfigApplicationContext context, String batchJobName) {
|
||||
|
@ -0,0 +1,117 @@
|
||||
package org.baeldung.batch;
|
||||
|
||||
import org.apache.http.client.config.RequestConfig;
|
||||
import org.apache.http.conn.ConnectTimeoutException;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.baeldung.batch.model.Transaction;
|
||||
import org.baeldung.batch.service.RecordFieldSetMapper;
|
||||
import org.baeldung.batch.service.RetryItemProcessor;
|
||||
import org.springframework.batch.core.Job;
|
||||
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.item.ItemProcessor;
|
||||
import org.springframework.batch.item.ItemReader;
|
||||
import org.springframework.batch.item.ItemWriter;
|
||||
import org.springframework.batch.item.file.FlatFileItemReader;
|
||||
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
|
||||
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
|
||||
import org.springframework.batch.item.xml.StaxEventItemWriter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.dao.DeadlockLoserDataAccessException;
|
||||
import org.springframework.oxm.Marshaller;
|
||||
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
@Configuration
|
||||
@EnableBatchProcessing
|
||||
public class SpringBatchRetryConfig {
|
||||
|
||||
private static final String[] tokens = { "username", "userid", "transactiondate", "amount" };
|
||||
private static final int TWO_SECONDS = 2000;
|
||||
|
||||
@Autowired
|
||||
private JobBuilderFactory jobBuilderFactory;
|
||||
|
||||
@Autowired
|
||||
private StepBuilderFactory stepBuilderFactory;
|
||||
|
||||
@Value("input/recordRetry.csv")
|
||||
private Resource inputCsv;
|
||||
|
||||
@Value("file:xml/retryOutput.xml")
|
||||
private Resource outputXml;
|
||||
|
||||
public ItemReader<Transaction> itemReader(Resource inputData) throws ParseException {
|
||||
DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
|
||||
tokenizer.setNames(tokens);
|
||||
DefaultLineMapper<Transaction> lineMapper = new DefaultLineMapper<>();
|
||||
lineMapper.setLineTokenizer(tokenizer);
|
||||
lineMapper.setFieldSetMapper(new RecordFieldSetMapper());
|
||||
FlatFileItemReader<Transaction> reader = new FlatFileItemReader<>();
|
||||
reader.setResource(inputData);
|
||||
reader.setLinesToSkip(1);
|
||||
reader.setLineMapper(lineMapper);
|
||||
return reader;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CloseableHttpClient closeableHttpClient() {
|
||||
final RequestConfig config = RequestConfig.custom()
|
||||
.setConnectTimeout(TWO_SECONDS)
|
||||
.build();
|
||||
return HttpClientBuilder.create().setDefaultRequestConfig(config).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ItemProcessor<Transaction, Transaction> retryItemProcessor() {
|
||||
return new RetryItemProcessor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ItemWriter<Transaction> itemWriter(Marshaller marshaller) {
|
||||
StaxEventItemWriter<Transaction> itemWriter = new StaxEventItemWriter<>();
|
||||
itemWriter.setMarshaller(marshaller);
|
||||
itemWriter.setRootTagName("transactionRecord");
|
||||
itemWriter.setResource(outputXml);
|
||||
return itemWriter;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Marshaller marshaller() {
|
||||
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
|
||||
marshaller.setClassesToBeBound(Transaction.class);
|
||||
return marshaller;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Step retryStep(@Qualifier("retryItemProcessor") ItemProcessor<Transaction, Transaction> processor,
|
||||
ItemWriter<Transaction> writer) throws ParseException {
|
||||
return stepBuilderFactory.get("retryStep")
|
||||
.<Transaction, Transaction>chunk(10)
|
||||
.reader(itemReader(inputCsv))
|
||||
.processor(processor)
|
||||
.writer(writer)
|
||||
.faultTolerant()
|
||||
.retryLimit(3)
|
||||
.retry(ConnectTimeoutException.class)
|
||||
.retry(DeadlockLoserDataAccessException.class)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean(name = "retryBatchJob")
|
||||
public Job retryJob(@Qualifier("retryStep") Step retryStep) {
|
||||
return jobBuilderFactory
|
||||
.get("retryBatchJob")
|
||||
.start(retryStep)
|
||||
.build();
|
||||
}
|
||||
}
|
@ -9,6 +9,8 @@ import javax.xml.bind.annotation.XmlRootElement;
|
||||
public class Transaction {
|
||||
private String username;
|
||||
private int userId;
|
||||
private int age;
|
||||
private String postCode;
|
||||
private Date transactionDate;
|
||||
private double amount;
|
||||
|
||||
@ -46,9 +48,25 @@ public class Transaction {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getPostCode() {
|
||||
return postCode;
|
||||
}
|
||||
|
||||
public void setPostCode(String postCode) {
|
||||
this.postCode = postCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Transaction [username=" + username + ", userId=" + userId + ", transactionDate=" + transactionDate + ", amount=" + amount + "]";
|
||||
return "Transaction [username=" + username + ", userId=" + userId + ", age=" + age + ", postCode=" + postCode + ", transactionDate=" + transactionDate + ", amount=" + amount + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
package org.baeldung.batch.service;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.baeldung.batch.model.Transaction;
|
||||
import org.codehaus.jettison.json.JSONException;
|
||||
import org.codehaus.jettison.json.JSONObject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.batch.item.ItemProcessor;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class RetryItemProcessor implements ItemProcessor<Transaction, Transaction> {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RetryItemProcessor.class);
|
||||
|
||||
@Autowired
|
||||
private CloseableHttpClient closeableHttpClient;
|
||||
|
||||
@Override
|
||||
public Transaction process(Transaction transaction) throws IOException, JSONException {
|
||||
LOGGER.info("Attempting to process user with id={}", transaction.getUserId());
|
||||
HttpResponse response = fetchMoreUserDetails(transaction.getUserId());
|
||||
|
||||
//parse user's age and postCode from response and update transaction
|
||||
String result = EntityUtils.toString(response.getEntity());
|
||||
JSONObject userObject = new JSONObject(result);
|
||||
transaction.setAge(Integer.parseInt(userObject.getString("age")));
|
||||
transaction.setPostCode(userObject.getString("postCode"));
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
private HttpResponse fetchMoreUserDetails(int id) throws IOException {
|
||||
final HttpGet request = new HttpGet("http://www.baeldung.com:81/user/" + id);
|
||||
return closeableHttpClient.execute(request);
|
||||
}
|
||||
}
|
3
spring-batch/src/main/resources/input/recordRetry.csv
Normal file
3
spring-batch/src/main/resources/input/recordRetry.csv
Normal file
@ -0,0 +1,3 @@
|
||||
username, user_id, transaction_date, transaction_amount
|
||||
sammy, 1234, 31/10/2015, 10000
|
||||
john, 9999, 3/12/2015, 12321
|
|
@ -54,4 +54,19 @@
|
||||
</batch:tasklet>
|
||||
</batch:step>
|
||||
</batch:job>
|
||||
|
||||
<batch:job id="retryBatchJob">
|
||||
<batch:step id="retryStep">
|
||||
<batch:tasklet>
|
||||
<batch:chunk reader="itemReader" writer="itemWriter"
|
||||
processor="retryItemProcessor" commit-interval="10"
|
||||
retry-limit="3">
|
||||
<batch:retryable-exception-classes>
|
||||
<batch:include class="org.apache.http.conn.ConnectTimeoutException"/>
|
||||
<batch:include class="org.springframework.dao.DeadlockLoserDataAccessException"/>
|
||||
</batch:retryable-exception-classes>
|
||||
</batch:chunk>
|
||||
</batch:tasklet>
|
||||
</batch:step>
|
||||
</batch:job>
|
||||
</beans>
|
||||
|
@ -0,0 +1,90 @@
|
||||
package org.baeldung.batch;
|
||||
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.conn.ConnectTimeoutException;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.springframework.batch.core.ExitStatus;
|
||||
import org.springframework.batch.core.JobExecution;
|
||||
import org.springframework.batch.core.JobInstance;
|
||||
import org.springframework.batch.core.JobParameters;
|
||||
import org.springframework.batch.core.JobParametersBuilder;
|
||||
import org.springframework.batch.test.AssertFile;
|
||||
import org.springframework.batch.test.JobLauncherTestUtils;
|
||||
import org.springframework.batch.test.context.SpringBatchTest;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBatchTest
|
||||
@EnableAutoConfiguration
|
||||
@ContextConfiguration(classes = { SpringBatchRetryConfig.class })
|
||||
public class SpringBatchRetryIntegrationTest {
|
||||
|
||||
private static final String TEST_OUTPUT = "xml/retryOutput.xml";
|
||||
private static final String EXPECTED_OUTPUT = "src/test/resources/output/batchRetry/retryOutput.xml";
|
||||
|
||||
@Autowired
|
||||
private JobLauncherTestUtils jobLauncherTestUtils;
|
||||
|
||||
@MockBean
|
||||
private CloseableHttpClient closeableHttpClient;
|
||||
|
||||
@Mock
|
||||
private CloseableHttpResponse httpResponse;
|
||||
|
||||
@Test
|
||||
public void whenEndpointAlwaysFail_thenJobFails() throws Exception {
|
||||
when(closeableHttpClient.execute(any()))
|
||||
.thenThrow(new ConnectTimeoutException("Endpoint is down"));
|
||||
|
||||
JobExecution jobExecution = jobLauncherTestUtils.launchJob(defaultJobParameters());
|
||||
JobInstance actualJobInstance = jobExecution.getJobInstance();
|
||||
ExitStatus actualJobExitStatus = jobExecution.getExitStatus();
|
||||
|
||||
assertThat(actualJobInstance.getJobName(), is("retryBatchJob"));
|
||||
assertThat(actualJobExitStatus.getExitCode(), is("FAILED"));
|
||||
assertThat(actualJobExitStatus.getExitDescription(), containsString("org.apache.http.conn.ConnectTimeoutException"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenEndpointFailsTwicePasses3rdTime_thenSuccess() throws Exception {
|
||||
FileSystemResource expectedResult = new FileSystemResource(EXPECTED_OUTPUT);
|
||||
FileSystemResource actualResult = new FileSystemResource(TEST_OUTPUT);
|
||||
|
||||
//fails for first two calls and passes third time onwards
|
||||
when(httpResponse.getEntity())
|
||||
.thenReturn(new StringEntity("{ \"age\":10, \"postCode\":\"430222\" }"));
|
||||
when(closeableHttpClient.execute(any()))
|
||||
.thenThrow(new ConnectTimeoutException("Timeout count 1"))
|
||||
.thenThrow(new ConnectTimeoutException("Timeout count 2"))
|
||||
.thenReturn(httpResponse);
|
||||
|
||||
JobExecution jobExecution = jobLauncherTestUtils.launchJob(defaultJobParameters());
|
||||
JobInstance actualJobInstance = jobExecution.getJobInstance();
|
||||
ExitStatus actualJobExitStatus = jobExecution.getExitStatus();
|
||||
|
||||
assertThat(actualJobInstance.getJobName(), is("retryBatchJob"));
|
||||
assertThat(actualJobExitStatus.getExitCode(), is("COMPLETED"));
|
||||
AssertFile.assertFileEquals(expectedResult, actualResult);
|
||||
}
|
||||
|
||||
private JobParameters defaultJobParameters() {
|
||||
JobParametersBuilder paramsBuilder = new JobParametersBuilder();
|
||||
paramsBuilder.addString("jobID", String.valueOf(System.currentTimeMillis()));
|
||||
return paramsBuilder.toJobParameters();
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><transactionRecord><transactionRecord><age>10</age><amount>10000.0</amount><postCode>430222</postCode><transactionDate>2015-10-31T00:00:00+05:30</transactionDate><userId>1234</userId><username>sammy</username></transactionRecord><transactionRecord><age>10</age><amount>12321.0</amount><postCode>430222</postCode><transactionDate>2015-12-03T00:00:00+05:30</transactionDate><userId>9999</userId><username>john</username></transactionRecord></transactionRecord>
|
1
spring-batch/xml/retryOutput.xml
Normal file
1
spring-batch/xml/retryOutput.xml
Normal file
@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><transactionRecord><transactionRecord><age>10</age><amount>10000.0</amount><postCode>430222</postCode><transactionDate>2015-10-31T00:00:00+05:30</transactionDate><userId>1234</userId><username>sammy</username></transactionRecord><transactionRecord><age>10</age><amount>12321.0</amount><postCode>430222</postCode><transactionDate>2015-12-03T00:00:00+05:30</transactionDate><userId>9999</userId><username>john</username></transactionRecord></transactionRecord>
|
@ -16,11 +16,12 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
|
||||
public class Swagger2Config {
|
||||
@Bean
|
||||
public Docket api() {
|
||||
return new Docket(DocumentationType.SWAGGER_2).select()
|
||||
.apis(RequestHandlerSelectors.basePackage("com.baeldung.swagger2boot.controller"))
|
||||
.paths(PathSelectors.regex("/.*"))
|
||||
.build()
|
||||
.apiInfo(apiEndPointsInfo());
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.select()
|
||||
.apis(RequestHandlerSelectors.any())
|
||||
.paths(PathSelectors.any())
|
||||
.build()
|
||||
.apiInfo(apiEndPointsInfo());
|
||||
}
|
||||
|
||||
private ApiInfo apiEndPointsInfo() {
|
||||
|
39
spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/swagger2boot/controller/UserController.java
Normal file
39
spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/swagger2boot/controller/UserController.java
Normal file
@ -0,0 +1,39 @@
|
||||
package com.baeldung.swagger2boot.controller;
|
||||
|
||||
import com.baeldung.swagger2boot.model.Foo;
|
||||
import com.baeldung.swagger2boot.model.User;
|
||||
import io.swagger.annotations.ApiImplicitParam;
|
||||
import io.swagger.annotations.ApiImplicitParams;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.websocket.server.PathParam;
|
||||
|
||||
import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
|
||||
|
||||
@Controller
|
||||
public class UserController {
|
||||
|
||||
public UserController() {
|
||||
super();
|
||||
} //@formatter:off
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST, value = "/createUser", produces = "application/json; charset=UTF-8")
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
@ResponseBody
|
||||
@ApiOperation(value = "Create user",
|
||||
notes = "This method creates a new user")
|
||||
public User createUser(@ApiParam(
|
||||
name = "firstName",
|
||||
type = "String",
|
||||
value = "First Name of the user",
|
||||
example = "Vatsal",
|
||||
required = true) @RequestParam String firstName) { //@formatter:on
|
||||
User user = new User(firstName);
|
||||
return user;
|
||||
}
|
||||
}
|
28
spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/swagger2boot/model/User.java
Normal file
28
spring-boot-modules/spring-boot-mvc-2/src/main/java/com/baeldung/swagger2boot/model/User.java
Normal file
@ -0,0 +1,28 @@
|
||||
package com.baeldung.swagger2boot.model;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
|
||||
@ApiModel
|
||||
public class User {
|
||||
|
||||
@ApiModelProperty(value = "first name of the user", name = "firstName", dataType = "String", example = "Vatsal")
|
||||
String firstName;
|
||||
|
||||
public User() {
|
||||
super();
|
||||
}
|
||||
|
||||
public User(final String firstName) {
|
||||
super();
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
}
|
@ -95,7 +95,6 @@
|
||||
<guava.version>27.0.1-jre</guava.version>
|
||||
<xstream.version>1.4.11.1</xstream.version>
|
||||
<modelmapper.version>2.3.5</modelmapper.version>
|
||||
<spring-boot.version>2.1.9.RELEASE</spring-boot.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
@ -0,0 +1,26 @@
|
||||
package com.baeldung.persistence.config;
|
||||
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
|
||||
/**
|
||||
* Since H2 1.4.200. the behavior of the drop table commands has changed.
|
||||
* Tables are not dropped in a correct order.
|
||||
* Until this is properly fixed directly in Hibernate project,
|
||||
* let's use this custom H2Dialect class to solve this issue.
|
||||
*
|
||||
* @see <a href="https://hibernate.atlassian.net/browse/HHH-13711">https://hibernate.atlassian.net/browse/HHH-13711</a>
|
||||
* @see <a href="https://github.com/hibernate/hibernate-orm/pull/3093">https://github.com/hibernate/hibernate-orm/pull/3093</a>
|
||||
*/
|
||||
public class CustomH2Dialect extends H2Dialect {
|
||||
|
||||
@Override
|
||||
public boolean dropConstraints() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsIfExistsAfterAlterTable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +1,13 @@
|
||||
package com.baeldung.persistence.model;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import org.springframework.hateoas.RepresentationModel;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@JsonInclude(Include.NON_NULL)
|
||||
public class Customer extends ResourceSupport {
|
||||
public class Customer extends RepresentationModel<Customer> {
|
||||
private String customerId;
|
||||
private String customerName;
|
||||
private String companyName;
|
||||
|
@ -1,8 +1,8 @@
|
||||
package com.baeldung.persistence.model;
|
||||
|
||||
import org.springframework.hateoas.ResourceSupport;
|
||||
import org.springframework.hateoas.RepresentationModel;
|
||||
|
||||
public class Order extends ResourceSupport {
|
||||
public class Order extends RepresentationModel<Order> {
|
||||
private String orderId;
|
||||
private double price;
|
||||
private int quantity;
|
||||
|
@ -1,11 +1,11 @@
|
||||
package com.baeldung.requestresponsebody;
|
||||
|
||||
import com.baeldung.services.ExampleService;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
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.PostMapping;
|
||||
@ -34,4 +34,18 @@ public class ExamplePostController {
|
||||
log.debug("POST received - serializing LoginForm: " + loginForm.getPassword() + " " + loginForm.getUsername());
|
||||
return new ResponseTransfer("Thanks For Posting!!!");
|
||||
}
|
||||
|
||||
@PostMapping(value = "/content", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@ResponseBody
|
||||
public ResponseTransfer postResponseJsonContent(@RequestBody LoginForm loginForm) {
|
||||
log.debug("POST received - serializing LoginForm: " + loginForm.getPassword() + " " + loginForm.getUsername());
|
||||
return new ResponseTransfer("JSON Content!");
|
||||
}
|
||||
|
||||
@PostMapping(value = "/content", produces = MediaType.APPLICATION_XML_VALUE)
|
||||
@ResponseBody
|
||||
public ResponseTransfer postResponseXmlContent(@RequestBody LoginForm loginForm) {
|
||||
log.debug("POST received - serializing LoginForm: " + loginForm.getPassword() + " " + loginForm.getUsername());
|
||||
return new ResponseTransfer("XML Content!");
|
||||
}
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
package com.baeldung.web.controller;
|
||||
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
|
||||
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
|
||||
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
|
||||
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.hateoas.Resources;
|
||||
import org.springframework.hateoas.CollectionModel;
|
||||
import org.springframework.hateoas.config.EnableHypermediaSupport;
|
||||
import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@ -41,7 +41,7 @@ public class CustomerController {
|
||||
}
|
||||
|
||||
@GetMapping(value = "/{customerId}/orders", produces = { "application/hal+json" })
|
||||
public Resources<Order> getOrdersForCustomer(@PathVariable final String customerId) {
|
||||
public CollectionModel<Order> getOrdersForCustomer(@PathVariable final String customerId) {
|
||||
final List<Order> orders = orderService.getAllOrdersForCustomer(customerId);
|
||||
for (final Order order : orders) {
|
||||
final Link selfLink = linkTo(
|
||||
@ -50,12 +50,12 @@ public class CustomerController {
|
||||
}
|
||||
|
||||
Link link = linkTo(methodOn(CustomerController.class).getOrdersForCustomer(customerId)).withSelfRel();
|
||||
Resources<Order> result = new Resources<>(orders, link);
|
||||
CollectionModel<Order> result = new CollectionModel<>(orders, link);
|
||||
return result;
|
||||
}
|
||||
|
||||
@GetMapping(produces = { "application/hal+json" })
|
||||
public Resources<Customer> getAllCustomers() {
|
||||
public CollectionModel<Customer> getAllCustomers() {
|
||||
final List<Customer> allCustomers = customerService.allCustomers();
|
||||
|
||||
for (final Customer customer : allCustomers) {
|
||||
@ -72,7 +72,7 @@ public class CustomerController {
|
||||
}
|
||||
|
||||
Link link = linkTo(CustomerController.class).withSelfRel();
|
||||
Resources<Customer> result = new Resources<>(allCustomers, link);
|
||||
CollectionModel<Customer> result = new CollectionModel<>(allCustomers, link);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,6 @@ jdbc.user=sa
|
||||
jdbc.pass=
|
||||
|
||||
# hibernate.X
|
||||
hibernate.dialect=org.hibernate.dialect.H2Dialect
|
||||
hibernate.dialect=com.baeldung.persistence.config.CustomH2Dialect
|
||||
hibernate.show_sql=false
|
||||
hibernate.hbm2ddl.auto=create-drop
|
||||
|
@ -60,7 +60,7 @@ public final class JacksonMarshaller implements IMarshaller {
|
||||
List<T> entities = null;
|
||||
try {
|
||||
if (clazz.equals(Foo.class)) {
|
||||
entities = objectMapper.readValue(resourcesAsString, new TypeReference<List<Foo>>() {
|
||||
entities = objectMapper.readValue(resourcesAsString, new TypeReference<List<T>>() {
|
||||
// ...
|
||||
});
|
||||
} else {
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -2,7 +2,7 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.baeldung.spring.cloud</groupId>
|
||||
<groupId>com.baeldung.spring.cloud</groupId>
|
||||
<artifactId>batch-job</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>batch-job</name>
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung.spring.cloud;
|
||||
package com.baeldung.spring.cloud;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
@ -1,39 +1,39 @@
|
||||
package org.baeldung.spring.cloud;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.StepContribution;
|
||||
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.scope.context.ChunkContext;
|
||||
import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@EnableBatchProcessing
|
||||
public class JobConfiguration {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JobConfiguration.class);
|
||||
|
||||
@Autowired
|
||||
public JobBuilderFactory jobBuilderFactory;
|
||||
|
||||
@Autowired
|
||||
public StepBuilderFactory stepBuilderFactory;
|
||||
|
||||
@Bean
|
||||
public Job job() {
|
||||
return jobBuilderFactory.get("job").start(stepBuilderFactory.get("jobStep1").tasklet(new Tasklet() {
|
||||
@Override
|
||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
|
||||
logger.info("Job was run");
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
}).build()).build();
|
||||
}
|
||||
}
|
||||
package com.baeldung.spring.cloud;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.batch.core.Job;
|
||||
import org.springframework.batch.core.StepContribution;
|
||||
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.scope.context.ChunkContext;
|
||||
import org.springframework.batch.core.step.tasklet.Tasklet;
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@EnableBatchProcessing
|
||||
public class JobConfiguration {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(JobConfiguration.class);
|
||||
|
||||
@Autowired
|
||||
public JobBuilderFactory jobBuilderFactory;
|
||||
|
||||
@Autowired
|
||||
public StepBuilderFactory stepBuilderFactory;
|
||||
|
||||
@Bean
|
||||
public Job job() {
|
||||
return jobBuilderFactory.get("job").start(stepBuilderFactory.get("jobStep1").tasklet(new Tasklet() {
|
||||
@Override
|
||||
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
|
||||
logger.info("Job was run");
|
||||
return RepeatStatus.FINISHED;
|
||||
}
|
||||
}).build()).build();
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.baeldung.spring.cloud.JobConfiguration;
|
||||
import com.baeldung.spring.cloud.JobConfiguration;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung.spring.cloud;
|
||||
package com.baeldung.spring.cloud;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung.spring.cloud;
|
||||
package com.baeldung.spring.cloud;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
@ -1,6 +1,6 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.baeldung.spring.cloud.DataFlowServerApplication;
|
||||
import com.baeldung.spring.cloud.DataFlowServerApplication;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung.spring.cloud;
|
||||
package com.baeldung.spring.cloud;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung.spring.cloud;
|
||||
package com.baeldung.spring.cloud;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
@ -1,6 +1,6 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.baeldung.spring.cloud.DataFlowShellApplication;
|
||||
import com.baeldung.spring.cloud.DataFlowShellApplication;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung.spring.cloud;
|
||||
package com.baeldung.spring.cloud;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
@ -1,6 +1,6 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.baeldung.spring.cloud.LogSinkApplication;
|
||||
import com.baeldung.spring.cloud.LogSinkApplication;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung.spring.cloud;
|
||||
package com.baeldung.spring.cloud;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
@ -1,6 +1,6 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.baeldung.spring.cloud.TimeProcessorApplication;
|
||||
import com.baeldung.spring.cloud.TimeProcessorApplication;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung.spring.cloud;
|
||||
package com.baeldung.spring.cloud;
|
||||
|
||||
import java.util.Date;
|
||||
|
@ -1,6 +1,6 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.baeldung.spring.cloud.TimeSourceApplication;
|
||||
import com.baeldung.spring.cloud.TimeSourceApplication;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -2,7 +2,7 @@
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.baeldung</groupId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-cloud-consul</artifactId>
|
||||
<name>spring-cloud-consul</name>
|
||||
<packaging>jar</packaging>
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -2,7 +2,7 @@
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.baeldung</groupId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-cloud-rest</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<name>spring-cloud-rest</name>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.baeldung</groupId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-cloud-rest-books-api</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>spring-cloud-rest-books-api</name>
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
|
@ -1,6 +1,6 @@
|
||||
package org.baeldung.persistence.dao;
|
||||
package com.baeldung.persistence.dao;
|
||||
|
||||
import org.baeldung.persistence.model.Book;
|
||||
import com.baeldung.persistence.model.Book;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.repository.CrudRepository;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung.persistence.model;
|
||||
package com.baeldung.persistence.model;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,14 +1,16 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import static io.restassured.RestAssured.preemptive;
|
||||
import static org.apache.commons.lang3.RandomStringUtils.randomAlphabetic;
|
||||
import static org.apache.commons.lang3.RandomStringUtils.randomNumeric;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import com.baeldung.BooksApiApplication;
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.response.Response;
|
||||
|
||||
import org.baeldung.persistence.model.Book;
|
||||
import com.baeldung.persistence.model.Book;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,7 +1,10 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import com.baeldung.BooksApiApplication;
|
||||
import com.baeldung.SessionConfig;
|
||||
import io.restassured.RestAssured;
|
||||
import io.restassured.response.Response;
|
||||
|
@ -1,5 +1,6 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import com.baeldung.BooksApiApplication;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
@ -2,7 +2,7 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.baeldung</groupId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-cloud-rest-config-server</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>spring-cloud-rest-config-server</name>
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -2,7 +2,7 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.baeldung</groupId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-cloud-rest-discovery-server</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>spring-cloud-rest-discovery-server</name>
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
@ -2,7 +2,7 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.baeldung</groupId>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>spring-cloud-rest-reviews-api</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>spring-cloud-rest-reviews-api</name>
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
@ -1,4 +1,4 @@
|
||||
package org.baeldung;
|
||||
package com.baeldung;
|
||||
|
||||
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
|
||||
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
|
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