Merge branch 'eugenp:master' into master
This commit is contained in:
commit
a0157154a3
@ -14,16 +14,6 @@
|
|||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.commons</groupId>
|
|
||||||
<artifactId>commons-math3</artifactId>
|
|
||||||
<version>${commons-math3.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>commons-codec</groupId>
|
|
||||||
<artifactId>commons-codec</artifactId>
|
|
||||||
<version>${commons-codec.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package com.baeldung.algorithms;
|
package com.baeldung.algorithms;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import com.baeldung.algorithms.ga.dijkstra.Dijkstra;
|
import com.baeldung.algorithms.ga.dijkstra.Dijkstra;
|
||||||
import com.baeldung.algorithms.ga.dijkstra.Graph;
|
import com.baeldung.algorithms.ga.dijkstra.Graph;
|
||||||
import com.baeldung.algorithms.ga.dijkstra.Node;
|
import com.baeldung.algorithms.ga.dijkstra.Node;
|
||||||
|
@ -20,8 +20,4 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
|
||||||
<cxf.version>4.0.0</cxf.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -48,7 +48,6 @@
|
|||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<cxf.version>4.0.0</cxf.version>
|
|
||||||
<jakarta-xml.version>4.0.0</jakarta-xml.version>
|
<jakarta-xml.version>4.0.0</jakarta-xml.version>
|
||||||
<jakarta.jws.version>3.0.0</jakarta.jws.version>
|
<jakarta.jws.version>3.0.0</jakarta.jws.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
@ -16,12 +16,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.cxf</groupId>
|
<groupId>org.apache.cxf</groupId>
|
||||||
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
|
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
|
||||||
<version>4.0.0</version>
|
<version>${cxf.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.cxf</groupId>
|
<groupId>org.apache.cxf</groupId>
|
||||||
<artifactId>cxf-rt-transports-http-jetty</artifactId>
|
<artifactId>cxf-rt-transports-http-jetty</artifactId>
|
||||||
<version>4.0.0</version>
|
<version>${cxf.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>jakarta.xml.ws</groupId>
|
<groupId>jakarta.xml.ws</groupId>
|
||||||
|
@ -115,6 +115,7 @@
|
|||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
<cxf.version>3.1.8</cxf.version>
|
||||||
<spring.version>5.3.25</spring.version>
|
<spring.version>5.3.25</spring.version>
|
||||||
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
|
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
|
||||||
<jstl.version>1.2</jstl.version>
|
<jstl.version>1.2</jstl.version>
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<cxf.version>3.1.8</cxf.version>
|
<cxf.version>4.0.0</cxf.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -16,12 +16,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.cxf</groupId>
|
<groupId>org.apache.cxf</groupId>
|
||||||
<artifactId>cxf-rt-rs-client</artifactId>
|
<artifactId>cxf-rt-rs-client</artifactId>
|
||||||
<version>${cxf-version}</version>
|
<version>${cxf.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.cxf</groupId>
|
<groupId>org.apache.cxf</groupId>
|
||||||
<artifactId>cxf-rt-rs-sse</artifactId>
|
<artifactId>cxf-rt-rs-sse</artifactId>
|
||||||
<version>${cxf-version}</version>
|
<version>${cxf.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>jakarta.ws.rs</groupId>
|
<groupId>jakarta.ws.rs</groupId>
|
||||||
@ -60,7 +60,6 @@
|
|||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<cxf-version>4.0.0</cxf-version>
|
|
||||||
<jakarta-ws.version>3.1.0</jakarta-ws.version>
|
<jakarta-ws.version>3.1.0</jakarta-ws.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@
|
|||||||
<json-simple.version>1.1.1</json-simple.version>
|
<json-simple.version>1.1.1</json-simple.version>
|
||||||
<aws-lambda-java-events.version>3.11.0</aws-lambda-java-events.version>
|
<aws-lambda-java-events.version>3.11.0</aws-lambda-java-events.version>
|
||||||
<aws-lambda-java-core.version>1.2.1</aws-lambda-java-core.version>
|
<aws-lambda-java-core.version>1.2.1</aws-lambda-java-core.version>
|
||||||
<gson.version>2.8.2</gson.version>
|
<gson.version>2.10.1</gson.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -46,7 +46,7 @@
|
|||||||
<maven.compiler.source.version>11</maven.compiler.source.version>
|
<maven.compiler.source.version>11</maven.compiler.source.version>
|
||||||
<maven.compiler.target.version>11</maven.compiler.target.version>
|
<maven.compiler.target.version>11</maven.compiler.target.version>
|
||||||
<jackson.version>2.16.0</jackson.version>
|
<jackson.version>2.16.0</jackson.version>
|
||||||
<gson.version>2.10</gson.version>
|
<gson.version>2.10.1</gson.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -27,7 +27,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.gson</groupId>
|
<groupId>com.google.code.gson</groupId>
|
||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>2.8.9</version>
|
<version>2.10.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.json</groupId>
|
<groupId>org.json</groupId>
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<gson.version>2.8.5</gson.version>
|
<gson.version>2.10.1</gson.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -32,7 +32,7 @@
|
|||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<gson.version>2.8.2</gson.version>
|
<gson.version>2.10.1</gson.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -48,12 +48,18 @@
|
|||||||
<version>${awaitility.version}</version>
|
<version>${awaitility.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<spring.batch.version>5.0.0</spring.batch.version>
|
<spring.batch.version>5.0.0</spring.batch.version>
|
||||||
<awaitility.version>4.2.0</awaitility.version>
|
<awaitility.version>4.2.0</awaitility.version>
|
||||||
<start-class>com.baeldung.batch.SpringBootBatchProcessingApplication</start-class>
|
<start-class>com.baeldung.batch.SpringBootBatchProcessingApplication</start-class>
|
||||||
|
<lombok.version>1.18.28</lombok.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -0,0 +1,78 @@
|
|||||||
|
package com.baeldung.batchreaderproperties;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.springframework.batch.core.Job;
|
||||||
|
import org.springframework.batch.core.Step;
|
||||||
|
import org.springframework.batch.core.configuration.annotation.StepScope;
|
||||||
|
import org.springframework.batch.core.job.builder.JobBuilder;
|
||||||
|
import org.springframework.batch.core.launch.support.RunIdIncrementer;
|
||||||
|
import org.springframework.batch.core.repository.JobRepository;
|
||||||
|
import org.springframework.batch.core.step.builder.StepBuilder;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
|
|
||||||
|
import com.baeldung.batchreaderproperties.job.ExpiresSoonMedicineReader;
|
||||||
|
import com.baeldung.batchreaderproperties.job.MedicineProcessor;
|
||||||
|
import com.baeldung.batchreaderproperties.job.MedicineWriter;
|
||||||
|
import com.baeldung.batchreaderproperties.model.Medicine;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class BatchConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@StepScope
|
||||||
|
public ExpiresSoonMedicineReader expiresSoonMedicineReader(JdbcTemplate jdbcTemplate, @Value("#{jobParameters}") Map<String, Object> jobParameters) {
|
||||||
|
|
||||||
|
ExpiresSoonMedicineReader medicineReader = new ExpiresSoonMedicineReader(jdbcTemplate);
|
||||||
|
enrichWithJobParameters(jobParameters, medicineReader);
|
||||||
|
return medicineReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@StepScope
|
||||||
|
public MedicineProcessor medicineProcessor(@Value("#{jobParameters}") Map<String, Object> jobParameters) {
|
||||||
|
MedicineProcessor medicineProcessor = new MedicineProcessor();
|
||||||
|
enrichWithJobParameters(jobParameters, medicineProcessor);
|
||||||
|
return medicineProcessor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
@StepScope
|
||||||
|
public MedicineWriter medicineWriter(@Value("#{jobParameters}") Map<String, Object> jobParameters) {
|
||||||
|
MedicineWriter medicineWriter = new MedicineWriter();
|
||||||
|
enrichWithJobParameters(jobParameters, medicineWriter);
|
||||||
|
return medicineWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Job medExpirationJob(JobRepository jobRepository, PlatformTransactionManager transactionManager, MedicineWriter medicineWriter, MedicineProcessor medicineProcessor, ExpiresSoonMedicineReader expiresSoonMedicineReader) {
|
||||||
|
Step notifyAboutExpiringMedicine = new StepBuilder("notifyAboutExpiringMedicine", jobRepository).<Medicine, Medicine>chunk(10)
|
||||||
|
.reader(expiresSoonMedicineReader)
|
||||||
|
.processor(medicineProcessor)
|
||||||
|
.writer(medicineWriter)
|
||||||
|
.faultTolerant()
|
||||||
|
.transactionManager(transactionManager)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return new JobBuilder("medExpirationJob", jobRepository).incrementer(new RunIdIncrementer())
|
||||||
|
.start(notifyAboutExpiringMedicine)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enrichWithJobParameters(Map<String, Object> jobParameters, ContainsJobParameters container) {
|
||||||
|
if (jobParameters.get(BatchConstants.TRIGGERED_DATE_TIME) != null) {
|
||||||
|
container.setTriggeredDateTime(ZonedDateTime.parse(jobParameters.get(BatchConstants.TRIGGERED_DATE_TIME)
|
||||||
|
.toString()));
|
||||||
|
}
|
||||||
|
if (jobParameters.get(BatchConstants.TRACE_ID) != null) {
|
||||||
|
container.setTraceId(jobParameters.get(BatchConstants.TRACE_ID)
|
||||||
|
.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.baeldung.batchreaderproperties;
|
||||||
|
|
||||||
|
public class BatchConstants {
|
||||||
|
public static final String TRIGGERED_DATE_TIME = "TRIGGERED_DATE_TIME";
|
||||||
|
public static final String TRACE_ID = "TRACE_ID";
|
||||||
|
public static final String ALERT_TYPE = "ALERT_TYPE";
|
||||||
|
public static final String DEFAULT_EXPIRATION = "DEFAULT_EXPIRATION";
|
||||||
|
public static final String SALE_STARTS_DAYS = "SALE_STARTS_DAYS";
|
||||||
|
public static final String MEDICINE_SALE = "MEDICINE_SALE";
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.baeldung.batchreaderproperties;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
|
public interface ContainsJobParameters {
|
||||||
|
ZonedDateTime getTriggeredDateTime();
|
||||||
|
String getTraceId();
|
||||||
|
|
||||||
|
void setTriggeredDateTime(ZonedDateTime triggeredDateTime);
|
||||||
|
void setTraceId(String traceId);
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
package com.baeldung.batchreaderproperties;
|
||||||
|
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.springframework.batch.core.Job;
|
||||||
|
import org.springframework.batch.core.JobParameters;
|
||||||
|
import org.springframework.batch.core.JobParametersBuilder;
|
||||||
|
import org.springframework.batch.core.launch.JobLauncher;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@EnableScheduling
|
||||||
|
public class MedExpirationBatchRunner {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Job medExpirationJob;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JobLauncher jobLauncher;
|
||||||
|
|
||||||
|
@Value("${batch.medicine.alert_type}")
|
||||||
|
private String alertType;
|
||||||
|
|
||||||
|
@Value("${batch.medicine.expiration.default.days}")
|
||||||
|
private long defaultExpiration;
|
||||||
|
|
||||||
|
@Value("${batch.medicine.start.sale.default.days}")
|
||||||
|
private long saleStartDays;
|
||||||
|
|
||||||
|
@Value("${batch.medicine.sale}")
|
||||||
|
private double medicineSale;
|
||||||
|
|
||||||
|
@Scheduled(cron = "${batch.medicine.cron}", zone = "GMT")
|
||||||
|
public void runJob() {
|
||||||
|
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC);
|
||||||
|
launchJob(now);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void launchJob(ZonedDateTime triggerZonedDateTime) {
|
||||||
|
try {
|
||||||
|
JobParameters jobParameters = new JobParametersBuilder().addString(BatchConstants.TRIGGERED_DATE_TIME, triggerZonedDateTime.toString())
|
||||||
|
.addString(BatchConstants.ALERT_TYPE, alertType)
|
||||||
|
.addLong(BatchConstants.DEFAULT_EXPIRATION, defaultExpiration)
|
||||||
|
.addLong(BatchConstants.SALE_STARTS_DAYS, saleStartDays)
|
||||||
|
.addDouble(BatchConstants.MEDICINE_SALE, medicineSale)
|
||||||
|
.addString(BatchConstants.TRACE_ID, UUID.randomUUID()
|
||||||
|
.toString())
|
||||||
|
.toJobParameters();
|
||||||
|
|
||||||
|
jobLauncher.run(medExpirationJob, jobParameters);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to run", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.baeldung.batchreaderproperties;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.annotation.PropertySource;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@PropertySource("classpath:disable-job-autorun.properties")
|
||||||
|
public class SpringBatchExpireMedicationApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(SpringBatchExpireMedicationApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
package com.baeldung.batchreaderproperties.job;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.springframework.batch.core.JobParameters;
|
||||||
|
import org.springframework.batch.core.StepExecution;
|
||||||
|
import org.springframework.batch.core.annotation.BeforeStep;
|
||||||
|
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.jdbc.core.JdbcTemplate;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
|
||||||
|
import com.baeldung.batchreaderproperties.ContainsJobParameters;
|
||||||
|
import com.baeldung.batchreaderproperties.model.Medicine;
|
||||||
|
import com.baeldung.batchreaderproperties.model.MedicineCategory;
|
||||||
|
|
||||||
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Slf4j
|
||||||
|
public class ExpiresSoonMedicineReader extends AbstractItemCountingItemStreamItemReader<Medicine> implements ContainsJobParameters {
|
||||||
|
|
||||||
|
private static final String FIND_EXPIRING_SOON_MEDICINE = "Select * from MEDICINE where EXPIRATION_DATE >= CURRENT_DATE AND EXPIRATION_DATE <= DATEADD('DAY', ?, CURRENT_DATE)";
|
||||||
|
//common job parameters populated in bean initialization
|
||||||
|
private ZonedDateTime triggeredDateTime;
|
||||||
|
private String traceId;
|
||||||
|
//job parameter injected by Spring
|
||||||
|
@Value("#{jobParameters['DEFAULT_EXPIRATION']}")
|
||||||
|
private long defaultExpiration;
|
||||||
|
|
||||||
|
private final JdbcTemplate jdbcTemplate;
|
||||||
|
|
||||||
|
private List<Medicine> expiringMedicineList;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Medicine doRead() {
|
||||||
|
if (expiringMedicineList != null && !expiringMedicineList.isEmpty()) {
|
||||||
|
return expiringMedicineList.get(getCurrentItemCount() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doOpen() {
|
||||||
|
expiringMedicineList = jdbcTemplate.query(FIND_EXPIRING_SOON_MEDICINE, ps -> ps.setLong(1, defaultExpiration), (rs, row) -> getMedicine(rs));
|
||||||
|
|
||||||
|
log.info("Trace = {}. Found {} meds that expires soon", traceId, expiringMedicineList.size());
|
||||||
|
if (!expiringMedicineList.isEmpty()) {
|
||||||
|
setMaxItemCount(expiringMedicineList.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Medicine getMedicine(ResultSet rs) throws SQLException {
|
||||||
|
return new Medicine(UUID.fromString(rs.getString(1)), rs.getString(2), MedicineCategory.valueOf(rs.getString(3)), rs.getTimestamp(4), rs.getDouble(5), rs.getObject(6, Double.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doClose() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
setName(ClassUtils.getShortName(getClass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeStep
|
||||||
|
public void beforeStep(StepExecution stepExecution) {
|
||||||
|
JobParameters parameters = stepExecution.getJobExecution()
|
||||||
|
.getJobParameters();
|
||||||
|
log.info("Before step params: {}", parameters);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.baeldung.batchreaderproperties.job;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
|
import org.springframework.batch.item.ItemProcessor;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
|
||||||
|
import com.baeldung.batchreaderproperties.ContainsJobParameters;
|
||||||
|
import com.baeldung.batchreaderproperties.model.Medicine;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class MedicineProcessor implements ItemProcessor<Medicine, Medicine>, ContainsJobParameters {
|
||||||
|
|
||||||
|
private ZonedDateTime triggeredDateTime;
|
||||||
|
private String traceId;
|
||||||
|
|
||||||
|
@Value("#{jobParameters['SALE_STARTS_DAYS']}")
|
||||||
|
private long saleStartsDays;
|
||||||
|
@Value("#{jobParameters['MEDICINE_SALE']}")
|
||||||
|
private double medicineSale;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Medicine process(Medicine medicine) {
|
||||||
|
|
||||||
|
final Double originalPrice = medicine.getOriginalPrice();
|
||||||
|
final Timestamp expirationDate = medicine.getExpirationDate();
|
||||||
|
|
||||||
|
Duration daysToExpiration = Duration.between(ZonedDateTime.now(), ZonedDateTime.ofInstant(expirationDate.toInstant(), ZoneId.of("UTC")));
|
||||||
|
|
||||||
|
if (daysToExpiration.toDays() < saleStartsDays) {
|
||||||
|
medicine.setSalePrice(originalPrice * (1 - medicineSale));
|
||||||
|
log.info("Trace = {}, calculated new sale price {} for medicine {}", traceId, medicine.getSalePrice(), medicine.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return medicine;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package com.baeldung.batchreaderproperties.job;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
|
import org.springframework.batch.item.Chunk;
|
||||||
|
import org.springframework.batch.item.ItemWriter;
|
||||||
|
|
||||||
|
import com.baeldung.batchreaderproperties.ContainsJobParameters;
|
||||||
|
import com.baeldung.batchreaderproperties.model.Medicine;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Slf4j
|
||||||
|
public class MedicineWriter implements ItemWriter<Medicine>, ContainsJobParameters {
|
||||||
|
|
||||||
|
private ZonedDateTime triggeredDateTime;
|
||||||
|
private String traceId;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(Chunk<? extends Medicine> chunk) {
|
||||||
|
chunk.forEach((medicine) -> log.info("Trace = {}. This medicine is expiring {}", traceId, medicine));
|
||||||
|
|
||||||
|
log.info("Finishing job started at {}", triggeredDateTime);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.baeldung.batchreaderproperties.model;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class Medicine {
|
||||||
|
private UUID id;
|
||||||
|
private String name;
|
||||||
|
private MedicineCategory type;
|
||||||
|
private Timestamp expirationDate;
|
||||||
|
private Double originalPrice;
|
||||||
|
private Double salePrice;
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.baeldung.batchreaderproperties.model;
|
||||||
|
|
||||||
|
public enum MedicineCategory {
|
||||||
|
ANESTHETICS, ANTIBACTERIALS, ANTIDEPRESSANTS;
|
||||||
|
}
|
@ -1 +1,7 @@
|
|||||||
file.input=coffee-list.csv
|
file.input=coffee-list.csv
|
||||||
|
##medicine batch related properties
|
||||||
|
batch.medicine.cron=0 */1 * * * *
|
||||||
|
batch.medicine.alert_type=LOGS
|
||||||
|
batch.medicine.expiration.default.days=60
|
||||||
|
batch.medicine.start.sale.default.days=45
|
||||||
|
batch.medicine.sale=0.1
|
4
spring-batch-2/src/main/resources/data.sql
Normal file
4
spring-batch-2/src/main/resources/data.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
INSERT INTO medicine VALUES ('ec278dd3-87b9-4ad1-858f-dfe5bc34bdb5', 'Lidocaine', 'ANESTHETICS', DATEADD('DAY', 120, CURRENT_DATE), 10, null);
|
||||||
|
INSERT INTO medicine VALUES ('9d39321d-34f3-4eb7-bb9a-a69734e0e372', 'Flucloxacillin', 'ANTIBACTERIALS', DATEADD('DAY', 40, CURRENT_DATE), 20, null);
|
||||||
|
INSERT INTO medicine VALUES ('87f4ff13-de40-4c7f-95db-627f309394dd', 'Amoxicillin', 'ANTIBACTERIALS', DATEADD('DAY', 70, CURRENT_DATE), 30, null);
|
||||||
|
INSERT INTO medicine VALUES ('acd99d6a-27be-4c89-babe-0edf4dca22cb', 'Prozac', 'ANTIDEPRESSANTS', DATEADD('DAY', 30, CURRENT_DATE), 40, null);
|
@ -0,0 +1 @@
|
|||||||
|
spring.batch.job.enabled=false
|
@ -6,3 +6,14 @@ CREATE TABLE coffee (
|
|||||||
origin VARCHAR(20),
|
origin VARCHAR(20),
|
||||||
characteristics VARCHAR(30)
|
characteristics VARCHAR(30)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
DROP TABLE medicine IF EXISTS;
|
||||||
|
|
||||||
|
CREATE TABLE medicine (
|
||||||
|
med_id VARCHAR(36) PRIMARY KEY,
|
||||||
|
name VARCHAR(30),
|
||||||
|
type VARCHAR(30),
|
||||||
|
expiration_date TIMESTAMP,
|
||||||
|
original_price DECIMAL,
|
||||||
|
sale_price DECIMAL
|
||||||
|
);
|
@ -64,6 +64,11 @@
|
|||||||
<groupId>org.springframework.session</groupId>
|
<groupId>org.springframework.session</groupId>
|
||||||
<artifactId>spring-session-data-redis</artifactId>
|
<artifactId>spring-session-data-redis</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>mockwebserver</artifactId>
|
||||||
|
<version>4.12.0</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
package com.baeldung.custom.deserialization;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.baeldung.custom.deserialization.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.codec.CodecCustomizer;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.codec.CodecConfigurer;
|
||||||
|
import org.springframework.http.codec.json.Jackson2JsonDecoder;
|
||||||
|
import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
||||||
|
import org.springframework.util.MimeType;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class CodecCustomizerConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public CodecCustomizer codecCustomizer(ObjectMapper customObjectMapper) {
|
||||||
|
return configurer -> {
|
||||||
|
MimeType mimeType = MimeType.valueOf(MediaType.APPLICATION_JSON_VALUE);
|
||||||
|
CodecConfigurer.CustomCodecs customCodecs = configurer.customCodecs();
|
||||||
|
customCodecs.register(new Jackson2JsonDecoder(customObjectMapper, mimeType));
|
||||||
|
customCodecs.register(new Jackson2JsonEncoder(customObjectMapper, mimeType));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.baeldung.custom.deserialization.config;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParser;
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
||||||
|
|
||||||
|
public class CustomDeserializer extends LocalDateTimeDeserializer {
|
||||||
|
@Override
|
||||||
|
public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
|
||||||
|
try {
|
||||||
|
return OffsetDateTime.parse(jsonParser.getText()).atZoneSameInstant(ZoneOffset.UTC).toLocalDateTime();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return super.deserialize(jsonParser, ctxt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.baeldung.custom.deserialization.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class CustomObjectMapper {
|
||||||
|
@Bean
|
||||||
|
public ObjectMapper objectMapper() {
|
||||||
|
return new ObjectMapper()
|
||||||
|
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, true)
|
||||||
|
.registerModule(new JavaTimeModule());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.baeldung.custom.deserialization.controller;
|
||||||
|
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.baeldung.custom.deserialization.model.OrderResponse;
|
||||||
|
import com.baeldung.custom.deserialization.service.ExternalServiceV1;
|
||||||
|
import com.baeldung.custom.deserialization.service.ExternalServiceV2;
|
||||||
|
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class OrderController {
|
||||||
|
|
||||||
|
private final ExternalServiceV1 externalServiceV1;
|
||||||
|
private final ExternalServiceV2 externalServiceV2;
|
||||||
|
|
||||||
|
public OrderController(ExternalServiceV1 externalServiceV1, ExternalServiceV2 externalServiceV2) {
|
||||||
|
this.externalServiceV1 = externalServiceV1;
|
||||||
|
this.externalServiceV2 = externalServiceV2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(value = "v1/order/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public final Mono<OrderResponse> searchOrderV1(@PathVariable(value = "id") int id) {
|
||||||
|
return externalServiceV1.findById(id)
|
||||||
|
.bodyToMono(OrderResponse.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping(value = "v2/order/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||||
|
public final Mono<OrderResponse> searchOrderV2(@PathVariable(value = "id") int id) {
|
||||||
|
return externalServiceV2.findById(id)
|
||||||
|
.bodyToMono(OrderResponse.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.baeldung.custom.deserialization.model;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class OrderResponse {
|
||||||
|
|
||||||
|
private UUID orderId;
|
||||||
|
|
||||||
|
private LocalDateTime orderDateTime;
|
||||||
|
|
||||||
|
private List<String> address;
|
||||||
|
|
||||||
|
private List<String> orderNotes;
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package com.baeldung.custom.deserialization.service;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ExternalServiceV1 {
|
||||||
|
|
||||||
|
private final WebClient.Builder webclientBuilder;
|
||||||
|
|
||||||
|
public ExternalServiceV1(WebClient.Builder webclientBuilder) {
|
||||||
|
this.webclientBuilder = webclientBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WebClient.ResponseSpec findById(int id) {
|
||||||
|
return webclientBuilder.baseUrl("http://localhost:8090/")
|
||||||
|
.build()
|
||||||
|
.get()
|
||||||
|
.uri("external/order/" + id)
|
||||||
|
.retrieve();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
package com.baeldung.custom.deserialization.service;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.codec.json.Jackson2JsonDecoder;
|
||||||
|
import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.reactive.function.client.ExchangeStrategies;
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
|
||||||
|
import com.baeldung.custom.deserialization.config.CustomDeserializer;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ExternalServiceV2 {
|
||||||
|
|
||||||
|
public WebClient.ResponseSpec findById(int id) {
|
||||||
|
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper().registerModule(new SimpleModule().addDeserializer(LocalDateTime.class, new CustomDeserializer()));
|
||||||
|
|
||||||
|
WebClient webClient = WebClient.builder()
|
||||||
|
.baseUrl("http://localhost:8090/")
|
||||||
|
.exchangeStrategies(ExchangeStrategies.builder()
|
||||||
|
.codecs(clientDefaultCodecsConfigurer -> {
|
||||||
|
clientDefaultCodecsConfigurer.defaultCodecs()
|
||||||
|
.jackson2JsonEncoder(new Jackson2JsonEncoder(objectMapper, MediaType.APPLICATION_JSON));
|
||||||
|
clientDefaultCodecsConfigurer.defaultCodecs()
|
||||||
|
.jackson2JsonDecoder(new Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON));
|
||||||
|
})
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return webClient.get()
|
||||||
|
.uri("external/order/" + id)
|
||||||
|
.retrieve();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,135 @@
|
|||||||
|
package com.baeldung.custom.deserialization;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.test.context.TestPropertySource;
|
||||||
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
|
|
||||||
|
import com.baeldung.custom.deserialization.model.OrderResponse;
|
||||||
|
|
||||||
|
import okhttp3.mockwebserver.MockResponse;
|
||||||
|
import okhttp3.mockwebserver.MockWebServer;
|
||||||
|
|
||||||
|
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
|
||||||
|
@TestPropertySource(properties = "server.port=8091")
|
||||||
|
@AutoConfigureWebTestClient(timeout = "100000")
|
||||||
|
class OrderControllerIntegrationTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WebTestClient webTestClient;
|
||||||
|
|
||||||
|
private static MockWebServer mockExternalService;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
static void setup() throws IOException {
|
||||||
|
mockExternalService = new MockWebServer();
|
||||||
|
mockExternalService.start(8090);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenMockedExternalResponse_whenSearchByIdV1_thenOrderResponseShouldFailBecauseOfUnknownProperty() {
|
||||||
|
|
||||||
|
mockExternalService.enqueue(new MockResponse().addHeader("Content-Type", "application/json; charset=utf-8")
|
||||||
|
.setBody("{\n" + " \"orderId\": \"a1b2c3d4-e5f6-4a5b-8c9d-0123456789ab\",\n"
|
||||||
|
+ " \"orderDateTime\": \"2024-01-20T12:34:56\",\n"
|
||||||
|
+ " \"address\": [\"123 Main St\", \"Apt 456\", \"Cityville\"],\n"
|
||||||
|
+ " \"orderNotes\": [\"Special request: Handle with care\", \"Gift wrapping required\"],\n"
|
||||||
|
+ " \"customerName\": \"John Doe\",\n" + " \"totalAmount\": 99.99,\n"
|
||||||
|
+ " \"paymentMethod\": \"Credit Card\"\n" + " }")
|
||||||
|
.setResponseCode(HttpStatus.OK.value()));
|
||||||
|
|
||||||
|
webTestClient.get()
|
||||||
|
.uri("v1/order/1")
|
||||||
|
.exchange()
|
||||||
|
.expectStatus()
|
||||||
|
.is5xxServerError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenMockedExternalResponse_whenSearchByIdV1_thenOrderResponseShouldBeReceivedSuccessfully() {
|
||||||
|
|
||||||
|
mockExternalService.enqueue(new MockResponse().addHeader("Content-Type", "application/json; charset=utf-8")
|
||||||
|
.setBody("{\n" + " \"orderId\": \"a1b2c3d4-e5f6-4a5b-8c9d-0123456789ab\",\n"
|
||||||
|
+ " \"orderDateTime\": \"2024-01-20T12:34:56\",\n"
|
||||||
|
+ " \"address\": [\"123 Main St\", \"Apt 456\", \"Cityville\"],\n"
|
||||||
|
+ " \"orderNotes\": [\"Special request: Handle with care\", \"Gift wrapping required\"]\n"
|
||||||
|
+ " }")
|
||||||
|
.setResponseCode(HttpStatus.OK.value()));
|
||||||
|
|
||||||
|
OrderResponse orderResponse = webTestClient.get()
|
||||||
|
.uri("v1/order/1")
|
||||||
|
.exchange()
|
||||||
|
.expectStatus()
|
||||||
|
.isOk()
|
||||||
|
.expectBody(OrderResponse.class)
|
||||||
|
.returnResult()
|
||||||
|
.getResponseBody();
|
||||||
|
assertEquals(UUID.fromString("a1b2c3d4-e5f6-4a5b-8c9d-0123456789ab"), orderResponse.getOrderId());
|
||||||
|
assertEquals(LocalDateTime.of(2024, 1, 20, 12, 34, 56), orderResponse.getOrderDateTime());
|
||||||
|
assertThat(orderResponse.getAddress()).hasSize(3);
|
||||||
|
assertThat(orderResponse.getOrderNotes()).hasSize(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenMockedExternalResponse_whenSearchByIdV2_thenOrderResponseShouldFailBecauseOfUnknownProperty() {
|
||||||
|
|
||||||
|
mockExternalService.enqueue(new MockResponse().addHeader("Content-Type", "application/json; charset=utf-8")
|
||||||
|
.setBody("{\n" + " \"orderId\": \"a1b2c3d4-e5f6-4a5b-8c9d-0123456789ab\",\n"
|
||||||
|
+ " \"orderDateTime\": \"2024-01-20T12:34:56\",\n"
|
||||||
|
+ " \"address\": [\"123 Main St\", \"Apt 456\", \"Cityville\"],\n"
|
||||||
|
+ " \"orderNotes\": [\"Special request: Handle with care\", \"Gift wrapping required\"],\n"
|
||||||
|
+ " \"customerName\": \"John Doe\",\n"
|
||||||
|
+ " \"totalAmount\": 99.99,\n"
|
||||||
|
+ " \"paymentMethod\": \"Credit Card\"\n"
|
||||||
|
+ " }")
|
||||||
|
.setResponseCode(HttpStatus.OK.value()));
|
||||||
|
|
||||||
|
webTestClient.get()
|
||||||
|
.uri("v2/order/1")
|
||||||
|
.exchange()
|
||||||
|
.expectStatus()
|
||||||
|
.is5xxServerError();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenMockedExternalResponse_whenSearchByIdV2_thenOrderResponseShouldBeReceivedSuccessfully() {
|
||||||
|
|
||||||
|
mockExternalService.enqueue(new MockResponse().addHeader("Content-Type", "application/json; charset=utf-8")
|
||||||
|
.setBody("{\n" + " \"orderId\": \"a1b2c3d4-e5f6-4a5b-8c9d-0123456789ab\",\n"
|
||||||
|
+ " \"orderDateTime\": \"2024-01-20T14:34:56+01:00\",\n"
|
||||||
|
+ " \"address\": [\"123 Main St\", \"Apt 456\", \"Cityville\"],\n"
|
||||||
|
+ " \"orderNotes\": [\"Special request: Handle with care\", \"Gift wrapping required\"]\n" + " }")
|
||||||
|
.setResponseCode(HttpStatus.OK.value()));
|
||||||
|
|
||||||
|
OrderResponse orderResponse = webTestClient.get()
|
||||||
|
.uri("v2/order/1")
|
||||||
|
.exchange()
|
||||||
|
.expectStatus()
|
||||||
|
.isOk()
|
||||||
|
.expectBody(OrderResponse.class)
|
||||||
|
.returnResult()
|
||||||
|
.getResponseBody();
|
||||||
|
assertEquals(UUID.fromString("a1b2c3d4-e5f6-4a5b-8c9d-0123456789ab"), orderResponse.getOrderId());
|
||||||
|
assertEquals(LocalDateTime.of(2024, 1, 20, 13, 34, 56), orderResponse.getOrderDateTime());
|
||||||
|
assertThat(orderResponse.getAddress()).hasSize(3);
|
||||||
|
assertThat(orderResponse.getOrderNotes()).hasSize(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
static void tearDown() throws IOException {
|
||||||
|
mockExternalService.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -22,7 +22,6 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
<version>3.0.2</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.tomcat.embed</groupId>
|
<groupId>org.apache.tomcat.embed</groupId>
|
||||||
@ -31,7 +30,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
<artifactId>jstl</artifactId>
|
<artifactId>jstl</artifactId>
|
||||||
<version>1.2</version>
|
<version>${jstl.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
@ -39,4 +38,8 @@
|
|||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<jstl.version>1.2</jstl.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
@ -65,8 +65,8 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.jayway.jsonpath</groupId>
|
<groupId>com.jayway.jsonpath</groupId>
|
||||||
<artifactId>json-path</artifactId>
|
<artifactId>json-path</artifactId>
|
||||||
<scope>test</scope>
|
|
||||||
<version>${json-path.version}</version>
|
<version>${json-path.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>spring-session</artifactId>
|
<artifactId>spring-session</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<name>spring-session</name>
|
<name>spring-session</name>
|
||||||
|
@ -108,7 +108,6 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-war-plugin</artifactId>
|
<artifactId>maven-war-plugin</artifactId>
|
||||||
<version>${maven-war-plugin.version}</version>
|
|
||||||
<configuration>
|
<configuration>
|
||||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.codeborne</groupId>
|
<groupId>com.codeborne</groupId>
|
||||||
<artifactId>selenide</artifactId>
|
<artifactId>selenide</artifactId>
|
||||||
<version>6.15.0</version>
|
<version>${selenide.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -54,6 +54,7 @@
|
|||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
<selenide.version>6.15.0</selenide.version>
|
||||||
<testng.version>6.10</testng.version>
|
<testng.version>6.10</testng.version>
|
||||||
<selenium-java.version>4.8.3</selenium-java.version>
|
<selenium-java.version>4.8.3</selenium-java.version>
|
||||||
<webdrivermanager.version>5.3.2</webdrivermanager.version>
|
<webdrivermanager.version>5.3.2</webdrivermanager.version>
|
||||||
|
@ -36,8 +36,6 @@
|
|||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
|
||||||
<maven.compiler.target>17</maven.compiler.target>
|
|
||||||
<version.ai.timefold.solver>1.4.0</version.ai.timefold.solver>
|
<version.ai.timefold.solver>1.4.0</version.ai.timefold.solver>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user