Merge branch 'master' of https://github.com/eugenp/tutorials
This commit is contained in:
commit
2bd89b92b2
|
@ -9,4 +9,5 @@
|
||||||
- [The Caesar Cipher in Java](https://www.baeldung.com/java-caesar-cipher)
|
- [The Caesar Cipher in Java](https://www.baeldung.com/java-caesar-cipher)
|
||||||
- [Implementing a 2048 Solver in Java](https://www.baeldung.com/2048-java-solver)
|
- [Implementing a 2048 Solver in Java](https://www.baeldung.com/2048-java-solver)
|
||||||
- [Finding Top K Elements in an Array](https://www.baeldung.com/java-array-top-elements)
|
- [Finding Top K Elements in an Array](https://www.baeldung.com/java-array-top-elements)
|
||||||
|
- [Reversing a Linked List in Java](https://www.baeldung.com/java-reverse-linked-list)
|
||||||
- More articles: [[<-- prev]](/../algorithms-miscellaneous-5)
|
- More articles: [[<-- prev]](/../algorithms-miscellaneous-5)
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,75 @@
|
||||||
|
package com.baeldung.differences.dataframe.dataset.rdd;
|
||||||
|
|
||||||
|
|
||||||
|
public class TouristData {
|
||||||
|
|
||||||
|
private String region;
|
||||||
|
private String country;
|
||||||
|
private String year;
|
||||||
|
private String series;
|
||||||
|
private Double value;
|
||||||
|
private String footnotes;
|
||||||
|
private String source;
|
||||||
|
|
||||||
|
public String getRegion() {
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRegion(String region) {
|
||||||
|
this.region = region;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCountry() {
|
||||||
|
return country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCountry(String country) {
|
||||||
|
this.country = country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getYear() {
|
||||||
|
return year;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setYear(String year) {
|
||||||
|
this.year = year;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSeries() {
|
||||||
|
return series;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSeries(String series) {
|
||||||
|
this.series = series;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Double getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(Double value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFootnotes() {
|
||||||
|
return footnotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFootnotes(String footnotes) {
|
||||||
|
this.footnotes = footnotes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSource(String source) {
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "TouristData [region=" + region + ", country=" + country + ", year=" + year + ", series=" + series + ", value=" + value + ", footnotes=" + footnotes + ", source=" + source + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package com.baeldung.differences.rdd;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.spark.SparkConf;
|
||||||
|
import org.apache.spark.api.java.JavaPairRDD;
|
||||||
|
import org.apache.spark.api.java.JavaRDD;
|
||||||
|
import org.apache.spark.api.java.JavaSparkContext;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import scala.Tuple2;
|
||||||
|
|
||||||
|
public class ActionsUnitTest {
|
||||||
|
private static JavaRDD<String> tourists;
|
||||||
|
private static JavaSparkContext sc;
|
||||||
|
public static final String COMMA_DELIMITER = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)";
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void init() {
|
||||||
|
SparkConf conf = new SparkConf().setAppName("reduce")
|
||||||
|
.setMaster("local[*]");
|
||||||
|
sc = new JavaSparkContext(conf);
|
||||||
|
tourists = sc.textFile("data/Tourist.csv").filter(line -> !line.startsWith("Region"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void cleanup() {
|
||||||
|
sc.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenDistinctCount_thenReturnDistinctNumRecords() {
|
||||||
|
JavaRDD<String> countries = tourists.map(line -> {
|
||||||
|
String[] columns = line.split(COMMA_DELIMITER);
|
||||||
|
return columns[1];
|
||||||
|
})
|
||||||
|
.distinct();
|
||||||
|
Long numberOfCountries = countries.count();
|
||||||
|
System.out.println("Count: " + numberOfCountries);
|
||||||
|
|
||||||
|
assertEquals(Long.valueOf(220), numberOfCountries);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenReduceByKeySum_thenTotalValuePerKey() {
|
||||||
|
JavaRDD<String> touristsExpenditure = tourists.filter(line -> line.split(COMMA_DELIMITER)[3].contains("expenditure"));
|
||||||
|
|
||||||
|
JavaPairRDD<String, Double> expenditurePairRdd = touristsExpenditure.mapToPair(line -> {
|
||||||
|
String[] columns = line.split(COMMA_DELIMITER);
|
||||||
|
return new Tuple2<>(columns[1], Double.valueOf(columns[6]));
|
||||||
|
});
|
||||||
|
List<Tuple2<String, Double>> totalByCountry = expenditurePairRdd.reduceByKey((x, y) -> x + y)
|
||||||
|
.collect();
|
||||||
|
System.out.println("Total per Country: " + totalByCountry);
|
||||||
|
|
||||||
|
for(Tuple2<String, Double> tuple : totalByCountry) {
|
||||||
|
if (tuple._1.equals("Mexico")) {
|
||||||
|
assertEquals(Double.valueOf(99164), tuple._2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package com.baeldung.differences.rdd;
|
||||||
|
|
||||||
|
import static org.apache.spark.sql.functions.col;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.spark.sql.DataFrameReader;
|
||||||
|
import org.apache.spark.sql.Dataset;
|
||||||
|
import org.apache.spark.sql.Row;
|
||||||
|
import org.apache.spark.sql.SparkSession;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class DataFrameUnitTest {
|
||||||
|
private static SparkSession session;
|
||||||
|
private static Dataset<Row> data;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void init() {
|
||||||
|
session = SparkSession.builder()
|
||||||
|
.appName("TouristDataFrameExample")
|
||||||
|
.master("local[*]")
|
||||||
|
.getOrCreate();
|
||||||
|
DataFrameReader dataFrameReader = session.read();
|
||||||
|
data = dataFrameReader.option("header", "true")
|
||||||
|
.csv("data/Tourist.csv");
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void cleanup() {
|
||||||
|
session.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSelectSpecificColumns_thenColumnsFiltered() {
|
||||||
|
Dataset<Row> selectedData = data.select(col("country"), col("year"), col("value"));
|
||||||
|
selectedData.show();
|
||||||
|
|
||||||
|
List<String> resultList = Arrays.asList(selectedData.columns());
|
||||||
|
assertTrue(resultList.contains("country"));
|
||||||
|
assertTrue(resultList.contains("year"));
|
||||||
|
assertTrue(resultList.contains("value"));
|
||||||
|
assertFalse(resultList.contains("Series"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenFilteringByCountry_thenCountryRecordsSelected() {
|
||||||
|
Dataset<Row> filteredData = data.filter(col("country").equalTo("Mexico"));
|
||||||
|
filteredData.show();
|
||||||
|
|
||||||
|
filteredData.foreach(record -> {
|
||||||
|
assertEquals("Mexico", record.get(1));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenGroupCountByCountry_thenContryTotalRecords() {
|
||||||
|
Dataset<Row> recordsPerCountry = data.groupBy(col("country"))
|
||||||
|
.count();
|
||||||
|
recordsPerCountry.show();
|
||||||
|
|
||||||
|
Dataset<Row> filteredData = recordsPerCountry.filter(col("country").equalTo("Sweden"));
|
||||||
|
assertEquals(new Long(12), filteredData.first()
|
||||||
|
.get(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
package com.baeldung.differences.rdd;
|
||||||
|
|
||||||
|
import static org.apache.spark.sql.functions.col;
|
||||||
|
import static org.apache.spark.sql.functions.sum;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import org.apache.spark.api.java.function.FilterFunction;
|
||||||
|
import org.apache.spark.sql.DataFrameReader;
|
||||||
|
import org.apache.spark.sql.Dataset;
|
||||||
|
import org.apache.spark.sql.Encoders;
|
||||||
|
import org.apache.spark.sql.Row;
|
||||||
|
import org.apache.spark.sql.SparkSession;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.baeldung.differences.dataframe.dataset.rdd.TouristData;
|
||||||
|
|
||||||
|
public class DatasetUnitTest {
|
||||||
|
private static SparkSession session;
|
||||||
|
private static Dataset<TouristData> typedDataset;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void init() {
|
||||||
|
session = SparkSession.builder()
|
||||||
|
.appName("TouristDatasetExample")
|
||||||
|
.master("local[*]")
|
||||||
|
.getOrCreate();
|
||||||
|
DataFrameReader dataFrameReader = session.read();
|
||||||
|
Dataset<Row> data = dataFrameReader.option("header", "true")
|
||||||
|
.csv("data/Tourist.csv");
|
||||||
|
Dataset<Row> responseWithSelectedColumns = data.select(col("region"),
|
||||||
|
col("country"), col("year"), col("series"), col("value").cast("double"),
|
||||||
|
col("footnotes"), col("source"));
|
||||||
|
typedDataset = responseWithSelectedColumns.as(Encoders.bean(TouristData.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void cleanup() {
|
||||||
|
session.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenFilteringByCountry_thenCountryRecordsSelected() {
|
||||||
|
Dataset<TouristData> selectedData = typedDataset
|
||||||
|
.filter((FilterFunction<TouristData>) record -> record.getCountry()
|
||||||
|
.equals("Norway"));
|
||||||
|
selectedData.show();
|
||||||
|
|
||||||
|
selectedData.foreach(record -> {
|
||||||
|
assertEquals("Norway", record.getCountry());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenGroupCountByCountry_thenContryTotalRecords() {
|
||||||
|
Dataset<Row> countriesCount = typedDataset.groupBy(typedDataset.col("country"))
|
||||||
|
.count();
|
||||||
|
countriesCount.show();
|
||||||
|
|
||||||
|
assertEquals(Long.valueOf(220), Long.valueOf(countriesCount.count()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenFilteredByPropertyRange_thenRetreiveValidRecords() {
|
||||||
|
// Filter records with existing data for years between 2010 and 2017
|
||||||
|
typedDataset.filter((FilterFunction<TouristData>) record -> record.getYear() != null
|
||||||
|
&& (Long.valueOf(record.getYear()) > 2010 && Long.valueOf(record.getYear()) < 2017))
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSumValue_thenRetreiveTotalValue() {
|
||||||
|
// Total tourist expenditure by country
|
||||||
|
typedDataset.filter((FilterFunction<TouristData>) record -> record.getValue() != null
|
||||||
|
&& record.getSeries()
|
||||||
|
.contains("expenditure"))
|
||||||
|
.groupBy("country")
|
||||||
|
.agg(sum("value"))
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.baeldung.differences.rdd;
|
||||||
|
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.spark.SparkConf;
|
||||||
|
import org.apache.spark.api.java.JavaRDD;
|
||||||
|
import org.apache.spark.api.java.JavaSparkContext;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TransformationsUnitTest {
|
||||||
|
|
||||||
|
public static final String COMMA_DELIMITER = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)";
|
||||||
|
private static JavaSparkContext sc;
|
||||||
|
private static JavaRDD<String> tourists;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void init() {
|
||||||
|
SparkConf conf = new SparkConf().setAppName("uppercaseCountries")
|
||||||
|
.setMaster("local[*]");
|
||||||
|
sc = new JavaSparkContext(conf);
|
||||||
|
tourists = sc.textFile("data/Tourist.csv")
|
||||||
|
.filter(line -> !line.startsWith("Region")); //filter header row
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void cleanup() {
|
||||||
|
sc.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenMapUpperCase_thenCountryNameUppercased() {
|
||||||
|
JavaRDD<String> upperCaseCountries = tourists.map(line -> {
|
||||||
|
String[] columns = line.split(COMMA_DELIMITER);
|
||||||
|
return columns[1].toUpperCase();
|
||||||
|
})
|
||||||
|
.distinct();
|
||||||
|
|
||||||
|
upperCaseCountries.saveAsTextFile("data/output/uppercase.txt");
|
||||||
|
|
||||||
|
upperCaseCountries.foreach(country -> {
|
||||||
|
//replace non alphanumerical characters
|
||||||
|
country = country.replaceAll("[^a-zA-Z]", "");
|
||||||
|
assertTrue(StringUtils.isAllUpperCase(country));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenFilterByCountry_thenShowRequestedCountryRecords() {
|
||||||
|
JavaRDD<String> touristsInMexico = tourists.filter(line -> line.split(COMMA_DELIMITER)[1].equals("Mexico"));
|
||||||
|
|
||||||
|
touristsInMexico.saveAsTextFile("data/output/touristInMexico.txt");
|
||||||
|
|
||||||
|
touristsInMexico.foreach(record -> {
|
||||||
|
assertEquals("Mexico", record.split(COMMA_DELIMITER)[1]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -13,3 +13,4 @@
|
||||||
- [Quick Guide to the Java Stack](https://www.baeldung.com/java-stack)
|
- [Quick Guide to the Java Stack](https://www.baeldung.com/java-stack)
|
||||||
- [Convert an Array of Primitives to a List](https://www.baeldung.com/java-primitive-array-to-list)
|
- [Convert an Array of Primitives to a List](https://www.baeldung.com/java-primitive-array-to-list)
|
||||||
- [A Guide to BitSet in Java](https://www.baeldung.com/java-bitset)
|
- [A Guide to BitSet in Java](https://www.baeldung.com/java-bitset)
|
||||||
|
- [Get the First Key and Value From a HashMap](https://www.baeldung.com/java-hashmap-get-first-entry)
|
||||||
|
|
|
@ -11,4 +11,5 @@ This module contains articles about core Java input and output (IO)
|
||||||
- [Java Files Open Options](https://www.baeldung.com/java-file-options)
|
- [Java Files Open Options](https://www.baeldung.com/java-file-options)
|
||||||
- [Creating Temporary Directories in Java](https://www.baeldung.com/java-temp-directories)
|
- [Creating Temporary Directories in Java](https://www.baeldung.com/java-temp-directories)
|
||||||
- [Reading a Line at a Given Line Number From a File in Java](https://www.baeldung.com/java-read-line-at-number)
|
- [Reading a Line at a Given Line Number From a File in Java](https://www.baeldung.com/java-read-line-at-number)
|
||||||
|
- [Find the Last Modified File in a Directory with Java](https://www.baeldung.com/java-last-modified-file)
|
||||||
- [[<-- Prev]](/core-java-modules/core-java-io-2)
|
- [[<-- Prev]](/core-java-modules/core-java-io-2)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
@ -37,6 +38,12 @@ public class CreateFileUnitTest {
|
||||||
assertTrue(success);
|
assertTrue(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenUsingFileOutputStream_whenCreatingFile_thenCorrect() throws IOException {
|
||||||
|
try(FileOutputStream fileOutputStream = new FileOutputStream(FILE_NAME)){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenUsingGuava_whenCreatingFile_thenCorrect() throws IOException {
|
public void givenUsingGuava_whenCreatingFile_thenCorrect() throws IOException {
|
||||||
com.google.common.io.Files.touch(new File(FILE_NAME));
|
com.google.common.io.Files.touch(new File(FILE_NAME));
|
||||||
|
|
|
@ -6,4 +6,5 @@ This module contains articles about core features in the Java language
|
||||||
- [Converting a Java String Into a Boolean](https://www.baeldung.com/java-string-to-boolean)
|
- [Converting a Java String Into a Boolean](https://www.baeldung.com/java-string-to-boolean)
|
||||||
- [When are Static Variables Initialized in Java?](https://www.baeldung.com/java-static-variables-initialization)
|
- [When are Static Variables Initialized in Java?](https://www.baeldung.com/java-static-variables-initialization)
|
||||||
- [Checking if a Class Exists in Java](https://www.baeldung.com/java-check-class-exists)
|
- [Checking if a Class Exists in Java](https://www.baeldung.com/java-check-class-exists)
|
||||||
|
- [The Difference Between a.getClass() and A.class in Java](https://www.baeldung.com/java-getclass-vs-class)
|
||||||
- [[<-- Prev]](/core-java-modules/core-java-lang-2)
|
- [[<-- Prev]](/core-java-modules/core-java-lang-2)
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.baeldung.reflection.check.abstractclass;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
|
||||||
|
public abstract class AbstractExample {
|
||||||
|
|
||||||
|
public static String getAuthorName() {
|
||||||
|
return "Umang Budhwar";
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract LocalDate getLocalDate();
|
||||||
|
|
||||||
|
public abstract LocalTime getLocalTime();
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.baeldung.reflection.check.abstractclass;
|
||||||
|
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class AbstractExampleUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenAbstractClass_whenCheckModifierIsAbstract_thenTrue() throws Exception {
|
||||||
|
Class<AbstractExample> clazz = AbstractExample.class;
|
||||||
|
Assertions.assertTrue(Modifier.isAbstract(clazz.getModifiers()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -10,4 +10,6 @@ This module contains articles about core Java Security
|
||||||
- [SHA-256 and SHA3-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java)
|
- [SHA-256 and SHA3-256 Hashing in Java](https://www.baeldung.com/sha-256-hashing-java)
|
||||||
- [Checksums in Java](https://www.baeldung.com/java-checksums)
|
- [Checksums in Java](https://www.baeldung.com/java-checksums)
|
||||||
- [How to Read PEM File to Get Public and Private Keys](https://www.baeldung.com/java-read-pem-file-keys)
|
- [How to Read PEM File to Get Public and Private Keys](https://www.baeldung.com/java-read-pem-file-keys)
|
||||||
|
- [Listing the Available Cipher Algorithms](https://www.baeldung.com/java-list-cipher-algorithms)
|
||||||
|
- [Get a List of Trusted Certificates in Java](https://www.baeldung.com/java-list-trusted-certificates)
|
||||||
- More articles: [[<-- prev]](/core-java-modules/core-java-security)
|
- More articles: [[<-- prev]](/core-java-modules/core-java-security)
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.baeldung.arguments
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
|
||||||
|
// Skip both the connectTimeout and enableRetry arguments
|
||||||
|
connect("http://www.baeldung.com")
|
||||||
|
|
||||||
|
// Skip only the enableRetry argument:
|
||||||
|
connect("http://www.baeldung.com", 5000)
|
||||||
|
|
||||||
|
// Skip only the middle argument connectTimeout
|
||||||
|
// connect("http://www.baeldung.com", false) // This results in a compiler error
|
||||||
|
|
||||||
|
// Because we skipped the connectTimeout argument, we must pass the enableRetry as a named argument
|
||||||
|
connect("http://www.baeldung.com", enableRetry = false)
|
||||||
|
|
||||||
|
// Overriding Functions and Default Arguments
|
||||||
|
val realConnector = RealConnector()
|
||||||
|
realConnector.connect("www.baeldung.com")
|
||||||
|
realConnector.connect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun connect(url: String, connectTimeout: Int = 1000, enableRetry: Boolean = true) {
|
||||||
|
println("The parameters are url = $url, connectTimeout = $connectTimeout, enableRetry = $enableRetry")
|
||||||
|
}
|
||||||
|
|
||||||
|
open class AbstractConnector {
|
||||||
|
open fun connect(url: String = "localhost") {
|
||||||
|
// function implementation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RealConnector : AbstractConnector() {
|
||||||
|
override fun connect(url: String) {
|
||||||
|
println("The parameter is url = $url")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.baeldung.arguments
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
resizePane(newSize = 10, forceResize = true, noAnimation = false)
|
||||||
|
|
||||||
|
// Swap the order of last two named arguments
|
||||||
|
resizePane(newSize = 11, noAnimation = false, forceResize = true)
|
||||||
|
|
||||||
|
// Named arguments can be passed in any order
|
||||||
|
resizePane(forceResize = true, newSize = 12, noAnimation = false)
|
||||||
|
|
||||||
|
// Mixing Named and Positional Arguments
|
||||||
|
// Kotlin 1.3 would allow us to name only the arguments after the positional ones
|
||||||
|
resizePane(20, true, noAnimation = false)
|
||||||
|
|
||||||
|
// Using a positional argument in the middle of named arguments (supported from Kotlin 1.4.0)
|
||||||
|
// resizePane(newSize = 20, true, noAnimation = false)
|
||||||
|
|
||||||
|
// Only the last argument as a positional argument (supported from Kotlin 1.4.0)
|
||||||
|
// resizePane(newSize = 30, forceResize = true, false)
|
||||||
|
|
||||||
|
// Use a named argument in the middle of positional arguments (supported from Kotlin 1.4.0)
|
||||||
|
// resizePane(40, forceResize = true, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resizePane(newSize: Int, forceResize: Boolean, noAnimation: Boolean) {
|
||||||
|
println("The parameters are newSize = $newSize, forceResize = $forceResize, noAnimation = $noAnimation")
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
### Relevant Articles:
|
||||||
|
|
||||||
|
- [Guide to the Gradle Wrapper](https://www.baeldung.com/gradle-wrapper)
|
|
@ -8,5 +8,7 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
|
||||||
|
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
|
|
||||||
- [How to Set TLS Version in Apache HttpClient](https://www.baeldung.com/TODO)
|
- [How to Set TLS Version in Apache HttpClient](https://www.baeldung.com/apache-httpclient-tls)
|
||||||
|
- [Reading an HTTP Response Body as a String in Java](https://www.baeldung.com/java-http-response-body-as-string)
|
||||||
|
- [How To Get Cookies From the Apache HttpClient Response](https://www.baeldung.com/java-apache-httpclient-cookies)
|
||||||
- More articles: [[<-- prev]](../httpclient)
|
- More articles: [[<-- prev]](../httpclient)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
### Relevant Articles:
|
||||||
|
|
||||||
|
- [Getting Started with jOOQ](https://www.baeldung.com/jooq-intro)
|
|
@ -0,0 +1,10 @@
|
||||||
|
#spring.datasource.url=jdbc:h2:file:C:/data/demodb
|
||||||
|
#spring.datasource.url=jdbc:h2:file:~/demodb
|
||||||
|
spring.datasource.url=jdbc:h2:file:./src/main/resources/db/demodb
|
||||||
|
spring.datasource.driverClassName=org.h2.Driver
|
||||||
|
spring.datasource.username=sa
|
||||||
|
spring.datasource.password=
|
||||||
|
spring.h2.console.enabled=true
|
||||||
|
spring.jpa.hibernate.ddl-auto=create-drop
|
||||||
|
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
|
||||||
|
spring.h2.console.path=/h2-console
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.baeldung.persistent;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext;
|
||||||
|
import org.springframework.test.annotation.DirtiesContext.ClassMode;
|
||||||
|
import org.springframework.test.context.ActiveProfiles;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
import com.baeldung.h2db.auto.configuration.AutoConfigurationDemo;
|
||||||
|
|
||||||
|
@ActiveProfiles("persistent-on")
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@DirtiesContext(classMode = ClassMode.BEFORE_EACH_TEST_METHOD)
|
||||||
|
@SpringBootTest(classes = AutoConfigurationDemo.class)
|
||||||
|
public class FilesLocationUnitTest {
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void beforeClass() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = Test.None.class)
|
||||||
|
public void whenApplicationStarted_thenEmbeddedDbSubfolderCreated() {
|
||||||
|
File subdirectory = new File("src/main/resources/db");
|
||||||
|
System.out.println(subdirectory.getAbsolutePath());
|
||||||
|
assertTrue(subdirectory.exists());
|
||||||
|
assertTrue(subdirectory.isDirectory());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = Test.None.class)
|
||||||
|
public void whenApplicationStarted_thenEmbeddedDbFilesCreated() {
|
||||||
|
File dbFile = new File("src/main/resources/db/demodb.mv.db");
|
||||||
|
System.out.println(dbFile.getAbsolutePath());
|
||||||
|
|
||||||
|
assertTrue(dbFile.exists());
|
||||||
|
assertTrue(dbFile.isFile());
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void cleanUp() {
|
||||||
|
File dbFile = new File("src/main/resources/db/demodb.mv.db");
|
||||||
|
dbFile.deleteOnExit();
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,3 +5,4 @@ This module contains articles about configuring the Spring Boot `Environment`
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
- [EnvironmentPostProcessor in Spring Boot](https://www.baeldung.com/spring-boot-environmentpostprocessor)
|
- [EnvironmentPostProcessor in Spring Boot](https://www.baeldung.com/spring-boot-environmentpostprocessor)
|
||||||
- [Spring Properties File Outside jar](https://www.baeldung.com/spring-properties-file-outside-jar)
|
- [Spring Properties File Outside jar](https://www.baeldung.com/spring-properties-file-outside-jar)
|
||||||
|
- [Get the Running Port in Spring Boot](https://www.baeldung.com/spring-boot-running-port)
|
||||||
|
|
|
@ -76,7 +76,7 @@
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<keycloak-adapter-bom.version>10.0.2</keycloak-adapter-bom.version>
|
<keycloak-adapter-bom.version>11.0.2</keycloak-adapter-bom.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -8,4 +8,5 @@ This module contains articles about Spring Web MVC in Spring Boot projects.
|
||||||
- [Download an Image or a File with Spring MVC](https://www.baeldung.com/spring-controller-return-image-file)
|
- [Download an Image or a File with Spring MVC](https://www.baeldung.com/spring-controller-return-image-file)
|
||||||
- [Spring MVC Async vs Spring WebFlux](https://www.baeldung.com/spring-mvc-async-vs-webflux)
|
- [Spring MVC Async vs Spring WebFlux](https://www.baeldung.com/spring-mvc-async-vs-webflux)
|
||||||
- [Differences in @Valid and @Validated Annotations in Spring](https://www.baeldung.com/spring-valid-vs-validated)
|
- [Differences in @Valid and @Validated Annotations in Spring](https://www.baeldung.com/spring-valid-vs-validated)
|
||||||
|
- [CharacterEncodingFilter In SpringBoot](https://www.baeldung.com/spring-boot-characterencodingfilter)
|
||||||
- More articles: [[prev -->]](/spring-boot-modules/spring-boot-mvc-2)
|
- More articles: [[prev -->]](/spring-boot-modules/spring-boot-mvc-2)
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.baeldung.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-netlix-feign</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<name>spring-cloud-netflix-feign</name>
|
||||||
|
<description>Netflix Feign project for Spring Boot</description>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung</groupId>
|
||||||
|
<artifactId>parent-boot-1</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
<relativePath>../../parent-boot-1</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-dependencies</artifactId>
|
||||||
|
<version>${spring-cloud.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-feign</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.netflix.feign</groupId>
|
||||||
|
<artifactId>feign-okhttp</artifactId>
|
||||||
|
<version>${feign-ok.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpcore</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<spring-cloud.version>Camden.SR7</spring-cloud.version>
|
||||||
|
<feign-ok.version>8.18.0</feign-ok.version>
|
||||||
|
<!--
|
||||||
|
<spring-cloud.version>Hoxton.SR8</spring-cloud.version>
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
-->
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.baeldung.cloud.netflix.feign;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.cloud.netflix.feign.EnableFeignClients;
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
@EnableFeignClients
|
||||||
|
public class ExampleApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(ExampleApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package com.baeldung.cloud.netflix.feign.client;
|
||||||
|
|
||||||
|
import com.baeldung.cloud.netflix.feign.config.ClientConfiguration;
|
||||||
|
import com.baeldung.cloud.netflix.feign.hystrix.JSONPlaceHolderFallback;
|
||||||
|
import com.baeldung.cloud.netflix.feign.model.Post;
|
||||||
|
import org.springframework.cloud.netflix.feign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@FeignClient(value = "jplaceholder",
|
||||||
|
url = "https://jsonplaceholder.typicode.com/",
|
||||||
|
configuration = ClientConfiguration.class,
|
||||||
|
fallback = JSONPlaceHolderFallback.class)
|
||||||
|
public interface JSONPlaceHolderClient {
|
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, value = "/posts")
|
||||||
|
List<Post> getPosts();
|
||||||
|
|
||||||
|
|
||||||
|
@RequestMapping(method = RequestMethod.GET, value = "/posts/{postId}", produces = "application/json")
|
||||||
|
Post getPostById(@PathVariable("postId") Long postId);
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.baeldung.cloud.netflix.feign.config;
|
||||||
|
|
||||||
|
import feign.Logger;
|
||||||
|
import feign.RequestInterceptor;
|
||||||
|
import feign.codec.ErrorDecoder;
|
||||||
|
import feign.okhttp.OkHttpClient;
|
||||||
|
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class ClientConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public Logger.Level feignLoggerLevel() {
|
||||||
|
return Logger.Level.FULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ErrorDecoder errorDecoder() {
|
||||||
|
return new ErrorDecoder.Default();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public OkHttpClient client() {
|
||||||
|
return new OkHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RequestInterceptor requestInterceptor() {
|
||||||
|
return requestTemplate -> {
|
||||||
|
requestTemplate.header("user", "ajeje");
|
||||||
|
requestTemplate.header("password", "brazof");
|
||||||
|
requestTemplate.header("Accept", ContentType.APPLICATION_JSON.getMimeType());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.baeldung.cloud.netflix.feign.config;
|
||||||
|
|
||||||
|
import com.baeldung.cloud.netflix.feign.exception.BadRequestException;
|
||||||
|
import com.baeldung.cloud.netflix.feign.exception.NotFoundException;
|
||||||
|
import feign.Response;
|
||||||
|
import feign.codec.ErrorDecoder;
|
||||||
|
|
||||||
|
public class CustomErrorDecoder implements ErrorDecoder {
|
||||||
|
@Override
|
||||||
|
public Exception decode(String methodKey, Response response) {
|
||||||
|
|
||||||
|
switch (response.status()){
|
||||||
|
case 400:
|
||||||
|
return new BadRequestException();
|
||||||
|
case 404:
|
||||||
|
return new NotFoundException();
|
||||||
|
default:
|
||||||
|
return new Exception("Generic error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.baeldung.cloud.netflix.feign.exception;
|
||||||
|
|
||||||
|
public class BadRequestException extends Exception {
|
||||||
|
|
||||||
|
public BadRequestException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public BadRequestException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BadRequestException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "BadRequestException: "+getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.baeldung.cloud.netflix.feign.exception;
|
||||||
|
|
||||||
|
public class NotFoundException extends Exception {
|
||||||
|
|
||||||
|
public NotFoundException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotFoundException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotFoundException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "NotFoundException: "+getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.baeldung.cloud.netflix.feign.hystrix;
|
||||||
|
|
||||||
|
import com.baeldung.cloud.netflix.feign.client.JSONPlaceHolderClient;
|
||||||
|
import com.baeldung.cloud.netflix.feign.model.Post;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JSONPlaceHolderFallback implements JSONPlaceHolderClient {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Post> getPosts() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Post getPostById(Long postId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.baeldung.cloud.netflix.feign.model;
|
||||||
|
|
||||||
|
public class Post {
|
||||||
|
|
||||||
|
private String userId;
|
||||||
|
private Long id;
|
||||||
|
private String title;
|
||||||
|
private String body;
|
||||||
|
|
||||||
|
public String getUserId() {
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserId(String userId) {
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBody(String body) {
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.baeldung.cloud.netflix.feign.service;
|
||||||
|
|
||||||
|
import com.baeldung.cloud.netflix.feign.model.Post;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface JSONPlaceHolderService {
|
||||||
|
|
||||||
|
List<Post> getPosts();
|
||||||
|
|
||||||
|
Post getPostById(Long id);
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.baeldung.cloud.netflix.feign.service.impl;
|
||||||
|
|
||||||
|
import com.baeldung.cloud.netflix.feign.client.JSONPlaceHolderClient;
|
||||||
|
import com.baeldung.cloud.netflix.feign.model.Post;
|
||||||
|
import com.baeldung.cloud.netflix.feign.service.JSONPlaceHolderService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class JSONPlaceHolderServiceImpl implements JSONPlaceHolderService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JSONPlaceHolderClient jsonPlaceHolderClient;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Post> getPosts() {
|
||||||
|
return jsonPlaceHolderClient.getPosts();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Post getPostById(Long id) {
|
||||||
|
return jsonPlaceHolderClient.getPostById(id);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
spring.application.name=netflix-feign
|
||||||
|
logging.level.com.baeldung.cloud.netflix.feign.client=DEBUG
|
||||||
|
feign.hystrix.enabled=true
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.baeldung.cloud.netflix.feign;
|
||||||
|
|
||||||
|
import com.baeldung.cloud.netflix.feign.config.ClientConfiguration;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest
|
||||||
|
@EnableAutoConfiguration
|
||||||
|
@ContextConfiguration(classes = { ClientConfiguration.class })
|
||||||
|
public class ExampleTestApplication {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.baeldung.cloud.netflix.feign;
|
||||||
|
|
||||||
|
import com.baeldung.cloud.netflix.feign.model.Post;
|
||||||
|
import com.baeldung.cloud.netflix.feign.service.JSONPlaceHolderService;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.test.context.junit4.SpringRunner;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
@RunWith(SpringRunner.class)
|
||||||
|
@SpringBootTest
|
||||||
|
public class NetflixFeignUnitTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JSONPlaceHolderService jsonPlaceHolderService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenGetPosts_thenListPostSizeGreaterThanZero() {
|
||||||
|
|
||||||
|
List<Post> posts = jsonPlaceHolderService.getPosts();
|
||||||
|
|
||||||
|
assertFalse(posts.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenGetPostWithId_thenPostExist() {
|
||||||
|
|
||||||
|
Post post = jsonPlaceHolderService.getPostById(1L);
|
||||||
|
|
||||||
|
assertNotNull(post);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,27 +21,27 @@
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>info.cukes</groupId>
|
<groupId>io.cucumber</groupId>
|
||||||
<artifactId>cucumber-core</artifactId>
|
<artifactId>cucumber-core</artifactId>
|
||||||
<version>${cucumber.java.version}</version>
|
<version>${cucumber.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>info.cukes</groupId>
|
<groupId>io.cucumber</groupId>
|
||||||
<artifactId>cucumber-java</artifactId>
|
<artifactId>cucumber-java</artifactId>
|
||||||
<version>${cucumber.java.version}</version>
|
<version>${cucumber.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>info.cukes</groupId>
|
<groupId>io.cucumber</groupId>
|
||||||
<artifactId>cucumber-junit</artifactId>
|
<artifactId>cucumber-junit</artifactId>
|
||||||
<version>${cucumber.java.version}</version>
|
<version>${cucumber.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>info.cukes</groupId>
|
<groupId>io.cucumber</groupId>
|
||||||
<artifactId>cucumber-spring</artifactId>
|
<artifactId>cucumber-spring</artifactId>
|
||||||
<version>${cucumber.java.version}</version>
|
<version>${cucumber.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-io -->
|
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-io -->
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<cucumber.java.version>1.2.5</cucumber.java.version>
|
<cucumber.version>6.8.0</cucumber.version>
|
||||||
<commons-io.version>1.3.2</commons-io.version>
|
<commons-io.version>1.3.2</commons-io.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
|
@ -4,18 +4,16 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
public class BaeldungController {
|
public class BaeldungController {
|
||||||
|
|
||||||
@GetMapping("/hello")
|
@GetMapping("/hello")
|
||||||
public String sayHello(HttpServletResponse response) {
|
public String sayHello() {
|
||||||
return "hello";
|
return "hello";
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/baeldung")
|
@PostMapping("/baeldung")
|
||||||
public String sayHelloPost(HttpServletResponse response) {
|
public String sayHelloPost() {
|
||||||
return "hello";
|
return "hello";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
package com.baeldung;
|
package com.baeldung;
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
public class VersionController {
|
public class VersionController {
|
||||||
|
|
||||||
@RequestMapping(method = { RequestMethod.GET }, value = { "/version" })
|
@GetMapping("/version")
|
||||||
public String getVersion() {
|
public String getVersion() {
|
||||||
return "1.0";
|
return "1.0";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package com.baeldung;
|
package com.baeldung;
|
||||||
|
|
||||||
|
import io.cucumber.junit.Cucumber;
|
||||||
|
import io.cucumber.junit.CucumberOptions;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
import cucumber.api.CucumberOptions;
|
|
||||||
import cucumber.api.junit.Cucumber;
|
|
||||||
|
|
||||||
@RunWith(Cucumber.class)
|
@RunWith(Cucumber.class)
|
||||||
@CucumberOptions(features = "src/test/resources")
|
@CucumberOptions(features = "src/test/resources")
|
||||||
|
|
|
@ -4,6 +4,7 @@ import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import io.cucumber.spring.CucumberContextConfiguration;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||||
|
@ -13,9 +14,8 @@ import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.web.client.ResponseErrorHandler;
|
import org.springframework.web.client.ResponseErrorHandler;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
//@RunWith(SpringJUnit4ClassRunner.class)
|
@CucumberContextConfiguration
|
||||||
@SpringBootTest(classes = SpringDemoApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT)
|
@SpringBootTest(classes = SpringDemoApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT)
|
||||||
@ContextConfiguration
|
|
||||||
public class SpringIntegrationTest {
|
public class SpringIntegrationTest {
|
||||||
static ResponseResults latestResponse = null;
|
static ResponseResults latestResponse = null;
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
package com.baeldung;
|
package com.baeldung;
|
||||||
|
|
||||||
|
import io.cucumber.java.en.And;
|
||||||
|
import io.cucumber.java.en.Given;
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
import cucumber.api.java.en.Given;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
|
|
||||||
import cucumber.api.java.en.And;
|
|
||||||
import cucumber.api.java.en.Then;
|
|
||||||
import cucumber.api.java.en.When;
|
|
||||||
|
|
||||||
public class StepDefsIntegrationTest extends SpringIntegrationTest {
|
public class StepDefsIntegrationTest extends SpringIntegrationTest {
|
||||||
|
|
||||||
|
|
|
@ -1,37 +1,61 @@
|
||||||
package com.baeldung.spring.configuration;
|
package com.baeldung.spring.configuration;
|
||||||
|
|
||||||
|
import freemarker.cache.ClassTemplateLoader;
|
||||||
|
import freemarker.cache.TemplateLoader;
|
||||||
|
import freemarker.template.Configuration;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
import org.springframework.context.annotation.ComponentScan;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.PropertySource;
|
||||||
import org.springframework.context.support.ResourceBundleMessageSource;
|
import org.springframework.context.support.ResourceBundleMessageSource;
|
||||||
import org.springframework.mail.SimpleMailMessage;
|
import org.springframework.mail.SimpleMailMessage;
|
||||||
import org.springframework.mail.javamail.JavaMailSender;
|
import org.springframework.mail.javamail.JavaMailSender;
|
||||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||||
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
|
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
|
||||||
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
|
|
||||||
import org.thymeleaf.spring5.SpringTemplateEngine;
|
import org.thymeleaf.spring5.SpringTemplateEngine;
|
||||||
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
|
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
|
||||||
|
import org.thymeleaf.templateresolver.ITemplateResolver;
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@ComponentScan(basePackages = { "com.baeldung.spring.mail" })
|
@ComponentScan(basePackages = { "com.baeldung.spring.mail" })
|
||||||
|
@PropertySource(value={"classpath:application.properties"})
|
||||||
public class EmailConfiguration {
|
public class EmailConfiguration {
|
||||||
|
|
||||||
|
@Value("${spring.mail.host}")
|
||||||
|
private String mailServerHost;
|
||||||
|
|
||||||
|
@Value("${spring.mail.port}")
|
||||||
|
private Integer mailServerPort;
|
||||||
|
|
||||||
|
@Value("${spring.mail.username}")
|
||||||
|
private String mailServerUsername;
|
||||||
|
|
||||||
|
@Value("${spring.mail.password}")
|
||||||
|
private String mailServerPassword;
|
||||||
|
|
||||||
|
@Value("${spring.mail.properties.mail.smtp.auth}")
|
||||||
|
private String mailServerAuth;
|
||||||
|
|
||||||
|
@Value("${spring.mail.properties.mail.smtp.starttls.enable}")
|
||||||
|
private String mailServerStartTls;
|
||||||
|
|
||||||
|
@Value("${spring.mail.templates.path}")
|
||||||
|
private String mailTemplatesPath;
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public JavaMailSender getJavaMailSender() {
|
public JavaMailSender getJavaMailSender() {
|
||||||
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
|
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
|
||||||
|
|
||||||
mailSender.setHost("smtp.gmail.com");
|
mailSender.setHost(mailServerHost);
|
||||||
mailSender.setPort(587);
|
mailSender.setPort(mailServerPort);
|
||||||
|
|
||||||
mailSender.setUsername("my.gmail@gmail.com");
|
mailSender.setUsername(mailServerUsername);
|
||||||
mailSender.setPassword("password");
|
mailSender.setPassword(mailServerPassword);
|
||||||
|
|
||||||
Properties props = mailSender.getJavaMailProperties();
|
Properties props = mailSender.getJavaMailProperties();
|
||||||
props.put("mail.transport.protocol", "smtp");
|
props.put("mail.transport.protocol", "smtp");
|
||||||
props.put("mail.smtp.auth", "true");
|
props.put("mail.smtp.auth", mailServerAuth);
|
||||||
props.put("mail.smtp.starttls.enable", "false");
|
props.put("mail.smtp.starttls.enable", mailServerStartTls);
|
||||||
props.put("mail.debug", "true");
|
props.put("mail.debug", "true");
|
||||||
|
|
||||||
return mailSender;
|
return mailSender;
|
||||||
|
@ -45,39 +69,52 @@ public class EmailConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SpringTemplateEngine thymeleafTemplateEngine() {
|
public SpringTemplateEngine thymeleafTemplateEngine(ITemplateResolver templateResolver) {
|
||||||
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
|
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
|
||||||
templateEngine.setTemplateResolver(thymeleafTemplateResolver());
|
templateEngine.setTemplateResolver(templateResolver);
|
||||||
templateEngine.setTemplateEngineMessageSource(emailMessageSource());
|
templateEngine.setTemplateEngineMessageSource(emailMessageSource());
|
||||||
return templateEngine;
|
return templateEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public SpringResourceTemplateResolver thymeleafTemplateResolver() {
|
public ITemplateResolver thymeleafClassLoaderTemplateResolver() {
|
||||||
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
|
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
|
||||||
templateResolver.setPrefix("/WEB-INF/views/mail/");
|
templateResolver.setPrefix(mailTemplatesPath + "/");
|
||||||
templateResolver.setSuffix(".html");
|
templateResolver.setSuffix(".html");
|
||||||
templateResolver.setTemplateMode("HTML");
|
templateResolver.setTemplateMode("HTML");
|
||||||
templateResolver.setCharacterEncoding("UTF-8");
|
templateResolver.setCharacterEncoding("UTF-8");
|
||||||
return templateResolver;
|
return templateResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @Bean
|
||||||
|
// public ITemplateResolver thymeleafFilesystemTemplateResolver() {
|
||||||
|
// FileTemplateResolver templateResolver = new FileTemplateResolver();
|
||||||
|
// templateResolver.setPrefix(mailTemplatesPath + "/");
|
||||||
|
// templateResolver.setSuffix(".html");
|
||||||
|
// templateResolver.setTemplateMode("HTML");
|
||||||
|
// templateResolver.setCharacterEncoding("UTF-8");
|
||||||
|
// return templateResolver;
|
||||||
|
// }
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public FreeMarkerConfigurer freemarkerConfig() {
|
public FreeMarkerConfigurer freemarkerClassLoaderConfig() {
|
||||||
|
Configuration configuration = new Configuration(Configuration.VERSION_2_3_27);
|
||||||
|
TemplateLoader templateLoader = new ClassTemplateLoader(this.getClass(), "/" + mailTemplatesPath);
|
||||||
|
configuration.setTemplateLoader(templateLoader);
|
||||||
FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
|
FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
|
||||||
freeMarkerConfigurer.setTemplateLoaderPath("/WEB-INF/views/mail");
|
freeMarkerConfigurer.setConfiguration(configuration);
|
||||||
return freeMarkerConfigurer;
|
return freeMarkerConfigurer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
// @Bean
|
||||||
public FreeMarkerViewResolver freemarkerViewResolver() {
|
// public FreeMarkerConfigurer freemarkerFilesystemConfig() throws IOException {
|
||||||
FreeMarkerViewResolver resolver = new FreeMarkerViewResolver();
|
// Configuration configuration = new Configuration(Configuration.VERSION_2_3_27);
|
||||||
resolver.setCache(true);
|
// TemplateLoader templateLoader = new FileTemplateLoader(new File(mailTemplatesPath));
|
||||||
resolver.setPrefix("");
|
// configuration.setTemplateLoader(templateLoader);
|
||||||
resolver.setSuffix(".ftl");
|
// FreeMarkerConfigurer freeMarkerConfigurer = new FreeMarkerConfigurer();
|
||||||
return resolver;
|
// freeMarkerConfigurer.setConfiguration(configuration);
|
||||||
}
|
// return freeMarkerConfigurer;
|
||||||
|
// }
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public ResourceBundleMessageSource emailMessageSource() {
|
public ResourceBundleMessageSource emailMessageSource() {
|
||||||
|
|
|
@ -112,7 +112,7 @@ public class EmailServiceImpl implements EmailService {
|
||||||
String to, String subject, Map<String, Object> templateModel)
|
String to, String subject, Map<String, Object> templateModel)
|
||||||
throws IOException, TemplateException, MessagingException {
|
throws IOException, TemplateException, MessagingException {
|
||||||
|
|
||||||
Template freemarkerTemplate = freemarkerConfigurer.createConfiguration().getTemplate("template-freemarker.ftl");
|
Template freemarkerTemplate = freemarkerConfigurer.getConfiguration().getTemplate("template-freemarker.ftl");
|
||||||
String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerTemplate, templateModel);
|
String htmlBody = FreeMarkerTemplateUtils.processTemplateIntoString(freemarkerTemplate, templateModel);
|
||||||
|
|
||||||
sendHtmlMessage(to, subject, htmlBody);
|
sendHtmlMessage(to, subject, htmlBody);
|
||||||
|
|
|
@ -6,7 +6,7 @@ spring.mail.port=587
|
||||||
spring.mail.username=username
|
spring.mail.username=username
|
||||||
spring.mail.password=password
|
spring.mail.password=password
|
||||||
spring.mail.properties.mail.smtp.auth=true
|
spring.mail.properties.mail.smtp.auth=true
|
||||||
spring.mail.properties.mail.smtp.starttls.enable=true
|
spring.mail.properties.mail.smtp.starttls.enable=false
|
||||||
|
|
||||||
# Amazon SES SMTP
|
# Amazon SES SMTP
|
||||||
#spring.mail.host=email-smtp.us-west-2.amazonaws.com
|
#spring.mail.host=email-smtp.us-west-2.amazonaws.com
|
||||||
|
@ -20,3 +20,13 @@ spring.mail.properties.mail.smtp.starttls.enable=true
|
||||||
|
|
||||||
# path to attachment file
|
# path to attachment file
|
||||||
attachment.invoice=path_to_file
|
attachment.invoice=path_to_file
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Mail templates
|
||||||
|
#
|
||||||
|
|
||||||
|
# Templates directory inside main/resources or absolute filesystem path
|
||||||
|
spring.mail.templates.path=mail-templates
|
||||||
|
#spring.mail.templates.path=/path/to/templates
|
||||||
|
|
||||||
|
|
|
@ -5,3 +5,4 @@
|
||||||
- [Introduction to JUnitParams](http://www.baeldung.com/junit-params)
|
- [Introduction to JUnitParams](http://www.baeldung.com/junit-params)
|
||||||
- [Running JUnit Tests Programmatically, from a Java Application](https://www.baeldung.com/junit-tests-run-programmatically-from-java)
|
- [Running JUnit Tests Programmatically, from a Java Application](https://www.baeldung.com/junit-tests-run-programmatically-from-java)
|
||||||
- [Introduction to Lambda Behave](https://www.baeldung.com/lambda-behave)
|
- [Introduction to Lambda Behave](https://www.baeldung.com/lambda-behave)
|
||||||
|
- [Conditionally Run or Ignore Tests in JUnit 4](https://www.baeldung.com/junit-conditional-assume)
|
||||||
|
|
|
@ -7,3 +7,4 @@
|
||||||
- [Testing an Abstract Class With JUnit](https://www.baeldung.com/junit-test-abstract-class)
|
- [Testing an Abstract Class With JUnit](https://www.baeldung.com/junit-test-abstract-class)
|
||||||
- [Guide to Dynamic Tests in JUnit 5](https://www.baeldung.com/junit5-dynamic-tests)
|
- [Guide to Dynamic Tests in JUnit 5](https://www.baeldung.com/junit5-dynamic-tests)
|
||||||
- [Determine the Execution Time of JUnit Tests](https://www.baeldung.com/junit-test-execution-time)
|
- [Determine the Execution Time of JUnit Tests](https://www.baeldung.com/junit-test-execution-time)
|
||||||
|
- [@BeforeAll and @AfterAll in Non-Static Methods](https://www.baeldung.com/java-beforeall-afterall-non-static)
|
||||||
|
|
|
@ -65,13 +65,13 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>info.cukes</groupId>
|
<groupId>io.cucumber</groupId>
|
||||||
<artifactId>cucumber-java</artifactId>
|
<artifactId>cucumber-java</artifactId>
|
||||||
<version>${cucumber.version}</version>
|
<version>${cucumber.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>info.cukes</groupId>
|
<groupId>io.cucumber</groupId>
|
||||||
<artifactId>cucumber-junit</artifactId>
|
<artifactId>cucumber-junit</artifactId>
|
||||||
<version>${cucumber.version}</version>
|
<version>${cucumber.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
@ -105,14 +105,22 @@
|
||||||
<filtering>true</filtering>
|
<filtering>true</filtering>
|
||||||
</resource>
|
</resource>
|
||||||
</resources>
|
</resources>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>parallel</id>
|
||||||
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-failsafe-plugin</artifactId>
|
<artifactId>maven-failsafe-plugin</artifactId>
|
||||||
<version>${maven-failsafe-plugin.version}</version>
|
<version>${maven-failsafe-plugin.version}</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<parallel>classes</parallel>
|
<includes>
|
||||||
<threadCount>4</threadCount>
|
<include>CucumberIntegrationTest.java</include>
|
||||||
|
</includes>
|
||||||
|
<parallel>methods</parallel>
|
||||||
|
<threadCount>2</threadCount>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
|
@ -123,30 +131,10 @@
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>com.github.temyers</groupId>
|
|
||||||
<artifactId>cucumber-jvm-parallel-plugin</artifactId>
|
|
||||||
<version>5.0.0</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>generateRunners</id>
|
|
||||||
<phase>generate-test-sources</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>generateRunners</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<glue>
|
|
||||||
<package>com.baeldung.rest.cucumber</package>
|
|
||||||
</glue>
|
|
||||||
<featuresDirectory>src/test/resources/Feature/</featuresDirectory>
|
|
||||||
<parallelScheme>SCENARIO</parallelScheme>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|
||||||
</build>
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<!-- util -->
|
<!-- util -->
|
||||||
|
@ -154,7 +142,7 @@
|
||||||
|
|
||||||
<!-- testing -->
|
<!-- testing -->
|
||||||
<rest-assured.version>2.9.0</rest-assured.version>
|
<rest-assured.version>2.9.0</rest-assured.version>
|
||||||
<cucumber.version>1.2.5</cucumber.version>
|
<cucumber.version>6.8.0</cucumber.version>
|
||||||
<wiremock.version>2.21.0</wiremock.version>
|
<wiremock.version>2.21.0</wiremock.version>
|
||||||
<karate.version>0.6.1</karate.version>
|
<karate.version>0.6.1</karate.version>
|
||||||
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
Feature: Testing a REST API
|
|
||||||
Users should be able to submit GET and POST requests to a web service, represented by WireMock
|
|
||||||
|
|
||||||
Scenario: Data Upload to a web service
|
|
||||||
When users upload data on a project
|
|
||||||
Then the server should handle it and return a success status
|
|
||||||
|
|
||||||
Scenario: Data retrieval from a web service
|
|
||||||
When users want to get information on the Cucumber project
|
|
||||||
Then the requested data is returned
|
|
|
@ -1,8 +1,8 @@
|
||||||
package com.baeldung.rest.cucumber;
|
package com.baeldung.rest.cucumber;
|
||||||
|
|
||||||
|
import io.cucumber.junit.Cucumber;
|
||||||
|
import io.cucumber.junit.CucumberOptions;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import cucumber.api.CucumberOptions;
|
|
||||||
import cucumber.api.junit.Cucumber;
|
|
||||||
|
|
||||||
@RunWith(Cucumber.class)
|
@RunWith(Cucumber.class)
|
||||||
@CucumberOptions(features = "classpath:Feature")
|
@CucumberOptions(features = "classpath:Feature")
|
||||||
|
|
|
@ -20,6 +20,8 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
|
||||||
|
import io.cucumber.java.en.Then;
|
||||||
|
import io.cucumber.java.en.When;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.client.methods.HttpPost;
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
@ -29,8 +31,6 @@ import org.apache.http.impl.client.HttpClients;
|
||||||
|
|
||||||
import com.github.tomakehurst.wiremock.WireMockServer;
|
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||||
|
|
||||||
import cucumber.api.java.en.Then;
|
|
||||||
import cucumber.api.java.en.When;
|
|
||||||
|
|
||||||
public class StepDefinition {
|
public class StepDefinition {
|
||||||
|
|
||||||
|
@ -66,7 +66,8 @@ public class StepDefinition {
|
||||||
wireMockServer.stop();
|
wireMockServer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@When("^users want to get information on the (.+) project$")
|
// @When("^users want to get information on the '(.+)' project$")
|
||||||
|
@When("users want to get information on the {string} project")
|
||||||
public void usersGetInformationOnAProject(String projectName) throws IOException {
|
public void usersGetInformationOnAProject(String projectName) throws IOException {
|
||||||
wireMockServer.start();
|
wireMockServer.start();
|
||||||
|
|
||||||
|
@ -86,11 +87,11 @@ public class StepDefinition {
|
||||||
wireMockServer.stop();
|
wireMockServer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Then("^the server should handle it and return a success status$")
|
@Then("the server should handle it and return a success status")
|
||||||
public void theServerShouldReturnASuccessStatus() {
|
public void theServerShouldReturnASuccessStatus() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Then("^the requested data is returned$")
|
@Then("the requested data is returned")
|
||||||
public void theRequestedDataIsReturned() {
|
public void theRequestedDataIsReturned() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,5 +6,5 @@ Feature: Testing a REST API
|
||||||
Then the server should handle it and return a success status
|
Then the server should handle it and return a success status
|
||||||
|
|
||||||
Scenario: Data retrieval from a web service
|
Scenario: Data retrieval from a web service
|
||||||
When users want to get information on the Cucumber project
|
When users want to get information on the 'Cucumber' project
|
||||||
Then the requested data is returned
|
Then the requested data is returned
|
Loading…
Reference in New Issue