diff --git a/algorithms-miscellaneous-3/pom.xml b/algorithms-miscellaneous-3/pom.xml index 802cf74320..5999d33c86 100644 --- a/algorithms-miscellaneous-3/pom.xml +++ b/algorithms-miscellaneous-3/pom.xml @@ -1,5 +1,5 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 algorithms-miscellaneous-3 0.0.1-SNAPSHOT @@ -18,17 +18,28 @@ ${org.assertj.core.version} test - + - org.apache.commons - commons-collections4 - ${commons-collections4.version} + org.apache.commons + commons-collections4 + ${commons-collections4.version} - + - com.google.guava - guava - ${guava.version} + com.google.guava + guava + ${guava.version} + + + + com.squareup.retrofit2 + retrofit + ${retrofit.version} + + + com.squareup.retrofit2 + converter-jackson + ${retrofit.version} @@ -61,5 +72,6 @@ 3.9.0 4.3 28.0-jre + 2.6.0 \ No newline at end of file diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/interpolationsearch/InterpolationSearch.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/interpolationsearch/InterpolationSearch.java new file mode 100644 index 0000000000..91423eeaa8 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/interpolationsearch/InterpolationSearch.java @@ -0,0 +1,35 @@ +package com.baeldung.algorithms.interpolationsearch; + +public class InterpolationSearch { + + public static int interpolationSearch(int[] data, int item) { + + int highEnd = (data.length - 1); + int lowEnd = 0; + + while (item >= data[lowEnd] && item <= data[highEnd] && lowEnd <= highEnd) { + + int probe = lowEnd + (highEnd - lowEnd) * (item - data[lowEnd]) / (data[highEnd] - data[lowEnd]); + + if (highEnd == lowEnd) { + if (data[lowEnd] == item) { + return lowEnd; + } else { + return -1; + } + } + + if (data[probe] == item) { + return probe; + } + + if (data[probe] < item) { + lowEnd = probe + 1; + } else { + highEnd = probe - 1; + } + } + return -1; + } + +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/Centroid.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/Centroid.java new file mode 100644 index 0000000000..523d5b56a5 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/Centroid.java @@ -0,0 +1,45 @@ +package com.baeldung.algorithms.kmeans; + +import java.util.Map; +import java.util.Objects; + +/** + * Encapsulates all coordinates for a particular cluster centroid. + */ +public class Centroid { + + /** + * The centroid coordinates. + */ + private final Map coordinates; + + public Centroid(Map coordinates) { + this.coordinates = coordinates; + } + + public Map getCoordinates() { + return coordinates; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Centroid centroid = (Centroid) o; + return Objects.equals(getCoordinates(), centroid.getCoordinates()); + } + + @Override + public int hashCode() { + return Objects.hash(getCoordinates()); + } + + @Override + public String toString() { + return "Centroid " + coordinates; + } +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/Distance.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/Distance.java new file mode 100644 index 0000000000..30723cb6b3 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/Distance.java @@ -0,0 +1,20 @@ +package com.baeldung.algorithms.kmeans; + +import java.util.Map; + +/** + * Defines a contract to calculate distance between two feature vectors. The less the + * calculated distance, the more two items are similar to each other. + */ +public interface Distance { + + /** + * Calculates the distance between two feature vectors. + * + * @param f1 The first set of features. + * @param f2 The second set of features. + * @return Calculated distance. + * @throws IllegalArgumentException If the given feature vectors are invalid. + */ + double calculate(Map f1, Map f2); +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/Errors.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/Errors.java new file mode 100644 index 0000000000..3228876051 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/Errors.java @@ -0,0 +1,23 @@ +package com.baeldung.algorithms.kmeans; + +import java.util.List; +import java.util.Map; + +/** + * Encapsulates methods to calculates errors between centroid and the cluster members. + */ +public class Errors { + + public static double sse(Map> clustered, Distance distance) { + double sum = 0; + for (Map.Entry> entry : clustered.entrySet()) { + Centroid centroid = entry.getKey(); + for (Record record : entry.getValue()) { + double d = distance.calculate(centroid.getCoordinates(), record.getFeatures()); + sum += Math.pow(d, 2); + } + } + + return sum; + } +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/EuclideanDistance.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/EuclideanDistance.java new file mode 100644 index 0000000000..193d9afed1 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/EuclideanDistance.java @@ -0,0 +1,26 @@ +package com.baeldung.algorithms.kmeans; + +import java.util.Map; + +/** + * Calculates the distance between two items using the Euclidean formula. + */ +public class EuclideanDistance implements Distance { + + @Override + public double calculate(Map f1, Map f2) { + if (f1 == null || f2 == null) { + throw new IllegalArgumentException("Feature vectors can't be null"); + } + + double sum = 0; + for (String key : f1.keySet()) { + Double v1 = f1.get(key); + Double v2 = f2.get(key); + + if (v1 != null && v2 != null) sum += Math.pow(v1 - v2, 2); + } + + return Math.sqrt(sum); + } +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/KMeans.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/KMeans.java new file mode 100644 index 0000000000..1fb8541ff9 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/KMeans.java @@ -0,0 +1,236 @@ +package com.baeldung.algorithms.kmeans; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.Set; + +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toSet; + +/** + * Encapsulates an implementation of KMeans clustering algorithm. + * + * @author Ali Dehghani + */ +public class KMeans { + + private KMeans() { + throw new IllegalAccessError("You shouldn't call this constructor"); + } + + /** + * Will be used to generate random numbers. + */ + private static final Random random = new Random(); + + /** + * Performs the K-Means clustering algorithm on the given dataset. + * + * @param records The dataset. + * @param k Number of Clusters. + * @param distance To calculate the distance between two items. + * @param maxIterations Upper bound for the number of iterations. + * @return K clusters along with their features. + */ + public static Map> fit(List records, int k, Distance distance, int maxIterations) { + applyPreconditions(records, k, distance, maxIterations); + + List centroids = randomCentroids(records, k); + Map> clusters = new HashMap<>(); + Map> lastState = new HashMap<>(); + + // iterate for a pre-defined number of times + for (int i = 0; i < maxIterations; i++) { + boolean isLastIteration = i == maxIterations - 1; + + // in each iteration we should find the nearest centroid for each record + for (Record record : records) { + Centroid centroid = nearestCentroid(record, centroids, distance); + assignToCluster(clusters, record, centroid); + } + + // if the assignment does not change, then the algorithm terminates + boolean shouldTerminate = isLastIteration || clusters.equals(lastState); + lastState = clusters; + if (shouldTerminate) { + break; + } + + // at the end of each iteration we should relocate the centroids + centroids = relocateCentroids(clusters); + clusters = new HashMap<>(); + } + + return lastState; + } + + /** + * Move all cluster centroids to the average of all assigned features. + * + * @param clusters The current cluster configuration. + * @return Collection of new and relocated centroids. + */ + private static List relocateCentroids(Map> clusters) { + return clusters + .entrySet() + .stream() + .map(e -> average(e.getKey(), e.getValue())) + .collect(toList()); + } + + /** + * Moves the given centroid to the average position of all assigned features. If + * the centroid has no feature in its cluster, then there would be no need for a + * relocation. Otherwise, for each entry we calculate the average of all records + * first by summing all the entries and then dividing the final summation value by + * the number of records. + * + * @param centroid The centroid to move. + * @param records The assigned features. + * @return The moved centroid. + */ + private static Centroid average(Centroid centroid, List records) { + // if this cluster is empty, then we shouldn't move the centroid + if (records == null || records.isEmpty()) { + return centroid; + } + + // Since some records don't have all possible attributes, we initialize + // average coordinates equal to current centroid coordinates + Map average = centroid.getCoordinates(); + + // The average function works correctly if we clear all coordinates corresponding + // to present record attributes + records + .stream() + .flatMap(e -> e + .getFeatures() + .keySet() + .stream()) + .forEach(k -> average.put(k, 0.0)); + + for (Record record : records) { + record + .getFeatures() + .forEach((k, v) -> average.compute(k, (k1, currentValue) -> v + currentValue)); + } + + average.forEach((k, v) -> average.put(k, v / records.size())); + + return new Centroid(average); + } + + /** + * Assigns a feature vector to the given centroid. If this is the first assignment for this centroid, + * first we should create the list. + * + * @param clusters The current cluster configuration. + * @param record The feature vector. + * @param centroid The centroid. + */ + private static void assignToCluster(Map> clusters, Record record, Centroid centroid) { + clusters.compute(centroid, (key, list) -> { + if (list == null) { + list = new ArrayList<>(); + } + + list.add(record); + return list; + }); + } + + /** + * With the help of the given distance calculator, iterates through centroids and finds the + * nearest one to the given record. + * + * @param record The feature vector to find a centroid for. + * @param centroids Collection of all centroids. + * @param distance To calculate the distance between two items. + * @return The nearest centroid to the given feature vector. + */ + private static Centroid nearestCentroid(Record record, List centroids, Distance distance) { + double minimumDistance = Double.MAX_VALUE; + Centroid nearest = null; + + for (Centroid centroid : centroids) { + double currentDistance = distance.calculate(record.getFeatures(), centroid.getCoordinates()); + + if (currentDistance < minimumDistance) { + minimumDistance = currentDistance; + nearest = centroid; + } + } + + return nearest; + } + + /** + * Generates k random centroids. Before kicking-off the centroid generation process, + * first we calculate the possible value range for each attribute. Then when + * we're going to generate the centroids, we generate random coordinates in + * the [min, max] range for each attribute. + * + * @param records The dataset which helps to calculate the [min, max] range for + * each attribute. + * @param k Number of clusters. + * @return Collections of randomly generated centroids. + */ + private static List randomCentroids(List records, int k) { + List centroids = new ArrayList<>(); + Map maxs = new HashMap<>(); + Map mins = new HashMap<>(); + + for (Record record : records) { + record + .getFeatures() + .forEach((key, value) -> { + // compares the value with the current max and choose the bigger value between them + maxs.compute(key, (k1, max) -> max == null || value > max ? value : max); + + // compare the value with the current min and choose the smaller value between them + mins.compute(key, (k1, min) -> min == null || value < min ? value : min); + }); + } + + Set attributes = records + .stream() + .flatMap(e -> e + .getFeatures() + .keySet() + .stream()) + .collect(toSet()); + for (int i = 0; i < k; i++) { + Map coordinates = new HashMap<>(); + for (String attribute : attributes) { + double max = maxs.get(attribute); + double min = mins.get(attribute); + coordinates.put(attribute, random.nextDouble() * (max - min) + min); + } + + centroids.add(new Centroid(coordinates)); + } + + return centroids; + } + + private static void applyPreconditions(List records, int k, Distance distance, int maxIterations) { + if (records == null || records.isEmpty()) { + throw new IllegalArgumentException("The dataset can't be empty"); + } + + if (k <= 1) { + throw new IllegalArgumentException("It doesn't make sense to have less than or equal to 1 cluster"); + } + + if (distance == null) { + throw new IllegalArgumentException("The distance calculator is required"); + } + + if (maxIterations <= 0) { + throw new IllegalArgumentException("Max iterations should be a positive number"); + } + } +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/LastFm.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/LastFm.java new file mode 100644 index 0000000000..4694a845af --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/LastFm.java @@ -0,0 +1,144 @@ +package com.baeldung.algorithms.kmeans; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.databind.ObjectMapper; +import okhttp3.OkHttpClient; +import retrofit2.Retrofit; +import retrofit2.converter.jackson.JacksonConverterFactory; + +import static java.util.stream.Collectors.toSet; + +public class LastFm { + + private static OkHttpClient okHttp = new OkHttpClient.Builder() + .addInterceptor(new LastFmService.Authenticator("put your API key here")) + .build(); + + private static Retrofit retrofit = new Retrofit.Builder() + .client(okHttp) + .addConverterFactory(JacksonConverterFactory.create()) + .baseUrl("http://ws.audioscrobbler.com/") + .build(); + + private static LastFmService lastFm = retrofit.create(LastFmService.class); + + private static ObjectMapper mapper = new ObjectMapper(); + + public static void main(String[] args) throws IOException { + List artists = getTop100Artists(); + Set tags = getTop100Tags(); + List records = datasetWithTaggedArtists(artists, tags); + + Map> clusters = KMeans.fit(records, 7, new EuclideanDistance(), 1000); + // Print the cluster configuration + clusters.forEach((key, value) -> { + System.out.println("------------------------------ CLUSTER -----------------------------------"); + + System.out.println(sortedCentroid(key)); + String members = String.join(", ", value + .stream() + .map(Record::getDescription) + .collect(toSet())); + System.out.print(members); + + System.out.println(); + System.out.println(); + }); + + Map json = convertToD3CompatibleMap(clusters); + System.out.println(mapper.writeValueAsString(json)); + } + + private static Map convertToD3CompatibleMap(Map> clusters) { + Map json = new HashMap<>(); + json.put("name", "Musicians"); + List> children = new ArrayList<>(); + clusters.forEach((key, value) -> { + Map child = new HashMap<>(); + child.put("name", dominantGenre(sortedCentroid(key))); + List> nested = new ArrayList<>(); + for (Record record : value) { + nested.add(Collections.singletonMap("name", record.getDescription())); + } + child.put("children", nested); + + children.add(child); + }); + json.put("children", children); + return json; + } + + private static String dominantGenre(Centroid centroid) { + return centroid + .getCoordinates() + .keySet() + .stream() + .limit(2) + .collect(Collectors.joining(", ")); + } + + private static Centroid sortedCentroid(Centroid key) { + List> entries = new ArrayList<>(key + .getCoordinates() + .entrySet()); + entries.sort((e1, e2) -> e2 + .getValue() + .compareTo(e1.getValue())); + + Map sorted = new LinkedHashMap<>(); + for (Map.Entry entry : entries) { + sorted.put(entry.getKey(), entry.getValue()); + } + + return new Centroid(sorted); + } + + private static List datasetWithTaggedArtists(List artists, Set topTags) throws IOException { + List records = new ArrayList<>(); + for (String artist : artists) { + Map tags = lastFm + .topTagsFor(artist) + .execute() + .body() + .all(); + + // Only keep popular tags. + tags + .entrySet() + .removeIf(e -> !topTags.contains(e.getKey())); + + records.add(new Record(artist, tags)); + } + return records; + } + + private static Set getTop100Tags() throws IOException { + return lastFm + .topTags() + .execute() + .body() + .all(); + } + + private static List getTop100Artists() throws IOException { + List artists = new ArrayList<>(); + for (int i = 1; i <= 2; i++) { + artists.addAll(lastFm + .topArtists(i) + .execute() + .body() + .all()); + } + + return artists; + } +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/LastFmService.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/LastFmService.java new file mode 100644 index 0000000000..db57deb888 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/LastFmService.java @@ -0,0 +1,118 @@ +package com.baeldung.algorithms.kmeans; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonProperty; +import okhttp3.HttpUrl; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; +import retrofit2.Call; +import retrofit2.http.GET; +import retrofit2.http.Query; + +import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY; +import static java.util.stream.Collectors.toList; + +public interface LastFmService { + + @GET("/2.0/?method=chart.gettopartists&format=json&limit=50") + Call topArtists(@Query("page") int page); + + @GET("/2.0/?method=artist.gettoptags&format=json&limit=20&autocorrect=1") + Call topTagsFor(@Query("artist") String artist); + + @GET("/2.0/?method=chart.gettoptags&format=json&limit=100") + Call topTags(); + + /** + * HTTP interceptor to intercept all HTTP requests and add the API key to them. + */ + class Authenticator implements Interceptor { + + private final String apiKey; + + Authenticator(String apiKey) { + this.apiKey = apiKey; + } + + @Override + public Response intercept(Chain chain) throws IOException { + HttpUrl url = chain + .request() + .url() + .newBuilder() + .addQueryParameter("api_key", apiKey) + .build(); + Request request = chain + .request() + .newBuilder() + .url(url) + .build(); + + return chain.proceed(request); + } + } + + @JsonAutoDetect(fieldVisibility = ANY) + class TopTags { + + private Map tags; + + @SuppressWarnings("unchecked") + public Set all() { + List> topTags = (List>) tags.get("tag"); + return topTags + .stream() + .map(e -> ((String) e.get("name"))) + .collect(Collectors.toSet()); + } + } + + @JsonAutoDetect(fieldVisibility = ANY) + class Tags { + + @JsonProperty("toptags") private Map topTags; + + @SuppressWarnings("unchecked") + public Map all() { + try { + Map all = new HashMap<>(); + List> tags = (List>) topTags.get("tag"); + for (Map tag : tags) { + all.put(((String) tag.get("name")), ((Integer) tag.get("count")).doubleValue()); + } + + return all; + } catch (Exception e) { + return Collections.emptyMap(); + } + } + } + + @JsonAutoDetect(fieldVisibility = ANY) + class Artists { + + private Map artists; + + @SuppressWarnings("unchecked") + public List all() { + try { + List> artists = (List>) this.artists.get("artist"); + return artists + .stream() + .map(e -> ((String) e.get("name"))) + .collect(toList()); + } catch (Exception e) { + return Collections.emptyList(); + } + } + } +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/Record.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/Record.java new file mode 100644 index 0000000000..d2a7b61c62 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/kmeans/Record.java @@ -0,0 +1,65 @@ +package com.baeldung.algorithms.kmeans; + +import java.util.Map; +import java.util.Objects; + +/** + * Encapsulates all feature values for a few attributes. Optionally each record + * can be described with the {@link #description} field. + */ +public class Record { + + /** + * The record description. For example, this can be the artist name for the famous musician + * example. + */ + private final String description; + + /** + * Encapsulates all attributes and their corresponding values, i.e. features. + */ + private final Map features; + + public Record(String description, Map features) { + this.description = description; + this.features = features; + } + + public Record(Map features) { + this("", features); + } + + public String getDescription() { + return description; + } + + public Map getFeatures() { + return features; + } + + @Override + public String toString() { + String prefix = description == null || description + .trim() + .isEmpty() ? "Record" : description; + + return prefix + ": " + features; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Record record = (Record) o; + return Objects.equals(getDescription(), record.getDescription()) && Objects.equals(getFeatures(), record.getFeatures()); + } + + @Override + public int hashCode() { + return Objects.hash(getDescription(), getFeatures()); + } +} diff --git a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/printtriangles/PrintTriangleExamples.java b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/printtriangles/PrintTriangleExamples.java index a67c54a922..156766f382 100644 --- a/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/printtriangles/PrintTriangleExamples.java +++ b/algorithms-miscellaneous-3/src/main/java/com/baeldung/algorithms/printtriangles/PrintTriangleExamples.java @@ -4,7 +4,7 @@ import org.apache.commons.lang3.StringUtils; public class PrintTriangleExamples { - public static String printARightAngledTriangle(int N) { + public static String printARightTriangle(int N) { StringBuilder result = new StringBuilder(); for (int r = 1; r <= N; r++) { for (int j = 1; j <= r; j++) { @@ -29,6 +29,17 @@ public class PrintTriangleExamples { return result.toString(); } + public static String printAnIsoscelesTriangleUsingStringUtils(int N) { + StringBuilder result = new StringBuilder(); + + for (int r = 1; r <= N; r++) { + result.append(StringUtils.repeat(' ', N - r)); + result.append(StringUtils.repeat('*', 2 * r - 1)); + result.append(System.lineSeparator()); + } + return result.toString(); + } + public static String printAnIsoscelesTriangleUsingSubstring(int N) { StringBuilder result = new StringBuilder(); String helperString = StringUtils.repeat(' ', N - 1) + StringUtils.repeat('*', N * 2 - 1); @@ -41,8 +52,9 @@ public class PrintTriangleExamples { } public static void main(String[] args) { - System.out.println(printARightAngledTriangle(5)); + System.out.println(printARightTriangle(5)); System.out.println(printAnIsoscelesTriangle(5)); + System.out.println(printAnIsoscelesTriangleUsingStringUtils(5)); System.out.println(printAnIsoscelesTriangleUsingSubstring(5)); } diff --git a/algorithms-miscellaneous-3/src/main/resources/kmeans/artists.json b/algorithms-miscellaneous-3/src/main/resources/kmeans/artists.json new file mode 100644 index 0000000000..6cee0d1de2 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/resources/kmeans/artists.json @@ -0,0 +1,3384 @@ +[ + { + "description": "Billie Eilish", + "features": { + "singer-songwriter": 3.0, + "american": 23.0, + "british": 3.0, + "experimental": 3.0, + "rnb": 3.0, + "female vocalists": 49.0, + "indie": 58.0, + "chillout": 12.0, + "ambient": 3.0, + "pop": 100.0, + "synthpop": 3.0, + "electronic": 58.0, + "indie pop": 83.0, + "seen live": 18.0, + "alternative": 40.0, + "female vocalist": 9.0 + } + }, + { + "description": "Ed Sheeran", + "features": { + "indie": 12.0, + "singer-songwriter": 78.0, + "male vocalists": 13.0, + "soul": 3.0, + "chillout": 2.0, + "Mellow": 2.0, + "british": 82.0, + "pop": 23.0, + "rock": 4.0, + "rap": 2.0, + "indie pop": 3.0, + "seen live": 21.0, + "Hip-Hop": 4.0, + "acoustic": 100.0, + "alternative": 8.0, + "guitar": 2.0, + "00s": 2.0, + "Soundtrack": 1.0, + "Love": 2.0, + "folk": 12.0 + } + }, + { + "description": "Lil Nas X", + "features": { + "country": 54.0, + "male vocalists": 8.0, + "american": 24.0, + "rock": 16.0, + "pop": 8.0, + "hip hop": 47.0, + "rap": 62.0, + "Hip-Hop": 100.0, + "alternative": 24.0 + } + }, + { + "description": "Queen", + "features": { + "favorites": 2.0, + "male vocalists": 3.0, + "british": 17.0, + "classic rock": 100.0, + "rock": 81.0, + "pop": 7.0, + "heavy metal": 2.0, + "oldies": 2.0, + "seen live": 2.0, + "alternative": 4.0, + "metal": 2.0, + "Progressive rock": 6.0, + "alternative rock": 1.0, + "hard rock": 38.0, + "70s": 8.0, + "80s": 41.0, + "90s": 2.0 + } + }, + { + "description": "Ariana Grande", + "features": { + "american": 13.0, + "beautiful": 2.0, + "dance": 11.0, + "House": 2.0, + "Soundtrack": 3.0, + "chillout": 3.0, + "pop": 100.0, + "rock": 2.0, + "electronic": 3.0, + "seen live": 3.0, + "female vocalist": 3.0, + "singer-songwriter": 5.0, + "rnb": 51.0, + "female vocalists": 54.0, + "soul": 10.0, + "synthpop": 2.0, + "hip hop": 3.0, + "Hip-Hop": 3.0 + } + }, + { + "description": "Post Malone", + "features": { + "american": 8.0, + "rap": 72.0, + "rnb": 14.0, + "pop": 8.0, + "synthpop": 3.0, + "hip hop": 35.0, + "seen live": 19.0, + "Hip-Hop": 100.0 + } + }, + { + "description": "Drake", + "features": { + "indie": 4.0, + "male vocalists": 5.0, + "soul": 2.0, + "pop": 6.0, + "hip hop": 37.0, + "rap": 72.0, + "seen live": 8.0, + "Hip-Hop": 100.0, + "rnb": 50.0, + "00s": 1.0 + } + }, + { + "description": "Kanye West", + "features": { + "indie": 2.0, + "male vocalists": 3.0, + "soul": 4.0, + "american": 6.0, + "experimental": 2.0, + "pop": 6.0, + "rock": 2.0, + "electronica": 1.0, + "hip hop": 40.0, + "electronic": 3.0, + "dance": 2.0, + "rap": 69.0, + "seen live": 22.0, + "Hip-Hop": 100.0, + "rnb": 31.0, + "alternative": 3.0, + "00s": 3.0 + } + }, + { + "description": "The Beatles", + "features": { + "indie": 3.0, + "favorites": 2.0, + "male vocalists": 2.0, + "singer-songwriter": 2.0, + "Psychedelic Rock": 6.0, + "british": 58.0, + "experimental": 2.0, + "classic rock": 100.0, + "rock": 71.0, + "pop": 41.0, + "psychedelic": 13.0, + "indie rock": 2.0, + "oldies": 10.0, + "britpop": 4.0, + "alternative": 4.0, + "Progressive rock": 2.0, + "alternative rock": 1.0, + "Love": 2.0, + "folk": 1.0, + "60s": 56.0, + "70s": 3.0 + } + }, + { + "description": "Taylor Swift", + "features": { + "country": 100.0, + "singer-songwriter": 42.0, + "chillout": 2.0, + "american": 8.0, + "pop": 71.0, + "rock": 2.0, + "beautiful": 2.0, + "synthpop": 2.0, + "seen live": 4.0, + "acoustic": 31.0, + "female vocalist": 3.0, + "00s": 3.0, + "female vocalists": 60.0, + "Love": 3.0, + "folk": 2.0 + } + }, + { + "description": "Radiohead", + "features": { + "indie": 59.0, + "favorites": 2.0, + "male vocalists": 2.0, + "emo": 1.0, + "chillout": 2.0, + "british": 22.0, + "experimental": 14.0, + "ambient": 2.0, + "classic rock": 1.0, + "rock": 73.0, + "electronica": 5.0, + "psychedelic": 3.0, + "pop": 2.0, + "beautiful": 1.0, + "post-rock": 3.0, + "indie rock": 15.0, + "electronic": 48.0, + "trip-hop": 1.0, + "britpop": 17.0, + "indie pop": 1.0, + "seen live": 27.0, + "alternative": 100.0, + "Progressive rock": 6.0, + "alternative rock": 81.0, + "00s": 2.0, + "idm": 1.0, + "90s": 5.0 + } + }, + { + "description": "Beyoncé", + "features": { + "singer-songwriter": 3.0, + "jazz": 2.0, + "american": 9.0, + "beautiful": 2.0, + "dance": 13.0, + "rap": 2.0, + "rnb": 100.0, + "female vocalists": 70.0, + "Love": 3.0, + "soul": 56.0, + "pop": 91.0, + "hip hop": 5.0, + "electronic": 2.0, + "seen live": 6.0, + "Hip-Hop": 45.0, + "alternative": 1.0, + "female vocalist": 4.0, + "00s": 3.0, + "funk": 2.0 + } + }, + { + "description": "Shawn Mendes", + "features": { + "male vocalists": 28.0, + "singer-songwriter": 13.0, + "british": 7.0, + "rnb": 7.0, + "acoustic": 37.0, + "metal": 4.0, + "folk": 37.0, + "indie": 10.0, + "soul": 4.0, + "pop": 100.0, + "seen live": 13.0, + "alternative": 4.0, + "alternative rock": 4.0 + } + }, + { + "description": "David Bowie", + "features": { + "singer-songwriter": 11.0, + "male vocalists": 4.0, + "Psychedelic Rock": 2.0, + "british": 23.0, + "experimental": 9.0, + "classic rock": 86.0, + "psychedelic": 3.0, + "electronica": 2.0, + "indie rock": 2.0, + "dance": 2.0, + "post-punk": 2.0, + "punk": 2.0, + "hard rock": 3.0, + "folk": 2.0, + "70s": 15.0, + "90s": 4.0, + "indie": 6.0, + "favorites": 2.0, + "soul": 2.0, + "ambient": 2.0, + "rock": 100.0, + "pop": 19.0, + "new wave": 7.0, + "electronic": 4.0, + "oldies": 2.0, + "britpop": 2.0, + "seen live": 11.0, + "alternative": 43.0, + "Progressive rock": 4.0, + "alternative rock": 6.0, + "industrial": 2.0, + "00s": 2.0, + "60s": 3.0, + "80s": 48.0, + "funk": 2.0 + } + }, + { + "description": "Kendrick Lamar", + "features": { + "male vocalists": 2.0, + "american": 7.0, + "hip hop": 17.0, + "rap": 70.0, + "seen live": 38.0, + "Hip-Hop": 100.0, + "funk": 2.0 + } + }, + { + "description": "Rihanna", + "features": { + "american": 4.0, + "beautiful": 2.0, + "dance": 56.0, + "rap": 2.0, + "rnb": 89.0, + "House": 1.0, + "female vocalists": 63.0, + "Love": 2.0, + "soul": 4.0, + "pop": 100.0, + "rock": 2.0, + "hip hop": 6.0, + "electronic": 3.0, + "seen live": 7.0, + "Hip-Hop": 41.0, + "alternative": 1.0, + "female vocalist": 4.0, + "00s": 3.0, + "reggae": 6.0 + } + }, + { + "description": "Arctic Monkeys", + "features": { + "indie": 98.0, + "male vocalists": 2.0, + "Psychedelic Rock": 1.0, + "british": 75.0, + "rock": 63.0, + "pop": 2.0, + "punk rock": 1.0, + "indie rock": 100.0, + "britpop": 16.0, + "indie pop": 2.0, + "seen live": 45.0, + "alternative": 60.0, + "post-punk": 3.0, + "alternative rock": 19.0, + "00s": 3.0, + "punk": 2.0 + } + }, + { + "description": "Tyler, the Creator", + "features": { + "experimental": 4.0, + "american": 4.0, + "hip hop": 12.0, + "rap": 55.0, + "seen live": 15.0, + "Hip-Hop": 100.0, + "alternative": 2.0 + } + }, + { + "description": "Lana Del Rey", + "features": { + "singer-songwriter": 10.0, + "jazz": 2.0, + "american": 14.0, + "beautiful": 2.0, + "indie rock": 2.0, + "female vocalists": 100.0, + "folk": 2.0, + "indie": 93.0, + "soul": 3.0, + "chillout": 3.0, + "blues": 2.0, + "pop": 80.0, + "rock": 2.0, + "electronic": 2.0, + "trip-hop": 10.0, + "indie pop": 88.0, + "seen live": 12.0, + "alternative": 67.0, + "female vocalist": 4.0, + "alternative rock": 2.0 + } + }, + { + "description": "Katy Perry", + "features": { + "indie": 25.0, + "singer-songwriter": 4.0, + "american": 9.0, + "pop": 100.0, + "rock": 24.0, + "beautiful": 2.0, + "indie rock": 1.0, + "electronic": 4.0, + "dance": 9.0, + "indie pop": 1.0, + "seen live": 7.0, + "rnb": 1.0, + "alternative": 3.0, + "female vocalist": 5.0, + "00s": 3.0, + "female vocalists": 62.0, + "Love": 2.0 + } + }, + { + "description": "Lady Gaga", + "features": { + "singer-songwriter": 4.0, + "american": 7.0, + "pop": 100.0, + "electronica": 3.0, + "rock": 2.0, + "electro": 2.0, + "synthpop": 2.0, + "electronic": 53.0, + "dance": 73.0, + "seen live": 8.0, + "techno": 1.0, + "rnb": 1.0, + "alternative": 1.0, + "female vocalist": 21.0, + "00s": 3.0, + "female vocalists": 43.0, + "Love": 2.0 + } + }, + { + "description": "Tame Impala", + "features": { + "indie": 21.0, + "male vocalists": 1.0, + "Psychedelic Rock": 100.0, + "experimental": 4.0, + "psychedelic": 92.0, + "rock": 41.0, + "indie rock": 60.0, + "electronic": 3.0, + "indie pop": 2.0, + "seen live": 53.0, + "alternative": 7.0, + "Progressive rock": 3.0, + "alternative rock": 3.0, + "00s": 3.0 + } + }, + { + "description": "Calvin Harris", + "features": { + "indie": 8.0, + "male vocalists": 3.0, + "singer-songwriter": 1.0, + "british": 15.0, + "electronica": 34.0, + "pop": 8.0, + "electro": 53.0, + "synthpop": 4.0, + "electronic": 100.0, + "dance": 75.0, + "indie pop": 2.0, + "seen live": 36.0, + "techno": 1.0, + "alternative": 1.0, + "House": 9.0, + "00s": 3.0, + "80s": 1.0 + } + }, + { + "description": "Red Hot Chili Peppers", + "features": { + "indie": 5.0, + "favorites": 1.0, + "male vocalists": 1.0, + "american": 5.0, + "classic rock": 3.0, + "rock": 100.0, + "pop": 2.0, + "punk rock": 2.0, + "indie rock": 2.0, + "seen live": 23.0, + "Grunge": 2.0, + "alternative": 54.0, + "metal": 2.0, + "alternative rock": 59.0, + "00s": 2.0, + "punk": 6.0, + "hard rock": 2.0, + "80s": 2.0, + "funk": 50.0, + "90s": 5.0 + } + }, + { + "description": "Coldplay", + "features": { + "indie": 55.0, + "favorites": 2.0, + "male vocalists": 3.0, + "singer-songwriter": 2.0, + "emo": 2.0, + "Mellow": 3.0, + "chillout": 3.0, + "british": 28.0, + "classic rock": 2.0, + "rock": 100.0, + "pop": 18.0, + "piano": 3.0, + "indie rock": 11.0, + "electronic": 2.0, + "britpop": 81.0, + "indie pop": 2.0, + "seen live": 22.0, + "alternative": 87.0, + "acoustic": 2.0, + "alternative rock": 68.0, + "00s": 2.0, + "Love": 2.0, + "90s": 2.0 + } + }, + { + "description": "Miley Cyrus", + "features": { + "country": 3.0, + "singer-songwriter": 1.0, + "american": 12.0, + "beautiful": 2.0, + "grindcore": 1.0, + "dance": 42.0, + "rnb": 4.0, + "Soundtrack": 2.0, + "female vocalists": 55.0, + "Love": 2.0, + "death metal": 2.0, + "pop": 100.0, + "rock": 8.0, + "electronic": 5.0, + "seen live": 3.0, + "Hip-Hop": 4.0, + "alternative": 2.0, + "female vocalist": 4.0, + "00s": 2.0 + } + }, + { + "description": "Mark Ronson", + "features": { + "singer-songwriter": 1.0, + "jazz": 7.0, + "british": 68.0, + "experimental": 2.0, + "american": 1.0, + "cover": 4.0, + "electronica": 2.0, + "dance": 5.0, + "rap": 4.0, + "rnb": 2.0, + "House": 1.0, + "indie": 3.0, + "soul": 17.0, + "chillout": 2.0, + "pop": 68.0, + "rock": 3.0, + "electro": 2.0, + "hip hop": 11.0, + "electronic": 9.0, + "trip-hop": 1.0, + "britpop": 4.0, + "seen live": 31.0, + "Hip-Hop": 57.0, + "alternative": 9.0, + "00s": 7.0, + "funk": 100.0 + } + }, + { + "description": "Imagine Dragons", + "features": { + "indie": 100.0, + "male vocalists": 6.0, + "american": 12.0, + "rock": 64.0, + "pop": 10.0, + "indie rock": 96.0, + "electronic": 4.0, + "new wave": 2.0, + "indie pop": 57.0, + "seen live": 29.0, + "alternative": 86.0, + "alternative rock": 21.0, + "folk": 2.0 + } + }, + { + "description": "The Weeknd", + "features": { + "indie": 6.0, + "male vocalists": 5.0, + "soul": 9.0, + "chillout": 2.0, + "Mellow": 2.0, + "experimental": 6.0, + "ambient": 3.0, + "pop": 10.0, + "electronica": 5.0, + "electro": 1.0, + "downtempo": 7.0, + "hip hop": 2.0, + "electronic": 78.0, + "trip-hop": 3.0, + "rap": 2.0, + "indie pop": 2.0, + "seen live": 16.0, + "Hip-Hop": 8.0, + "rnb": 100.0, + "alternative": 5.0 + } + }, + { + "description": "Eminem", + "features": { + "male vocalists": 3.0, + "singer-songwriter": 2.0, + "emo": 1.0, + "american": 6.0, + "pop": 16.0, + "rock": 3.0, + "hip hop": 33.0, + "dance": 1.0, + "rap": 100.0, + "seen live": 4.0, + "Hip-Hop": 79.0, + "alternative": 3.0, + "00s": 2.0, + "90s": 2.0 + } + }, + { + "description": "Nirvana", + "features": { + "indie": 4.0, + "favorites": 1.0, + "male vocalists": 2.0, + "Grunge": 100.0, + "alternative": 35.0, + "metal": 3.0, + "american": 4.0, + "classic rock": 2.0, + "rock": 52.0, + "alternative rock": 34.0, + "punk rock": 3.0, + "punk": 7.0, + "indie rock": 2.0, + "hard rock": 3.0, + "90s": 28.0 + } + }, + { + "description": "Fleetwood Mac", + "features": { + "favorites": 2.0, + "male vocalists": 2.0, + "singer-songwriter": 2.0, + "british": 10.0, + "american": 3.0, + "classic rock": 100.0, + "blues": 41.0, + "rock": 67.0, + "pop": 33.0, + "oldies": 3.0, + "seen live": 7.0, + "alternative": 1.0, + "acoustic": 1.0, + "female vocalist": 2.0, + "guitar": 1.0, + "Progressive rock": 2.0, + "female vocalists": 10.0, + "folk": 2.0, + "60s": 5.0, + "70s": 48.0, + "80s": 12.0, + "90s": 2.0 + } + }, + { + "description": "Childish Gambino", + "features": { + "indie": 35.0, + "male vocalists": 1.0, + "soul": 5.0, + "american": 8.0, + "experimental": 3.0, + "pop": 3.0, + "psychedelic": 2.0, + "hip hop": 31.0, + "electronic": 2.0, + "dance": 1.0, + "rap": 70.0, + "seen live": 37.0, + "Hip-Hop": 100.0, + "rnb": 6.0, + "alternative": 4.0, + "funk": 8.0 + } + }, + { + "description": "Pink Floyd", + "features": { + "favorites": 1.0, + "indie": 1.0, + "Psychedelic Rock": 72.0, + "british": 13.0, + "experimental": 6.0, + "ambient": 1.0, + "classic rock": 79.0, + "rock": 53.0, + "psychedelic": 44.0, + "oldies": 1.0, + "seen live": 3.0, + "alternative": 6.0, + "Progressive rock": 100.0, + "alternative rock": 2.0, + "hard rock": 2.0, + "60s": 5.0, + "70s": 8.0, + "80s": 3.0 + } + }, + { + "description": "The Killers", + "features": { + "indie": 100.0, + "favorites": 2.0, + "male vocalists": 3.0, + "emo": 2.0, + "american": 9.0, + "british": 2.0, + "classic rock": 1.0, + "rock": 93.0, + "pop": 10.0, + "electronica": 1.0, + "punk rock": 1.0, + "indie rock": 90.0, + "new wave": 4.0, + "electronic": 3.0, + "dance": 1.0, + "britpop": 4.0, + "indie pop": 4.0, + "seen live": 39.0, + "alternative": 75.0, + "post-punk": 3.0, + "alternative rock": 64.0, + "00s": 3.0, + "punk": 4.0 + } + }, + { + "description": "The Rolling Stones", + "features": { + "indie": 2.0, + "male vocalists": 1.0, + "Psychedelic Rock": 2.0, + "british": 43.0, + "classic rock": 100.0, + "blues": 31.0, + "rock": 80.0, + "psychedelic": 3.0, + "pop": 2.0, + "oldies": 3.0, + "seen live": 14.0, + "alternative": 4.0, + "guitar": 1.0, + "hard rock": 8.0, + "60s": 41.0, + "70s": 8.0, + "80s": 4.0, + "90s": 2.0 + } + }, + { + "description": "Gorillaz", + "features": { + "indie": 46.0, + "favorites": 1.0, + "chillout": 3.0, + "british": 12.0, + "experimental": 6.0, + "rock": 58.0, + "electronica": 13.0, + "pop": 13.0, + "electro": 2.0, + "downtempo": 1.0, + "punk rock": 1.0, + "indie rock": 4.0, + "hip hop": 7.0, + "electronic": 88.0, + "trip-hop": 20.0, + "dance": 4.0, + "britpop": 4.0, + "rap": 4.0, + "indie pop": 2.0, + "seen live": 5.0, + "Hip-Hop": 63.0, + "alternative": 100.0, + "metal": 2.0, + "alternative rock": 11.0, + "00s": 3.0, + "punk": 2.0, + "funk": 3.0 + } + }, + { + "description": "Frank Ocean", + "features": { + "indie": 3.0, + "male vocalists": 6.0, + "singer-songwriter": 4.0, + "soul": 93.0, + "american": 8.0, + "experimental": 2.0, + "pop": 6.0, + "electronica": 1.0, + "hip hop": 8.0, + "electronic": 3.0, + "rap": 4.0, + "seen live": 14.0, + "Hip-Hop": 82.0, + "rnb": 100.0, + "alternative": 3.0, + "funk": 2.0 + } + }, + { + "description": "Panic! at the Disco", + "features": { + "male vocalists": 3.0, + "american": 8.0, + "electronica": 2.0, + "punk rock": 6.0, + "indie rock": 21.0, + "dance": 20.0, + "metal": 2.0, + "screamo": 2.0, + "punk": 21.0, + "Love": 2.0, + "indie": 68.0, + "favorites": 4.0, + "emo": 97.0, + "rock": 100.0, + "pop": 9.0, + "electronic": 4.0, + "indie pop": 2.0, + "seen live": 51.0, + "hardcore": 2.0, + "techno": 1.0, + "alternative": 99.0, + "alternative rock": 21.0, + "00s": 2.0 + } + }, + { + "description": "The Cure", + "features": { + "indie": 14.0, + "favorites": 2.0, + "male vocalists": 2.0, + "emo": 1.0, + "british": 16.0, + "classic rock": 3.0, + "rock": 52.0, + "pop": 6.0, + "psychedelic": 1.0, + "synthpop": 1.0, + "punk rock": 1.0, + "indie rock": 3.0, + "new wave": 100.0, + "electronic": 2.0, + "britpop": 2.0, + "indie pop": 1.0, + "seen live": 24.0, + "alternative": 68.0, + "Gothic": 10.0, + "post-punk": 100.0, + "alternative rock": 23.0, + "punk": 4.0, + "Love": 2.0, + "70s": 2.0, + "80s": 65.0, + "90s": 3.0 + } + }, + { + "description": "Madonna", + "features": { + "singer-songwriter": 3.0, + "american": 8.0, + "pop": 100.0, + "rock": 5.0, + "electronica": 3.0, + "electronic": 29.0, + "dance": 50.0, + "seen live": 9.0, + "rnb": 1.0, + "alternative": 2.0, + "female vocalist": 4.0, + "00s": 4.0, + "female vocalists": 50.0, + "Love": 1.0, + "80s": 35.0, + "90s": 8.0 + } + }, + { + "description": "The Chainsmokers", + "features": { + "male vocalists": 6.0, + "american": 28.0, + "electronica": 3.0, + "dance": 33.0, + "House": 63.0, + "pop": 79.0, + "electro": 6.0, + "electronic": 100.0, + "seen live": 17.0, + "techno": 3.0, + "alternative": 3.0 + } + }, + { + "description": "Linkin Park", + "features": { + "favorites": 2.0, + "indie": 1.0, + "male vocalists": 3.0, + "emo": 3.0, + "american": 6.0, + "rock": 100.0, + "pop": 3.0, + "punk rock": 2.0, + "electronic": 4.0, + "rap": 3.0, + "seen live": 21.0, + "Hip-Hop": 2.0, + "alternative": 67.0, + "metal": 37.0, + "Nu Metal": 92.0, + "alternative rock": 74.0, + "00s": 2.0, + "punk": 4.0, + "hard rock": 5.0 + } + }, + { + "description": "Lorde", + "features": { + "indie": 72.0, + "singer-songwriter": 7.0, + "soul": 1.0, + "experimental": 2.0, + "pop": 100.0, + "electronica": 5.0, + "rock": 1.0, + "synthpop": 7.0, + "electronic": 81.0, + "trip-hop": 2.0, + "indie pop": 92.0, + "seen live": 20.0, + "alternative": 17.0, + "female vocalist": 4.0, + "female vocalists": 28.0, + "folk": 2.0 + } + }, + { + "description": "The Black Keys", + "features": { + "indie": 50.0, + "male vocalists": 2.0, + "soul": 2.0, + "Psychedelic Rock": 2.0, + "american": 8.0, + "blues": 68.0, + "classic rock": 2.0, + "rock": 63.0, + "psychedelic": 2.0, + "indie rock": 48.0, + "seen live": 37.0, + "alternative": 11.0, + "alternative rock": 7.0, + "00s": 3.0, + "hard rock": 2.0 + } + }, + { + "description": "Daft Punk", + "features": { + "indie": 2.0, + "chillout": 2.0, + "experimental": 2.0, + "electronica": 37.0, + "rock": 3.0, + "pop": 2.0, + "electro": 11.0, + "synthpop": 1.0, + "electronic": 100.0, + "dance": 54.0, + "french": 19.0, + "seen live": 7.0, + "techno": 36.0, + "alternative": 6.0, + "House": 54.0, + "trance": 2.0, + "00s": 2.0, + "Soundtrack": 2.0, + "funk": 4.0, + "90s": 3.0 + } + }, + { + "description": "Led Zeppelin", + "features": { + "favorites": 1.0, + "indie": 1.0, + "Psychedelic Rock": 3.0, + "british": 9.0, + "classic rock": 100.0, + "blues": 9.0, + "rock": 64.0, + "psychedelic": 4.0, + "heavy metal": 8.0, + "oldies": 1.0, + "metal": 4.0, + "alternative": 4.0, + "guitar": 2.0, + "Progressive rock": 33.0, + "alternative rock": 1.0, + "hard rock": 63.0, + "folk": 1.0, + "60s": 3.0, + "70s": 36.0, + "80s": 1.0 + } + }, + { + "description": "Marshmello", + "features": { + "emo": 10.0, + "pop": 28.0, + "electronic": 91.0, + "dance": 100.0, + "rap": 28.0, + "seen live": 19.0, + "rnb": 19.0, + "House": 10.0 + } + }, + { + "description": "Khalid", + "features": { + "indie": 7.0, + "male vocalists": 7.0, + "soul": 88.0, + "american": 19.0, + "pop": 100.0, + "synthpop": 7.0, + "electronic": 13.0, + "seen live": 25.0, + "rnb": 75.0, + "alternative": 63.0, + "folk": 7.0 + } + }, + { + "description": "David Guetta", + "features": { + "chillout": 1.0, + "electronica": 7.0, + "pop": 6.0, + "electro": 6.0, + "electronic": 76.0, + "dance": 82.0, + "french": 11.0, + "seen live": 9.0, + "techno": 39.0, + "House": 100.0, + "trance": 4.0, + "00s": 2.0 + } + }, + { + "description": "Billie Eilish", + "features": { + "singer-songwriter": 3.0, + "american": 23.0, + "british": 3.0, + "experimental": 3.0, + "rnb": 3.0, + "female vocalists": 49.0, + "indie": 58.0, + "chillout": 12.0, + "ambient": 3.0, + "pop": 100.0, + "synthpop": 3.0, + "electronic": 58.0, + "indie pop": 83.0, + "seen live": 18.0, + "alternative": 40.0, + "female vocalist": 9.0 + } + }, + { + "description": "Ed Sheeran", + "features": { + "indie": 12.0, + "singer-songwriter": 78.0, + "male vocalists": 13.0, + "soul": 3.0, + "chillout": 2.0, + "Mellow": 2.0, + "british": 82.0, + "pop": 23.0, + "rock": 4.0, + "rap": 2.0, + "indie pop": 3.0, + "seen live": 21.0, + "Hip-Hop": 4.0, + "acoustic": 100.0, + "alternative": 8.0, + "guitar": 2.0, + "00s": 2.0, + "Soundtrack": 1.0, + "Love": 2.0, + "folk": 12.0 + } + }, + { + "description": "Lil Nas X", + "features": { + "country": 54.0, + "male vocalists": 8.0, + "american": 24.0, + "rock": 16.0, + "pop": 8.0, + "hip hop": 47.0, + "rap": 62.0, + "Hip-Hop": 100.0, + "alternative": 24.0 + } + }, + { + "description": "Queen", + "features": { + "favorites": 2.0, + "male vocalists": 3.0, + "british": 17.0, + "classic rock": 100.0, + "rock": 81.0, + "pop": 7.0, + "heavy metal": 2.0, + "oldies": 2.0, + "seen live": 2.0, + "alternative": 4.0, + "metal": 2.0, + "Progressive rock": 6.0, + "alternative rock": 1.0, + "hard rock": 38.0, + "70s": 8.0, + "80s": 41.0, + "90s": 2.0 + } + }, + { + "description": "Ariana Grande", + "features": { + "american": 13.0, + "beautiful": 2.0, + "dance": 11.0, + "House": 2.0, + "Soundtrack": 3.0, + "chillout": 3.0, + "pop": 100.0, + "rock": 2.0, + "electronic": 3.0, + "seen live": 3.0, + "female vocalist": 3.0, + "singer-songwriter": 5.0, + "rnb": 51.0, + "female vocalists": 54.0, + "soul": 10.0, + "synthpop": 2.0, + "hip hop": 3.0, + "Hip-Hop": 3.0 + } + }, + { + "description": "Post Malone", + "features": { + "american": 8.0, + "rap": 72.0, + "rnb": 14.0, + "pop": 8.0, + "synthpop": 3.0, + "hip hop": 35.0, + "seen live": 19.0, + "Hip-Hop": 100.0 + } + }, + { + "description": "Drake", + "features": { + "indie": 4.0, + "male vocalists": 5.0, + "soul": 2.0, + "pop": 6.0, + "hip hop": 37.0, + "rap": 72.0, + "seen live": 8.0, + "Hip-Hop": 100.0, + "rnb": 50.0, + "00s": 1.0 + } + }, + { + "description": "Kanye West", + "features": { + "indie": 2.0, + "male vocalists": 3.0, + "soul": 4.0, + "american": 6.0, + "experimental": 2.0, + "pop": 6.0, + "rock": 2.0, + "electronica": 1.0, + "hip hop": 40.0, + "electronic": 3.0, + "dance": 2.0, + "rap": 69.0, + "seen live": 22.0, + "Hip-Hop": 100.0, + "rnb": 31.0, + "alternative": 3.0, + "00s": 3.0 + } + }, + { + "description": "The Beatles", + "features": { + "indie": 3.0, + "favorites": 2.0, + "male vocalists": 2.0, + "singer-songwriter": 2.0, + "Psychedelic Rock": 6.0, + "british": 58.0, + "experimental": 2.0, + "classic rock": 100.0, + "rock": 71.0, + "pop": 41.0, + "psychedelic": 13.0, + "indie rock": 2.0, + "oldies": 10.0, + "britpop": 4.0, + "alternative": 4.0, + "Progressive rock": 2.0, + "alternative rock": 1.0, + "Love": 2.0, + "folk": 1.0, + "60s": 56.0, + "70s": 3.0 + } + }, + { + "description": "Taylor Swift", + "features": { + "country": 100.0, + "singer-songwriter": 42.0, + "chillout": 2.0, + "american": 8.0, + "pop": 71.0, + "rock": 2.0, + "beautiful": 2.0, + "synthpop": 2.0, + "seen live": 4.0, + "acoustic": 31.0, + "female vocalist": 3.0, + "00s": 3.0, + "female vocalists": 60.0, + "Love": 3.0, + "folk": 2.0 + } + }, + { + "description": "Radiohead", + "features": { + "indie": 59.0, + "favorites": 2.0, + "male vocalists": 2.0, + "emo": 1.0, + "chillout": 2.0, + "british": 22.0, + "experimental": 14.0, + "ambient": 2.0, + "classic rock": 1.0, + "rock": 73.0, + "electronica": 5.0, + "psychedelic": 3.0, + "pop": 2.0, + "beautiful": 1.0, + "post-rock": 3.0, + "indie rock": 15.0, + "electronic": 48.0, + "trip-hop": 1.0, + "britpop": 17.0, + "indie pop": 1.0, + "seen live": 27.0, + "alternative": 100.0, + "Progressive rock": 6.0, + "alternative rock": 81.0, + "00s": 2.0, + "idm": 1.0, + "90s": 5.0 + } + }, + { + "description": "Beyoncé", + "features": { + "singer-songwriter": 3.0, + "jazz": 2.0, + "american": 9.0, + "beautiful": 2.0, + "dance": 13.0, + "rap": 2.0, + "rnb": 100.0, + "female vocalists": 70.0, + "Love": 3.0, + "soul": 56.0, + "pop": 91.0, + "hip hop": 5.0, + "electronic": 2.0, + "seen live": 6.0, + "Hip-Hop": 45.0, + "alternative": 1.0, + "female vocalist": 4.0, + "00s": 3.0, + "funk": 2.0 + } + }, + { + "description": "Shawn Mendes", + "features": { + "male vocalists": 28.0, + "singer-songwriter": 13.0, + "british": 7.0, + "rnb": 7.0, + "acoustic": 37.0, + "metal": 4.0, + "folk": 37.0, + "indie": 10.0, + "soul": 4.0, + "pop": 100.0, + "seen live": 13.0, + "alternative": 4.0, + "alternative rock": 4.0 + } + }, + { + "description": "David Bowie", + "features": { + "singer-songwriter": 11.0, + "male vocalists": 4.0, + "Psychedelic Rock": 2.0, + "british": 23.0, + "experimental": 9.0, + "classic rock": 86.0, + "psychedelic": 3.0, + "electronica": 2.0, + "indie rock": 2.0, + "dance": 2.0, + "post-punk": 2.0, + "punk": 2.0, + "hard rock": 3.0, + "folk": 2.0, + "70s": 15.0, + "90s": 4.0, + "indie": 6.0, + "favorites": 2.0, + "soul": 2.0, + "ambient": 2.0, + "rock": 100.0, + "pop": 19.0, + "new wave": 7.0, + "electronic": 4.0, + "oldies": 2.0, + "britpop": 2.0, + "seen live": 11.0, + "alternative": 43.0, + "Progressive rock": 4.0, + "alternative rock": 6.0, + "industrial": 2.0, + "00s": 2.0, + "60s": 3.0, + "80s": 48.0, + "funk": 2.0 + } + }, + { + "description": "Kendrick Lamar", + "features": { + "male vocalists": 2.0, + "american": 7.0, + "hip hop": 17.0, + "rap": 70.0, + "seen live": 38.0, + "Hip-Hop": 100.0, + "funk": 2.0 + } + }, + { + "description": "Rihanna", + "features": { + "american": 4.0, + "beautiful": 2.0, + "dance": 56.0, + "rap": 2.0, + "rnb": 89.0, + "House": 1.0, + "female vocalists": 63.0, + "Love": 2.0, + "soul": 4.0, + "pop": 100.0, + "rock": 2.0, + "hip hop": 6.0, + "electronic": 3.0, + "seen live": 7.0, + "Hip-Hop": 41.0, + "alternative": 1.0, + "female vocalist": 4.0, + "00s": 3.0, + "reggae": 6.0 + } + }, + { + "description": "Arctic Monkeys", + "features": { + "indie": 98.0, + "male vocalists": 2.0, + "Psychedelic Rock": 1.0, + "british": 75.0, + "rock": 63.0, + "pop": 2.0, + "punk rock": 1.0, + "indie rock": 100.0, + "britpop": 16.0, + "indie pop": 2.0, + "seen live": 45.0, + "alternative": 60.0, + "post-punk": 3.0, + "alternative rock": 19.0, + "00s": 3.0, + "punk": 2.0 + } + }, + { + "description": "Tyler, the Creator", + "features": { + "experimental": 4.0, + "american": 4.0, + "hip hop": 12.0, + "rap": 55.0, + "seen live": 15.0, + "Hip-Hop": 100.0, + "alternative": 2.0 + } + }, + { + "description": "Lana Del Rey", + "features": { + "singer-songwriter": 10.0, + "jazz": 2.0, + "american": 14.0, + "beautiful": 2.0, + "indie rock": 2.0, + "female vocalists": 100.0, + "folk": 2.0, + "indie": 93.0, + "soul": 3.0, + "chillout": 3.0, + "blues": 2.0, + "pop": 80.0, + "rock": 2.0, + "electronic": 2.0, + "trip-hop": 10.0, + "indie pop": 88.0, + "seen live": 12.0, + "alternative": 67.0, + "female vocalist": 4.0, + "alternative rock": 2.0 + } + }, + { + "description": "Katy Perry", + "features": { + "indie": 25.0, + "singer-songwriter": 4.0, + "american": 9.0, + "pop": 100.0, + "rock": 24.0, + "beautiful": 2.0, + "indie rock": 1.0, + "electronic": 4.0, + "dance": 9.0, + "indie pop": 1.0, + "seen live": 7.0, + "rnb": 1.0, + "alternative": 3.0, + "female vocalist": 5.0, + "00s": 3.0, + "female vocalists": 62.0, + "Love": 2.0 + } + }, + { + "description": "Lady Gaga", + "features": { + "singer-songwriter": 4.0, + "american": 7.0, + "pop": 100.0, + "electronica": 3.0, + "rock": 2.0, + "electro": 2.0, + "synthpop": 2.0, + "electronic": 53.0, + "dance": 73.0, + "seen live": 8.0, + "techno": 1.0, + "rnb": 1.0, + "alternative": 1.0, + "female vocalist": 21.0, + "00s": 3.0, + "female vocalists": 43.0, + "Love": 2.0 + } + }, + { + "description": "Tame Impala", + "features": { + "indie": 21.0, + "male vocalists": 1.0, + "Psychedelic Rock": 100.0, + "experimental": 4.0, + "psychedelic": 92.0, + "rock": 41.0, + "indie rock": 60.0, + "electronic": 3.0, + "indie pop": 2.0, + "seen live": 53.0, + "alternative": 7.0, + "Progressive rock": 3.0, + "alternative rock": 3.0, + "00s": 3.0 + } + }, + { + "description": "Calvin Harris", + "features": { + "indie": 8.0, + "male vocalists": 3.0, + "singer-songwriter": 1.0, + "british": 15.0, + "electronica": 34.0, + "pop": 8.0, + "electro": 53.0, + "synthpop": 4.0, + "electronic": 100.0, + "dance": 75.0, + "indie pop": 2.0, + "seen live": 36.0, + "techno": 1.0, + "alternative": 1.0, + "House": 9.0, + "00s": 3.0, + "80s": 1.0 + } + }, + { + "description": "Red Hot Chili Peppers", + "features": { + "indie": 5.0, + "favorites": 1.0, + "male vocalists": 1.0, + "american": 5.0, + "classic rock": 3.0, + "rock": 100.0, + "pop": 2.0, + "punk rock": 2.0, + "indie rock": 2.0, + "seen live": 23.0, + "Grunge": 2.0, + "alternative": 54.0, + "metal": 2.0, + "alternative rock": 59.0, + "00s": 2.0, + "punk": 6.0, + "hard rock": 2.0, + "80s": 2.0, + "funk": 50.0, + "90s": 5.0 + } + }, + { + "description": "Coldplay", + "features": { + "indie": 55.0, + "favorites": 2.0, + "male vocalists": 3.0, + "singer-songwriter": 2.0, + "emo": 2.0, + "Mellow": 3.0, + "chillout": 3.0, + "british": 28.0, + "classic rock": 2.0, + "rock": 100.0, + "pop": 18.0, + "piano": 3.0, + "indie rock": 11.0, + "electronic": 2.0, + "britpop": 81.0, + "indie pop": 2.0, + "seen live": 22.0, + "alternative": 87.0, + "acoustic": 2.0, + "alternative rock": 68.0, + "00s": 2.0, + "Love": 2.0, + "90s": 2.0 + } + }, + { + "description": "Miley Cyrus", + "features": { + "country": 3.0, + "singer-songwriter": 1.0, + "american": 12.0, + "beautiful": 2.0, + "grindcore": 1.0, + "dance": 42.0, + "rnb": 4.0, + "Soundtrack": 2.0, + "female vocalists": 55.0, + "Love": 2.0, + "death metal": 2.0, + "pop": 100.0, + "rock": 8.0, + "electronic": 5.0, + "seen live": 3.0, + "Hip-Hop": 4.0, + "alternative": 2.0, + "female vocalist": 4.0, + "00s": 2.0 + } + }, + { + "description": "Mark Ronson", + "features": { + "singer-songwriter": 1.0, + "jazz": 7.0, + "british": 68.0, + "experimental": 2.0, + "american": 1.0, + "cover": 4.0, + "electronica": 2.0, + "dance": 5.0, + "rap": 4.0, + "rnb": 2.0, + "House": 1.0, + "indie": 3.0, + "soul": 17.0, + "chillout": 2.0, + "pop": 68.0, + "rock": 3.0, + "electro": 2.0, + "hip hop": 11.0, + "electronic": 9.0, + "trip-hop": 1.0, + "britpop": 4.0, + "seen live": 31.0, + "Hip-Hop": 57.0, + "alternative": 9.0, + "00s": 7.0, + "funk": 100.0 + } + }, + { + "description": "Imagine Dragons", + "features": { + "indie": 100.0, + "male vocalists": 6.0, + "american": 12.0, + "rock": 64.0, + "pop": 10.0, + "indie rock": 96.0, + "electronic": 4.0, + "new wave": 2.0, + "indie pop": 57.0, + "seen live": 29.0, + "alternative": 86.0, + "alternative rock": 21.0, + "folk": 2.0 + } + }, + { + "description": "The Weeknd", + "features": { + "indie": 6.0, + "male vocalists": 5.0, + "soul": 9.0, + "chillout": 2.0, + "Mellow": 2.0, + "experimental": 6.0, + "ambient": 3.0, + "pop": 10.0, + "electronica": 5.0, + "electro": 1.0, + "downtempo": 7.0, + "hip hop": 2.0, + "electronic": 78.0, + "trip-hop": 3.0, + "rap": 2.0, + "indie pop": 2.0, + "seen live": 16.0, + "Hip-Hop": 8.0, + "rnb": 100.0, + "alternative": 5.0 + } + }, + { + "description": "Eminem", + "features": { + "male vocalists": 3.0, + "singer-songwriter": 2.0, + "emo": 1.0, + "american": 6.0, + "pop": 16.0, + "rock": 3.0, + "hip hop": 33.0, + "dance": 1.0, + "rap": 100.0, + "seen live": 4.0, + "Hip-Hop": 79.0, + "alternative": 3.0, + "00s": 2.0, + "90s": 2.0 + } + }, + { + "description": "Nirvana", + "features": { + "indie": 4.0, + "favorites": 1.0, + "male vocalists": 2.0, + "Grunge": 100.0, + "alternative": 35.0, + "metal": 3.0, + "american": 4.0, + "classic rock": 2.0, + "rock": 52.0, + "alternative rock": 34.0, + "punk rock": 3.0, + "punk": 7.0, + "indie rock": 2.0, + "hard rock": 3.0, + "90s": 28.0 + } + }, + { + "description": "Fleetwood Mac", + "features": { + "favorites": 2.0, + "male vocalists": 2.0, + "singer-songwriter": 2.0, + "british": 10.0, + "american": 3.0, + "classic rock": 100.0, + "blues": 41.0, + "rock": 67.0, + "pop": 33.0, + "oldies": 3.0, + "seen live": 7.0, + "alternative": 1.0, + "acoustic": 1.0, + "female vocalist": 2.0, + "guitar": 1.0, + "Progressive rock": 2.0, + "female vocalists": 10.0, + "folk": 2.0, + "60s": 5.0, + "70s": 48.0, + "80s": 12.0, + "90s": 2.0 + } + }, + { + "description": "Childish Gambino", + "features": { + "indie": 35.0, + "male vocalists": 1.0, + "soul": 5.0, + "american": 8.0, + "experimental": 3.0, + "pop": 3.0, + "psychedelic": 2.0, + "hip hop": 31.0, + "electronic": 2.0, + "dance": 1.0, + "rap": 70.0, + "seen live": 37.0, + "Hip-Hop": 100.0, + "rnb": 6.0, + "alternative": 4.0, + "funk": 8.0 + } + }, + { + "description": "Pink Floyd", + "features": { + "favorites": 1.0, + "indie": 1.0, + "Psychedelic Rock": 72.0, + "british": 13.0, + "experimental": 6.0, + "ambient": 1.0, + "classic rock": 79.0, + "rock": 53.0, + "psychedelic": 44.0, + "oldies": 1.0, + "seen live": 3.0, + "alternative": 6.0, + "Progressive rock": 100.0, + "alternative rock": 2.0, + "hard rock": 2.0, + "60s": 5.0, + "70s": 8.0, + "80s": 3.0 + } + }, + { + "description": "The Killers", + "features": { + "indie": 100.0, + "favorites": 2.0, + "male vocalists": 3.0, + "emo": 2.0, + "american": 9.0, + "british": 2.0, + "classic rock": 1.0, + "rock": 93.0, + "pop": 10.0, + "electronica": 1.0, + "punk rock": 1.0, + "indie rock": 90.0, + "new wave": 4.0, + "electronic": 3.0, + "dance": 1.0, + "britpop": 4.0, + "indie pop": 4.0, + "seen live": 39.0, + "alternative": 75.0, + "post-punk": 3.0, + "alternative rock": 64.0, + "00s": 3.0, + "punk": 4.0 + } + }, + { + "description": "The Rolling Stones", + "features": { + "indie": 2.0, + "male vocalists": 1.0, + "Psychedelic Rock": 2.0, + "british": 43.0, + "classic rock": 100.0, + "blues": 31.0, + "rock": 80.0, + "psychedelic": 3.0, + "pop": 2.0, + "oldies": 3.0, + "seen live": 14.0, + "alternative": 4.0, + "guitar": 1.0, + "hard rock": 8.0, + "60s": 41.0, + "70s": 8.0, + "80s": 4.0, + "90s": 2.0 + } + }, + { + "description": "Gorillaz", + "features": { + "indie": 46.0, + "favorites": 1.0, + "chillout": 3.0, + "british": 12.0, + "experimental": 6.0, + "rock": 58.0, + "electronica": 13.0, + "pop": 13.0, + "electro": 2.0, + "downtempo": 1.0, + "punk rock": 1.0, + "indie rock": 4.0, + "hip hop": 7.0, + "electronic": 88.0, + "trip-hop": 20.0, + "dance": 4.0, + "britpop": 4.0, + "rap": 4.0, + "indie pop": 2.0, + "seen live": 5.0, + "Hip-Hop": 63.0, + "alternative": 100.0, + "metal": 2.0, + "alternative rock": 11.0, + "00s": 3.0, + "punk": 2.0, + "funk": 3.0 + } + }, + { + "description": "Frank Ocean", + "features": { + "indie": 3.0, + "male vocalists": 6.0, + "singer-songwriter": 4.0, + "soul": 93.0, + "american": 8.0, + "experimental": 2.0, + "pop": 6.0, + "electronica": 1.0, + "hip hop": 8.0, + "electronic": 3.0, + "rap": 4.0, + "seen live": 14.0, + "Hip-Hop": 82.0, + "rnb": 100.0, + "alternative": 3.0, + "funk": 2.0 + } + }, + { + "description": "Panic! at the Disco", + "features": { + "male vocalists": 3.0, + "american": 8.0, + "electronica": 2.0, + "punk rock": 6.0, + "indie rock": 21.0, + "dance": 20.0, + "metal": 2.0, + "screamo": 2.0, + "punk": 21.0, + "Love": 2.0, + "indie": 68.0, + "favorites": 4.0, + "emo": 97.0, + "rock": 100.0, + "pop": 9.0, + "electronic": 4.0, + "indie pop": 2.0, + "seen live": 51.0, + "hardcore": 2.0, + "techno": 1.0, + "alternative": 99.0, + "alternative rock": 21.0, + "00s": 2.0 + } + }, + { + "description": "The Cure", + "features": { + "indie": 14.0, + "favorites": 2.0, + "male vocalists": 2.0, + "emo": 1.0, + "british": 16.0, + "classic rock": 3.0, + "rock": 52.0, + "pop": 6.0, + "psychedelic": 1.0, + "synthpop": 1.0, + "punk rock": 1.0, + "indie rock": 3.0, + "new wave": 100.0, + "electronic": 2.0, + "britpop": 2.0, + "indie pop": 1.0, + "seen live": 24.0, + "alternative": 68.0, + "Gothic": 10.0, + "post-punk": 100.0, + "alternative rock": 23.0, + "punk": 4.0, + "Love": 2.0, + "70s": 2.0, + "80s": 65.0, + "90s": 3.0 + } + }, + { + "description": "Madonna", + "features": { + "singer-songwriter": 3.0, + "american": 8.0, + "pop": 100.0, + "rock": 5.0, + "electronica": 3.0, + "electronic": 29.0, + "dance": 50.0, + "seen live": 9.0, + "rnb": 1.0, + "alternative": 2.0, + "female vocalist": 4.0, + "00s": 4.0, + "female vocalists": 50.0, + "Love": 1.0, + "80s": 35.0, + "90s": 8.0 + } + }, + { + "description": "The Chainsmokers", + "features": { + "male vocalists": 6.0, + "american": 28.0, + "electronica": 3.0, + "dance": 33.0, + "House": 63.0, + "pop": 79.0, + "electro": 6.0, + "electronic": 100.0, + "seen live": 17.0, + "techno": 3.0, + "alternative": 3.0 + } + }, + { + "description": "Linkin Park", + "features": { + "favorites": 2.0, + "indie": 1.0, + "male vocalists": 3.0, + "emo": 3.0, + "american": 6.0, + "rock": 100.0, + "pop": 3.0, + "punk rock": 2.0, + "electronic": 4.0, + "rap": 3.0, + "seen live": 21.0, + "Hip-Hop": 2.0, + "alternative": 67.0, + "metal": 37.0, + "Nu Metal": 92.0, + "alternative rock": 74.0, + "00s": 2.0, + "punk": 4.0, + "hard rock": 5.0 + } + }, + { + "description": "Lorde", + "features": { + "indie": 72.0, + "singer-songwriter": 7.0, + "soul": 1.0, + "experimental": 2.0, + "pop": 100.0, + "electronica": 5.0, + "rock": 1.0, + "synthpop": 7.0, + "electronic": 81.0, + "trip-hop": 2.0, + "indie pop": 92.0, + "seen live": 20.0, + "alternative": 17.0, + "female vocalist": 4.0, + "female vocalists": 28.0, + "folk": 2.0 + } + }, + { + "description": "The Black Keys", + "features": { + "indie": 50.0, + "male vocalists": 2.0, + "soul": 2.0, + "Psychedelic Rock": 2.0, + "american": 8.0, + "blues": 68.0, + "classic rock": 2.0, + "rock": 63.0, + "psychedelic": 2.0, + "indie rock": 48.0, + "seen live": 37.0, + "alternative": 11.0, + "alternative rock": 7.0, + "00s": 3.0, + "hard rock": 2.0 + } + }, + { + "description": "Daft Punk", + "features": { + "indie": 2.0, + "chillout": 2.0, + "experimental": 2.0, + "electronica": 37.0, + "rock": 3.0, + "pop": 2.0, + "electro": 11.0, + "synthpop": 1.0, + "electronic": 100.0, + "dance": 54.0, + "french": 19.0, + "seen live": 7.0, + "techno": 36.0, + "alternative": 6.0, + "House": 54.0, + "trance": 2.0, + "00s": 2.0, + "Soundtrack": 2.0, + "funk": 4.0, + "90s": 3.0 + } + }, + { + "description": "Led Zeppelin", + "features": { + "favorites": 1.0, + "indie": 1.0, + "Psychedelic Rock": 3.0, + "british": 9.0, + "classic rock": 100.0, + "blues": 9.0, + "rock": 64.0, + "psychedelic": 4.0, + "heavy metal": 8.0, + "oldies": 1.0, + "metal": 4.0, + "alternative": 4.0, + "guitar": 2.0, + "Progressive rock": 33.0, + "alternative rock": 1.0, + "hard rock": 63.0, + "folk": 1.0, + "60s": 3.0, + "70s": 36.0, + "80s": 1.0 + } + }, + { + "description": "Marshmello", + "features": { + "emo": 10.0, + "pop": 28.0, + "electronic": 91.0, + "dance": 100.0, + "rap": 28.0, + "seen live": 19.0, + "rnb": 19.0, + "House": 10.0 + } + }, + { + "description": "Khalid", + "features": { + "indie": 7.0, + "male vocalists": 7.0, + "soul": 88.0, + "american": 19.0, + "pop": 100.0, + "synthpop": 7.0, + "electronic": 13.0, + "seen live": 25.0, + "rnb": 75.0, + "alternative": 63.0, + "folk": 7.0 + } + }, + { + "description": "David Guetta", + "features": { + "chillout": 1.0, + "electronica": 7.0, + "pop": 6.0, + "electro": 6.0, + "electronic": 76.0, + "dance": 82.0, + "french": 11.0, + "seen live": 9.0, + "techno": 39.0, + "House": 100.0, + "trance": 4.0, + "00s": 2.0 + } + }, + { + "description": "Lizzo", + "features": { + "american": 16.0, + "dance": 8.0, + "rap": 47.0, + "rnb": 54.0, + "female vocalists": 24.0, + "pop": 16.0, + "hip hop": 47.0, + "seen live": 93.0, + "Hip-Hop": 100.0, + "alternative": 8.0 + } + }, + { + "description": "Sia", + "features": { + "indie": 70.0, + "favorites": 1.0, + "singer-songwriter": 18.0, + "soul": 3.0, + "jazz": 2.0, + "chillout": 76.0, + "Mellow": 4.0, + "ambient": 2.0, + "pop": 20.0, + "electronica": 4.0, + "rock": 2.0, + "beautiful": 4.0, + "piano": 1.0, + "downtempo": 57.0, + "indie rock": 1.0, + "electronic": 16.0, + "trip-hop": 57.0, + "dance": 2.0, + "indie pop": 8.0, + "lounge": 2.0, + "seen live": 7.0, + "alternative": 9.0, + "acoustic": 2.0, + "female vocalist": 7.0, + "alternative rock": 1.0, + "00s": 2.0, + "female vocalists": 100.0, + "Love": 2.0 + } + }, + { + "description": "Elton John", + "features": { + "favorites": 2.0, + "indie": 1.0, + "singer-songwriter": 64.0, + "male vocalists": 9.0, + "soul": 2.0, + "british": 28.0, + "classic rock": 87.0, + "blues": 1.0, + "pop": 100.0, + "rock": 59.0, + "piano": 54.0, + "oldies": 4.0, + "britpop": 2.0, + "seen live": 19.0, + "alternative": 2.0, + "Soundtrack": 3.0, + "00s": 2.0, + "Love": 2.0, + "60s": 2.0, + "70s": 16.0, + "80s": 16.0, + "90s": 5.0 + } + }, + { + "description": "Twenty One Pilots", + "features": { + "american": 15.0, + "experimental": 6.0, + "electronica": 1.0, + "piano": 1.0, + "indie rock": 12.0, + "rap": 48.0, + "pop": 17.0, + "rock": 11.0, + "electronic": 100.0, + "noise": 1.0, + "indie pop": 71.0, + "seen live": 50.0, + "male vocalists": 4.0, + "punk": 1.0, + "Love": 1.0, + "indie": 84.0, + "emo": 5.0, + "electro": 1.0, + "synthpop": 1.0, + "hip hop": 7.0, + "Hip-Hop": 27.0, + "alternative": 84.0, + "alternative rock": 23.0 + } + }, + { + "description": "Avicii", + "features": { + "swedish": 20.0, + "seen live": 14.0, + "techno": 2.0, + "House": 100.0, + "trance": 3.0, + "electronica": 6.0, + "pop": 3.0, + "electro": 5.0, + "electronic": 83.0, + "dance": 66.0 + } + }, + { + "description": "Ellie Goulding", + "features": { + "indie": 85.0, + "singer-songwriter": 11.0, + "chillout": 3.0, + "british": 89.0, + "pop": 36.0, + "electronica": 3.0, + "rock": 1.0, + "electro": 2.0, + "synthpop": 9.0, + "electronic": 98.0, + "dance": 5.0, + "britpop": 2.0, + "indie pop": 78.0, + "seen live": 27.0, + "alternative": 6.0, + "acoustic": 2.0, + "female vocalist": 5.0, + "00s": 2.0, + "female vocalists": 100.0, + "folk": 4.0 + } + }, + { + "description": "Muse", + "features": { + "indie": 43.0, + "favorites": 2.0, + "male vocalists": 3.0, + "emo": 2.0, + "british": 21.0, + "experimental": 3.0, + "rock": 83.0, + "pop": 2.0, + "piano": 1.0, + "indie rock": 12.0, + "electronic": 4.0, + "britpop": 10.0, + "seen live": 46.0, + "alternative": 70.0, + "metal": 1.0, + "Progressive rock": 57.0, + "alternative rock": 100.0, + "00s": 2.0, + "hard rock": 2.0, + "90s": 2.0 + } + }, + { + "description": "Green Day", + "features": { + "indie": 3.0, + "favorites": 2.0, + "male vocalists": 2.0, + "emo": 4.0, + "american": 7.0, + "classic rock": 2.0, + "rock": 75.0, + "pop": 6.0, + "punk rock": 100.0, + "indie rock": 2.0, + "seen live": 26.0, + "Grunge": 1.0, + "alternative": 47.0, + "metal": 2.0, + "alternative rock": 17.0, + "00s": 2.0, + "punk": 69.0, + "hard rock": 2.0, + "90s": 5.0 + } + }, + { + "description": "Metallica", + "features": { + "seen live": 31.0, + "emo": 2.0, + "metal": 91.0, + "alternative": 2.0, + "american": 6.0, + "Power metal": 1.0, + "classic rock": 6.0, + "rock": 34.0, + "alternative rock": 2.0, + "hard rock": 41.0, + "heavy metal": 74.0, + "80s": 4.0, + "thrash metal": 100.0, + "90s": 3.0, + "Progressive metal": 2.0 + } + }, + { + "description": "Sam Smith", + "features": { + "indie": 3.0, + "male vocalists": 9.0, + "singer-songwriter": 8.0, + "soul": 100.0, + "british": 55.0, + "pop": 87.0, + "electronic": 45.0, + "dance": 32.0, + "seen live": 30.0, + "rnb": 7.0, + "alternative": 3.0, + "folk": 2.0 + } + }, + { + "description": "Kygo", + "features": { + "electronica": 7.0, + "downtempo": 49.0, + "dance": 5.0, + "House": 74.0, + "chillout": 65.0, + "pop": 5.0, + "synthpop": 3.0, + "electronic": 100.0, + "seen live": 36.0 + } + }, + { + "description": "Halsey", + "features": { + "american": 34.0, + "classic rock": 2.0, + "beautiful": 4.0, + "black metal": 4.0, + "pop": 100.0, + "electronic": 38.0, + "noise": 2.0, + "heavy metal": 2.0, + "indie pop": 44.0, + "seen live": 32.0, + "female vocalist": 4.0, + "singer-songwriter": 8.0, + "british": 4.0, + "rnb": 4.0, + "trance": 2.0, + "female vocalists": 44.0, + "indie": 68.0, + "soul": 4.0, + "emo": 4.0, + "synthpop": 12.0, + "alternative": 32.0 + } + }, + { + "description": "Michael Jackson", + "features": { + "male vocalists": 5.0, + "singer-songwriter": 2.0, + "soul": 36.0, + "american": 6.0, + "classic rock": 2.0, + "pop": 100.0, + "rock": 8.0, + "electronic": 1.0, + "dance": 41.0, + "seen live": 3.0, + "rnb": 7.0, + "70s": 3.0, + "80s": 50.0, + "funk": 34.0, + "90s": 5.0 + } + }, + { + "description": "Maroon 5", + "features": { + "indie": 12.0, + "favorites": 3.0, + "male vocalists": 9.0, + "singer-songwriter": 2.0, + "soul": 3.0, + "emo": 2.0, + "jazz": 2.0, + "american": 11.0, + "classic rock": 2.0, + "rock": 100.0, + "pop": 96.0, + "punk rock": 2.0, + "indie rock": 3.0, + "electronic": 1.0, + "dance": 2.0, + "britpop": 1.0, + "indie pop": 2.0, + "seen live": 16.0, + "alternative": 69.0, + "acoustic": 2.0, + "metal": 1.0, + "alternative rock": 52.0, + "00s": 4.0, + "punk": 3.0, + "Love": 2.0, + "funk": 5.0 + } + }, + { + "description": "Charli XCX", + "features": { + "singer-songwriter": 5.0, + "british": 26.0, + "experimental": 2.0, + "electronica": 5.0, + "dance": 4.0, + "female vocalists": 56.0, + "indie": 7.0, + "chillout": 11.0, + "pop": 98.0, + "rock": 2.0, + "electro": 4.0, + "synthpop": 100.0, + "electronic": 99.0, + "new wave": 4.0, + "britpop": 2.0, + "indie pop": 7.0, + "seen live": 63.0, + "Hip-Hop": 2.0, + "alternative": 5.0, + "female vocalist": 2.0, + "00s": 2.0 + } + }, + { + "description": "Foo Fighters", + "features": { + "indie": 7.0, + "favorites": 2.0, + "male vocalists": 2.0, + "emo": 1.0, + "american": 5.0, + "classic rock": 1.0, + "rock": 100.0, + "pop": 2.0, + "punk rock": 2.0, + "indie rock": 3.0, + "seen live": 35.0, + "Grunge": 48.0, + "alternative": 47.0, + "metal": 2.0, + "alternative rock": 69.0, + "00s": 2.0, + "punk": 5.0, + "hard rock": 30.0, + "90s": 4.0 + } + }, + { + "description": "Florence + the Machine", + "features": { + "indie": 100.0, + "singer-songwriter": 7.0, + "soul": 5.0, + "british": 72.0, + "experimental": 2.0, + "pop": 10.0, + "rock": 5.0, + "beautiful": 1.0, + "indie rock": 8.0, + "electronic": 2.0, + "britpop": 2.0, + "indie pop": 61.0, + "seen live": 29.0, + "alternative": 72.0, + "female vocalist": 3.0, + "alternative rock": 5.0, + "00s": 2.0, + "female vocalists": 86.0, + "Love": 2.0, + "folk": 6.0 + } + }, + { + "description": "blink-182", + "features": { + "indie": 3.0, + "favorites": 2.0, + "male vocalists": 2.0, + "emo": 8.0, + "american": 6.0, + "rock": 56.0, + "pop": 5.0, + "punk rock": 100.0, + "indie rock": 2.0, + "seen live": 23.0, + "hardcore": 2.0, + "alternative": 42.0, + "metal": 2.0, + "alternative rock": 10.0, + "00s": 1.0, + "punk": 72.0, + "hard rock": 1.0, + "90s": 4.0 + } + }, + { + "description": "Vampire Weekend", + "features": { + "indie": 100.0, + "male vocalists": 3.0, + "american": 11.0, + "experimental": 6.0, + "rock": 37.0, + "pop": 9.0, + "indie rock": 82.0, + "electronic": 2.0, + "indie pop": 63.0, + "seen live": 58.0, + "alternative": 57.0, + "alternative rock": 7.0, + "00s": 4.0, + "folk": 1.0 + } + }, + { + "description": "Martin Garrix", + "features": { + "german": 2.0, + "experimental": 2.0, + "american": 2.0, + "electronica": 5.0, + "dance": 57.0, + "House": 100.0, + "Soundtrack": 2.0, + "black metal": 2.0, + "Power metal": 2.0, + "pop": 30.0, + "electronic": 80.0, + "noise": 2.0, + "seen live": 38.0, + "Grunge": 2.0, + "techno": 2.0, + "trance": 3.0, + "electro": 5.0 + } + }, + { + "description": "Paramore", + "features": { + "indie": 9.0, + "favorites": 2.0, + "emo": 35.0, + "american": 7.0, + "rock": 100.0, + "pop": 6.0, + "punk rock": 8.0, + "indie rock": 4.0, + "seen live": 34.0, + "alternative": 79.0, + "female vocalist": 6.0, + "alternative rock": 22.0, + "screamo": 1.0, + "00s": 2.0, + "female vocalists": 72.0, + "punk": 13.0, + "Love": 2.0 + } + }, + { + "description": "Britney Spears", + "features": { + "singer-songwriter": 2.0, + "american": 9.0, + "electronica": 1.0, + "beautiful": 2.0, + "dance": 44.0, + "rnb": 3.0, + "House": 1.0, + "trance": 1.0, + "female vocalists": 44.0, + "Love": 2.0, + "black metal": 2.0, + "90s": 6.0, + "indie": 1.0, + "death metal": 1.0, + "emo": 2.0, + "pop": 100.0, + "rock": 3.0, + "electro": 2.0, + "electronic": 5.0, + "seen live": 7.0, + "Hip-Hop": 2.0, + "alternative": 2.0, + "female vocalist": 4.0, + "00s": 4.0 + } + }, + { + "description": "Travi$ Scott", + "features": { + "male vocalists": 2.0, + "american": 10.0, + "experimental": 4.0, + "electronica": 2.0, + "rap": 62.0, + "rnb": 4.0, + "soul": 4.0, + "electro": 4.0, + "hip hop": 20.0, + "seen live": 24.0, + "Hip-Hop": 100.0, + "alternative": 2.0 + } + }, + { + "description": "Oasis", + "features": { + "indie": 45.0, + "favorites": 1.0, + "male vocalists": 2.0, + "british": 61.0, + "classic rock": 3.0, + "rock": 89.0, + "pop": 7.0, + "indie rock": 12.0, + "britpop": 100.0, + "seen live": 21.0, + "alternative": 53.0, + "alternative rock": 20.0, + "00s": 2.0, + "punk": 1.0, + "hard rock": 2.0, + "90s": 10.0 + } + }, + { + "description": "A$AP Rocky", + "features": { + "male vocalists": 3.0, + "american": 9.0, + "experimental": 2.0, + "hip hop": 12.0, + "rap": 61.0, + "seen live": 30.0, + "Hip-Hop": 100.0 + } + }, + { + "description": "Nicki Minaj", + "features": { + "singer-songwriter": 2.0, + "american": 7.0, + "dance": 9.0, + "rap": 84.0, + "rnb": 51.0, + "female vocalists": 25.0, + "Love": 2.0, + "chillout": 1.0, + "pop": 44.0, + "hip hop": 39.0, + "electronic": 3.0, + "seen live": 4.0, + "Hip-Hop": 100.0, + "alternative": 2.0, + "female vocalist": 3.0 + } + }, + { + "description": "The Smiths", + "features": { + "indie": 100.0, + "favorites": 3.0, + "male vocalists": 3.0, + "singer-songwriter": 2.0, + "emo": 2.0, + "british": 32.0, + "classic rock": 4.0, + "rock": 32.0, + "pop": 10.0, + "indie rock": 22.0, + "new wave": 85.0, + "electronic": 1.0, + "britpop": 10.0, + "indie pop": 10.0, + "seen live": 2.0, + "alternative": 77.0, + "post-punk": 85.0, + "alternative rock": 21.0, + "punk": 2.0, + "Love": 2.0, + "80s": 96.0 + } + }, + { + "description": "The Strokes", + "features": { + "indie": 97.0, + "favorites": 2.0, + "male vocalists": 2.0, + "emo": 1.0, + "american": 10.0, + "british": 2.0, + "classic rock": 2.0, + "rock": 98.0, + "pop": 2.0, + "punk rock": 2.0, + "indie rock": 100.0, + "new wave": 1.0, + "britpop": 2.0, + "indie pop": 3.0, + "seen live": 42.0, + "alternative": 71.0, + "post-punk": 5.0, + "alternative rock": 59.0, + "00s": 4.0, + "punk": 4.0, + "Love": 1.0 + } + }, + { + "description": "MGMT", + "features": { + "indie": 90.0, + "male vocalists": 2.0, + "Psychedelic Rock": 4.0, + "american": 8.0, + "experimental": 5.0, + "psychedelic": 68.0, + "pop": 7.0, + "rock": 5.0, + "electronica": 5.0, + "electro": 3.0, + "synthpop": 10.0, + "indie rock": 10.0, + "electronic": 100.0, + "dance": 3.0, + "indie pop": 51.0, + "seen live": 35.0, + "alternative": 53.0, + "post-punk": 1.0, + "alternative rock": 3.0, + "00s": 3.0 + } + }, + { + "description": "Fall Out Boy", + "features": { + "indie": 14.0, + "favorites": 3.0, + "male vocalists": 3.0, + "emo": 86.0, + "american": 7.0, + "rock": 91.0, + "pop": 9.0, + "punk rock": 28.0, + "indie rock": 4.0, + "dance": 1.0, + "seen live": 39.0, + "hardcore": 3.0, + "alternative": 69.0, + "metal": 2.0, + "alternative rock": 16.0, + "screamo": 3.0, + "00s": 2.0, + "punk": 55.0, + "Love": 2.0 + } + }, + { + "description": "Dua Lipa", + "features": { + "beautiful": 8.0, + "dance": 11.0, + "pop": 100.0, + "electronic": 11.0, + "indie pop": 16.0, + "seen live": 28.0, + "british": 29.0, + "japanese": 6.0, + "rnb": 12.0, + "female vocalists": 31.0, + "indie": 9.0, + "emo": 9.0, + "synthpop": 35.0 + } + }, + { + "description": "Jonas Brothers", + "features": { + "american": 9.0, + "grindcore": 3.0, + "punk rock": 2.0, + "dance": 2.0, + "metal": 3.0, + "House": 2.0, + "Soundtrack": 2.0, + "black metal": 3.0, + "Power metal": 2.0, + "pop": 100.0, + "rock": 56.0, + "Melodic Death Metal": 3.0, + "seen live": 17.0, + "00s": 4.0, + "male vocalists": 10.0, + "female vocalists": 2.0, + "punk": 3.0, + "Love": 3.0, + "indie": 2.0, + "death metal": 4.0, + "emo": 3.0, + "metalcore": 2.0, + "hardcore": 2.0, + "alternative": 2.0, + "alternative rock": 2.0 + } + }, + { + "description": "Foster the People", + "features": { + "indie": 100.0, + "male vocalists": 4.0, + "american": 36.0, + "pop": 10.0, + "rock": 7.0, + "indie rock": 12.0, + "electronic": 8.0, + "dance": 2.0, + "indie pop": 83.0, + "seen live": 23.0, + "alternative": 65.0, + "alternative rock": 7.0, + "00s": 1.0 + } + }, + { + "description": "Bon Iver", + "features": { + "indie": 75.0, + "singer-songwriter": 70.0, + "male vocalists": 4.0, + "Mellow": 3.0, + "chillout": 2.0, + "american": 7.0, + "experimental": 2.0, + "ambient": 2.0, + "rock": 2.0, + "beautiful": 3.0, + "indie rock": 5.0, + "indie pop": 2.0, + "seen live": 36.0, + "acoustic": 59.0, + "alternative": 6.0, + "00s": 2.0, + "folk": 100.0 + } + }, + { + "description": "Major Lazer", + "features": { + "indie": 2.0, + "american": 4.0, + "experimental": 3.0, + "british": 2.0, + "electronica": 5.0, + "pop": 2.0, + "electro": 37.0, + "hip hop": 2.0, + "electronic": 85.0, + "dance": 12.0, + "seen live": 100.0, + "Hip-Hop": 4.0, + "alternative": 2.0, + "House": 3.0, + "00s": 2.0, + "funk": 4.0, + "reggae": 66.0 + } + }, + { + "description": "Two Door Cinema Club", + "features": { + "indie": 100.0, + "male vocalists": 2.0, + "british": 63.0, + "rock": 6.0, + "pop": 3.0, + "electronica": 2.0, + "synthpop": 2.0, + "indie rock": 19.0, + "electronic": 68.0, + "dance": 2.0, + "britpop": 2.0, + "indie pop": 10.0, + "seen live": 47.0, + "alternative": 53.0, + "alternative rock": 4.0, + "00s": 2.0 + } + }, + { + "description": "OneRepublic", + "features": { + "indie": 63.0, + "favorites": 2.0, + "male vocalists": 8.0, + "emo": 1.0, + "american": 12.0, + "rock": 100.0, + "pop": 21.0, + "piano": 2.0, + "indie rock": 5.0, + "indie pop": 2.0, + "seen live": 9.0, + "alternative": 94.0, + "acoustic": 1.0, + "alternative rock": 80.0, + "00s": 3.0, + "Love": 2.0 + } + }, + { + "description": "Cage the Elephant", + "features": { + "indie": 59.0, + "male vocalists": 2.0, + "american": 11.0, + "rock": 68.0, + "punk rock": 44.0, + "indie rock": 100.0, + "seen live": 41.0, + "alternative": 73.0, + "alternative rock": 26.0, + "00s": 4.0, + "punk": 7.0 + } + }, + { + "description": "Arcade Fire", + "features": { + "indie": 100.0, + "male vocalists": 2.0, + "experimental": 6.0, + "rock": 48.0, + "pop": 2.0, + "beautiful": 1.0, + "post-rock": 2.0, + "indie rock": 99.0, + "new wave": 1.0, + "indie pop": 4.0, + "seen live": 59.0, + "alternative": 76.0, + "post-punk": 3.0, + "alternative rock": 16.0, + "00s": 5.0, + "female vocalists": 2.0, + "folk": 6.0 + } + }, + { + "description": "Bruno Mars", + "features": { + "indie": 3.0, + "male vocalists": 47.0, + "singer-songwriter": 7.0, + "soul": 10.0, + "american": 8.0, + "blues": 2.0, + "pop": 100.0, + "rock": 2.0, + "hip hop": 2.0, + "dance": 2.0, + "seen live": 6.0, + "Hip-Hop": 3.0, + "rnb": 63.0, + "alternative": 2.0, + "acoustic": 1.0, + "folk": 1.0, + "funk": 4.0, + "reggae": 4.0 + } + }, + { + "description": "Carly Rae Jepsen", + "features": { + "singer-songwriter": 5.0, + "soul": 2.0, + "chillout": 2.0, + "pop": 100.0, + "synthpop": 9.0, + "electronic": 4.0, + "dance": 11.0, + "seen live": 6.0, + "acoustic": 21.0, + "female vocalist": 4.0, + "00s": 1.0, + "female vocalists": 46.0, + "folk": 26.0 + } + }, + { + "description": "Weezer", + "features": { + "indie": 50.0, + "favorites": 3.0, + "male vocalists": 2.0, + "emo": 15.0, + "american": 8.0, + "classic rock": 2.0, + "rock": 100.0, + "pop": 6.0, + "punk rock": 5.0, + "indie rock": 41.0, + "britpop": 1.0, + "indie pop": 3.0, + "seen live": 37.0, + "hardcore": 1.0, + "Grunge": 2.0, + "alternative": 86.0, + "metal": 2.0, + "alternative rock": 73.0, + "00s": 2.0, + "punk": 11.0, + "Love": 1.0, + "hard rock": 2.0, + "90s": 9.0 + } + }, + { + "description": "P!nk", + "features": { + "indie": 2.0, + "favorites": 2.0, + "singer-songwriter": 5.0, + "soul": 2.0, + "american": 11.0, + "pop": 100.0, + "rock": 59.0, + "electronic": 2.0, + "dance": 7.0, + "seen live": 14.0, + "Hip-Hop": 2.0, + "rnb": 5.0, + "alternative": 4.0, + "female vocalist": 4.0, + "alternative rock": 2.0, + "00s": 4.0, + "female vocalists": 74.0, + "punk": 3.0 + } + }, + { + "description": "System of a Down", + "features": { + "indie": 2.0, + "favorites": 1.0, + "male vocalists": 1.0, + "emo": 2.0, + "american": 5.0, + "experimental": 3.0, + "rock": 65.0, + "punk rock": 2.0, + "metalcore": 1.0, + "heavy metal": 6.0, + "Progressive metal": 3.0, + "thrash metal": 2.0, + "seen live": 18.0, + "hardcore": 3.0, + "metal": 100.0, + "alternative": 54.0, + "Progressive rock": 2.0, + "Nu Metal": 62.0, + "alternative rock": 13.0, + "industrial": 1.0, + "00s": 2.0, + "punk": 3.0, + "hard rock": 20.0, + "90s": 2.0 + } + }, + { + "description": "Adele", + "features": { + "indie": 40.0, + "singer-songwriter": 50.0, + "soul": 100.0, + "jazz": 8.0, + "chillout": 2.0, + "Mellow": 2.0, + "british": 66.0, + "blues": 3.0, + "pop": 19.0, + "rock": 2.0, + "beautiful": 1.0, + "piano": 2.0, + "britpop": 3.0, + "indie pop": 3.0, + "seen live": 2.0, + "rnb": 2.0, + "acoustic": 4.0, + "alternative": 4.0, + "female vocalist": 4.0, + "00s": 2.0, + "female vocalists": 81.0, + "Love": 2.0, + "folk": 2.0 + } + }, + { + "description": "xxxtentacion", + "features": { + "american": 11.0, + "experimental": 7.0, + "punk rock": 4.0, + "rap": 80.0, + "folk": 4.0, + "rock": 7.0, + "pop": 4.0, + "heavy metal": 4.0, + "seen live": 4.0, + "rnb": 7.0, + "emo": 49.0, + "soul": 4.0, + "hip hop": 32.0, + "new wave": 4.0, + "hardcore": 4.0, + "Hip-Hop": 100.0, + "alternative": 11.0, + "alternative rock": 7.0 + } + }, + { + "description": "The 1975", + "features": { + "male vocalists": 5.0, + "british": 69.0, + "experimental": 2.0, + "indie rock": 98.0, + "Love": 1.0, + "indie": 100.0, + "emo": 1.0, + "ambient": 1.0, + "rock": 21.0, + "pop": 9.0, + "post-rock": 1.0, + "synthpop": 5.0, + "new wave": 4.0, + "electronic": 3.0, + "britpop": 1.0, + "indie pop": 17.0, + "seen live": 73.0, + "alternative": 69.0, + "alternative rock": 20.0, + "00s": 1.0, + "funk": 1.0 + } + }, + { + "description": "Depeche Mode", + "features": { + "indie": 3.0, + "favorites": 1.0, + "male vocalists": 2.0, + "british": 13.0, + "ambient": 1.0, + "experimental": 1.0, + "classic rock": 2.0, + "rock": 16.0, + "electronica": 11.0, + "pop": 9.0, + "electro": 3.0, + "synthpop": 56.0, + "electronic": 100.0, + "new wave": 87.0, + "dance": 3.0, + "britpop": 2.0, + "seen live": 22.0, + "techno": 1.0, + "alternative": 20.0, + "Gothic": 2.0, + "post-punk": 4.0, + "alternative rock": 5.0, + "industrial": 3.0, + "00s": 2.0, + "80s": 59.0, + "90s": 4.0 + } + }, + { + "description": "The White Stripes", + "features": { + "indie": 59.0, + "favorites": 2.0, + "male vocalists": 1.0, + "singer-songwriter": 1.0, + "american": 8.0, + "experimental": 1.0, + "blues": 13.0, + "classic rock": 3.0, + "rock": 100.0, + "pop": 2.0, + "punk rock": 2.0, + "indie rock": 47.0, + "seen live": 25.0, + "Grunge": 1.0, + "alternative": 74.0, + "metal": 1.0, + "guitar": 2.0, + "Progressive rock": 1.0, + "alternative rock": 65.0, + "00s": 3.0, + "punk": 5.0, + "hard rock": 3.0, + "folk": 2.0, + "90s": 2.0 + } + }, + { + "description": "The Clash", + "features": { + "indie": 5.0, + "british": 43.0, + "classic rock": 29.0, + "rock": 43.0, + "pop": 1.0, + "punk rock": 71.0, + "indie rock": 2.0, + "new wave": 4.0, + "alternative": 9.0, + "post-punk": 3.0, + "alternative rock": 2.0, + "punk": 100.0, + "hard rock": 1.0, + "70s": 8.0, + "80s": 13.0, + "reggae": 6.0 + } + } +] \ No newline at end of file diff --git a/algorithms-miscellaneous-3/src/main/resources/kmeans/lastfm.json b/algorithms-miscellaneous-3/src/main/resources/kmeans/lastfm.json new file mode 100644 index 0000000000..4d684b2fc0 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/resources/kmeans/lastfm.json @@ -0,0 +1,490 @@ +{ + "children": [ + { + "children": [ + { + "name": "Radiohead" + }, + { + "name": "Red Hot Chili Peppers" + }, + { + "name": "Coldplay" + }, + { + "name": "Nirvana" + }, + { + "name": "Panic! at the Disco" + }, + { + "name": "The Cure" + }, + { + "name": "Linkin Park" + }, + { + "name": "Radiohead" + }, + { + "name": "Red Hot Chili Peppers" + }, + { + "name": "Coldplay" + }, + { + "name": "Nirvana" + }, + { + "name": "Panic! at the Disco" + }, + { + "name": "The Cure" + }, + { + "name": "Linkin Park" + }, + { + "name": "Muse" + }, + { + "name": "Maroon 5" + }, + { + "name": "Foo Fighters" + }, + { + "name": "Paramore" + }, + { + "name": "Oasis" + }, + { + "name": "Fall Out Boy" + }, + { + "name": "OneRepublic" + }, + { + "name": "Weezer" + }, + { + "name": "System of a Down" + }, + { + "name": "The White Stripes" + } + ], + "name": "rock, alternative" + }, + { + "children": [ + { + "name": "Lil Nas X" + }, + { + "name": "Post Malone" + }, + { + "name": "Drake" + }, + { + "name": "Kanye West" + }, + { + "name": "Kendrick Lamar" + }, + { + "name": "Tyler, the Creator" + }, + { + "name": "Eminem" + }, + { + "name": "Childish Gambino" + }, + { + "name": "Frank Ocean" + }, + { + "name": "Lil Nas X" + }, + { + "name": "Post Malone" + }, + { + "name": "Drake" + }, + { + "name": "Kanye West" + }, + { + "name": "Kendrick Lamar" + }, + { + "name": "Tyler, the Creator" + }, + { + "name": "Eminem" + }, + { + "name": "Childish Gambino" + }, + { + "name": "Frank Ocean" + }, + { + "name": "Lizzo" + }, + { + "name": "Travi$ Scott" + }, + { + "name": "A$AP Rocky" + }, + { + "name": "Nicki Minaj" + }, + { + "name": "xxxtentacion" + } + ], + "name": "Hip-Hop, rap" + }, + { + "children": [ + { + "name": "Arctic Monkeys" + }, + { + "name": "Imagine Dragons" + }, + { + "name": "The Killers" + }, + { + "name": "Gorillaz" + }, + { + "name": "The Black Keys" + }, + { + "name": "Arctic Monkeys" + }, + { + "name": "Imagine Dragons" + }, + { + "name": "The Killers" + }, + { + "name": "Gorillaz" + }, + { + "name": "The Black Keys" + }, + { + "name": "Twenty One Pilots" + }, + { + "name": "Ellie Goulding" + }, + { + "name": "Florence + the Machine" + }, + { + "name": "Vampire Weekend" + }, + { + "name": "The Smiths" + }, + { + "name": "The Strokes" + }, + { + "name": "MGMT" + }, + { + "name": "Foster the People" + }, + { + "name": "Two Door Cinema Club" + }, + { + "name": "Cage the Elephant" + }, + { + "name": "Arcade Fire" + }, + { + "name": "The 1975" + } + ], + "name": "indie, alternative" + }, + { + "children": [ + { + "name": "Ed Sheeran" + }, + { + "name": "Tame Impala" + }, + { + "name": "Ed Sheeran" + }, + { + "name": "Tame Impala" + }, + { + "name": "Green Day" + }, + { + "name": "Metallica" + }, + { + "name": "blink-182" + }, + { + "name": "Bon Iver" + }, + { + "name": "The Clash" + } + ], + "name": "rock, punk rock" + }, + { + "children": [ + { + "name": "Calvin Harris" + }, + { + "name": "The Weeknd" + }, + { + "name": "The Chainsmokers" + }, + { + "name": "Daft Punk" + }, + { + "name": "Marshmello" + }, + { + "name": "David Guetta" + }, + { + "name": "Calvin Harris" + }, + { + "name": "The Weeknd" + }, + { + "name": "The Chainsmokers" + }, + { + "name": "Daft Punk" + }, + { + "name": "Marshmello" + }, + { + "name": "David Guetta" + }, + { + "name": "Avicii" + }, + { + "name": "Kygo" + }, + { + "name": "Martin Garrix" + }, + { + "name": "Major Lazer" + }, + { + "name": "Depeche Mode" + } + ], + "name": "electronic, dance" + }, + { + "children": [ + { + "name": "Queen" + }, + { + "name": "The Beatles" + }, + { + "name": "David Bowie" + }, + { + "name": "Fleetwood Mac" + }, + { + "name": "Pink Floyd" + }, + { + "name": "The Rolling Stones" + }, + { + "name": "Led Zeppelin" + }, + { + "name": "Queen" + }, + { + "name": "The Beatles" + }, + { + "name": "David Bowie" + }, + { + "name": "Fleetwood Mac" + }, + { + "name": "Pink Floyd" + }, + { + "name": "The Rolling Stones" + }, + { + "name": "Led Zeppelin" + }, + { + "name": "Elton John" + } + ], + "name": "classic rock, rock" + }, + { + "children": [ + { + "name": "Billie Eilish" + }, + { + "name": "Ariana Grande" + }, + { + "name": "Taylor Swift" + }, + { + "name": "Beyoncé" + }, + { + "name": "Shawn Mendes" + }, + { + "name": "Rihanna" + }, + { + "name": "Lana Del Rey" + }, + { + "name": "Katy Perry" + }, + { + "name": "Lady Gaga" + }, + { + "name": "Miley Cyrus" + }, + { + "name": "Mark Ronson" + }, + { + "name": "Madonna" + }, + { + "name": "Lorde" + }, + { + "name": "Khalid" + }, + { + "name": "Billie Eilish" + }, + { + "name": "Ariana Grande" + }, + { + "name": "Taylor Swift" + }, + { + "name": "Beyoncé" + }, + { + "name": "Shawn Mendes" + }, + { + "name": "Rihanna" + }, + { + "name": "Lana Del Rey" + }, + { + "name": "Katy Perry" + }, + { + "name": "Lady Gaga" + }, + { + "name": "Miley Cyrus" + }, + { + "name": "Mark Ronson" + }, + { + "name": "Madonna" + }, + { + "name": "Lorde" + }, + { + "name": "Khalid" + }, + { + "name": "Sia" + }, + { + "name": "Sam Smith" + }, + { + "name": "Halsey" + }, + { + "name": "Michael Jackson" + }, + { + "name": "Charli XCX" + }, + { + "name": "Britney Spears" + }, + { + "name": "Dua Lipa" + }, + { + "name": "Jonas Brothers" + }, + { + "name": "Bruno Mars" + }, + { + "name": "Carly Rae Jepsen" + }, + { + "name": "P!nk" + }, + { + "name": "Adele" + } + ], + "name": "pop, female vocalists" + } + ], + "name": "Musicians" +} diff --git a/algorithms-miscellaneous-3/src/main/resources/kmeans/radial.html b/algorithms-miscellaneous-3/src/main/resources/kmeans/radial.html new file mode 100644 index 0000000000..e7e7403871 --- /dev/null +++ b/algorithms-miscellaneous-3/src/main/resources/kmeans/radial.html @@ -0,0 +1,68 @@ + + + + + + \ No newline at end of file diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/interpolationsearch/InterpolationSearchUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/interpolationsearch/InterpolationSearchUnitTest.java new file mode 100644 index 0000000000..8ad962055e --- /dev/null +++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/interpolationsearch/InterpolationSearchUnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.algorithms.interpolationsearch; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +public class InterpolationSearchUnitTest { + + private int[] myData; + + @Before + public void setUp() { + myData = new int[]{13,21,34,55,69,73,84,101}; + } + + @Test + public void givenSortedArray_whenLookingFor84_thenReturn6() { + int pos = InterpolationSearch.interpolationSearch(myData, 84); + assertEquals(6, pos); + } + + @Test + public void givenSortedArray_whenLookingFor19_thenReturnMinusOne() { + int pos = InterpolationSearch.interpolationSearch(myData, 19); + assertEquals(-1, pos); + } + +} diff --git a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/printtriangles/PrintTriangleExamplesUnitTest.java b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/printtriangles/PrintTriangleExamplesUnitTest.java index 6fa6584b8e..97e99290c9 100644 --- a/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/printtriangles/PrintTriangleExamplesUnitTest.java +++ b/algorithms-miscellaneous-3/src/test/java/com/baeldung/algorithms/printtriangles/PrintTriangleExamplesUnitTest.java @@ -9,9 +9,9 @@ import static org.junit.Assert.assertEquals; @RunWith(JUnitParamsRunner.class) public class PrintTriangleExamplesUnitTest { - - private static Object[][] rightAngledTriangles() { - String expected0 = ""; + + private static Object[][] rightTriangles() { + String expected0 = ""; String expected2 = "*" + System.lineSeparator() + "**" + System.lineSeparator(); @@ -39,9 +39,9 @@ public class PrintTriangleExamplesUnitTest { } @Test - @Parameters(method = "rightAngledTriangles") - public void whenPrintARightAngledTriangleIsCalled_ThenTheCorrectStringIsReturned(int nrOfRows, String expected) { - String actual = PrintTriangleExamples.printARightAngledTriangle(nrOfRows); + @Parameters(method = "rightTriangles") + public void whenPrintARightTriangleIsCalled_ThenTheCorrectStringIsReturned(int nrOfRows, String expected) { + String actual = PrintTriangleExamples.printARightTriangle(nrOfRows); assertEquals(expected, actual); } @@ -81,6 +81,14 @@ public class PrintTriangleExamplesUnitTest { assertEquals(expected, actual); } + + @Test + @Parameters(method = "isoscelesTriangles") + public void whenPrintAnIsoscelesTriangleUsingStringUtilsIsCalled_ThenTheCorrectStringIsReturned(int nrOfRows, String expected) { + String actual = PrintTriangleExamples.printAnIsoscelesTriangleUsingStringUtils(nrOfRows); + + assertEquals(expected, actual); + } @Test @Parameters(method = "isoscelesTriangles") diff --git a/algorithms-sorting/README.md b/algorithms-sorting/README.md index 36460293b0..48c75f88cd 100644 --- a/algorithms-sorting/README.md +++ b/algorithms-sorting/README.md @@ -5,3 +5,4 @@ - [Quicksort Algorithm Implementation in Java](https://www.baeldung.com/java-quicksort) - [Insertion Sort in Java](https://www.baeldung.com/java-insertion-sort) - [Heap Sort in Java](https://www.baeldung.com/java-heap-sort) +- [Shell Sort in Java](https://www.baeldung.com/java-shell-sort) diff --git a/core-groovy-2/README.md b/core-groovy-2/README.md index 33df8b107b..1211dae76d 100644 --- a/core-groovy-2/README.md +++ b/core-groovy-2/README.md @@ -8,3 +8,4 @@ - [Pattern Matching in Strings in Groovy](https://www.baeldung.com/groovy-pattern-matching) - [Working with XML in Groovy](https://www.baeldung.com/groovy-xml) - [Integrating Groovy into Java Applications](https://www.baeldung.com/groovy-java-applications) +- [Concatenate Strings with Groovy](https://www.baeldung.com/groovy-concatenate-strings) diff --git a/core-java-modules/core-java-arrays-2/README.MD b/core-java-modules/core-java-arrays-2/README.MD index 9ee6998784..f272f4d299 100644 --- a/core-java-modules/core-java-arrays-2/README.MD +++ b/core-java-modules/core-java-arrays-2/README.MD @@ -1,3 +1,5 @@ ## Relevant Articles - [Extending an Array’s Length](https://www.baeldung.com/java-array-add-element-at-the-end) +- [Checking If an Array Is Sorted in Java](https://www.baeldung.com/java-check-sorted-array) +- [Looping Diagonally Through a 2d Java Array](https://www.baeldung.com/java-loop-diagonal-array) diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGenerator.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGenerator.java new file mode 100644 index 0000000000..97d44e5156 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGenerator.java @@ -0,0 +1,11 @@ +package com.baeldung.concurrent.mutex; + +public class SequenceGenerator { + private int currentValue = 0; + + public int getNextSequence() throws InterruptedException { + currentValue = currentValue + 1; + Thread.sleep(500); + return currentValue; + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingMonitor.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingMonitor.java new file mode 100644 index 0000000000..30c8da4865 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingMonitor.java @@ -0,0 +1,18 @@ +package com.baeldung.concurrent.mutex; + +import com.google.common.util.concurrent.Monitor; + +public class SequenceGeneratorUsingMonitor extends SequenceGenerator { + + private Monitor monitor = new Monitor(); + + @Override + public int getNextSequence() throws InterruptedException { + monitor.enter(); + try { + return super.getNextSequence(); + } finally { + monitor.leave(); + } + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingReentrantLock.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingReentrantLock.java new file mode 100644 index 0000000000..85ce780bda --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingReentrantLock.java @@ -0,0 +1,18 @@ +package com.baeldung.concurrent.mutex; + +import java.util.concurrent.locks.ReentrantLock; + +public class SequenceGeneratorUsingReentrantLock extends SequenceGenerator { + + private ReentrantLock mutex = new ReentrantLock(); + + @Override + public int getNextSequence() throws InterruptedException { + try { + mutex.lock(); + return super.getNextSequence(); + } finally { + mutex.unlock(); + } + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingSemaphore.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingSemaphore.java new file mode 100644 index 0000000000..fdece049e6 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingSemaphore.java @@ -0,0 +1,18 @@ +package com.baeldung.concurrent.mutex; + +import java.util.concurrent.Semaphore; + +public class SequenceGeneratorUsingSemaphore extends SequenceGenerator { + + private Semaphore mutex = new Semaphore(1); + + @Override + public int getNextSequence() throws InterruptedException { + try { + mutex.acquire(); + return super.getNextSequence(); + } finally { + mutex.release(); + } + } +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingSynchronizedBlock.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingSynchronizedBlock.java new file mode 100644 index 0000000000..d485eae21c --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingSynchronizedBlock.java @@ -0,0 +1,12 @@ +package com.baeldung.concurrent.mutex; + +public class SequenceGeneratorUsingSynchronizedBlock extends SequenceGenerator { + + @Override + public int getNextSequence() throws InterruptedException { + synchronized (this) { + return super.getNextSequence(); + } + } + +} diff --git a/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingSynchronizedMethod.java b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingSynchronizedMethod.java new file mode 100644 index 0000000000..441b33dc43 --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/main/java/com/baeldung/concurrent/mutex/SequenceGeneratorUsingSynchronizedMethod.java @@ -0,0 +1,10 @@ +package com.baeldung.concurrent.mutex; + +public class SequenceGeneratorUsingSynchronizedMethod extends SequenceGenerator { + + @Override + public synchronized int getNextSequence() throws InterruptedException { + return super.getNextSequence(); + } + +} diff --git a/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/mutex/MutexUnitTest.java b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/mutex/MutexUnitTest.java new file mode 100644 index 0000000000..620179800a --- /dev/null +++ b/core-java-modules/core-java-concurrency-basic/src/test/java/com/baeldung/concurrent/mutex/MutexUnitTest.java @@ -0,0 +1,81 @@ +package com.baeldung.concurrent.mutex; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; + +import org.junit.Assert; +import org.junit.Test; + +import com.baeldung.concurrent.mutex.SequenceGenerator; +import com.baeldung.concurrent.mutex.SequenceGeneratorUsingMonitor; +import com.baeldung.concurrent.mutex.SequenceGeneratorUsingReentrantLock; +import com.baeldung.concurrent.mutex.SequenceGeneratorUsingSemaphore; +import com.baeldung.concurrent.mutex.SequenceGeneratorUsingSynchronizedBlock; +import com.baeldung.concurrent.mutex.SequenceGeneratorUsingSynchronizedMethod; + +public class MutexUnitTest { + + private final int RANGE = 30; + + @Test + public void givenUnsafeSequenceGenerator_whenRaceCondition_thenUnexpectedBehavior() throws Exception { + Set uniqueSequences = getASetOFUniqueSequences(new SequenceGenerator()); + Assert.assertNotEquals(RANGE, uniqueSequences.size()); + } + + @Test + public void givenSequenceGeneratorUsingSynchronizedMethod_whenRaceCondition_thenSuccess() throws Exception { + Set uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingSynchronizedMethod()); + Assert.assertEquals(RANGE, uniqueSequences.size()); + } + + @Test + public void givenSequenceGeneratorUsingSynchronizedBlock_whenRaceCondition_thenSuccess() throws Exception { + Set uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingSynchronizedBlock()); + Assert.assertEquals(RANGE, uniqueSequences.size()); + } + + @Test + public void givenSequenceGeneratorUsingReentrantLock_whenRaceCondition_thenSuccess() throws Exception { + Set uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingReentrantLock()); + Assert.assertEquals(RANGE, uniqueSequences.size()); + } + + @Test + public void givenSequenceGeneratorUsingSemaphore_whenRaceCondition_thenSuccess() throws Exception { + Set uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingSemaphore()); + Assert.assertEquals(RANGE, uniqueSequences.size()); + } + + @Test + public void givenSequenceGeneratorUsingMonitor_whenRaceCondition_thenSuccess() throws Exception { + Set uniqueSequences = getASetOFUniqueSequences(new SequenceGeneratorUsingMonitor()); + Assert.assertEquals(RANGE, uniqueSequences.size()); + } + + private Set getASetOFUniqueSequences(SequenceGenerator generator) throws Exception { + ExecutorService executor = Executors.newFixedThreadPool(3); + Set uniqueSequences = new HashSet<>(); + List> futures = new ArrayList<>(); + + for (int i = 0; i < RANGE; i++) { + futures.add(executor.submit(generator::getNextSequence)); + } + + for (Future future : futures) { + uniqueSequences.add(future.get()); + } + + executor.awaitTermination(15, TimeUnit.SECONDS); + executor.shutdown(); + + return uniqueSequences; + } + +} diff --git a/core-java-modules/core-java-jndi/pom.xml b/core-java-modules/core-java-jndi/pom.xml new file mode 100644 index 0000000000..eb363f8598 --- /dev/null +++ b/core-java-modules/core-java-jndi/pom.xml @@ -0,0 +1,65 @@ + + + 4.0.0 + + com.baeldung.jndi + core-java-jndi + 1.0-SNAPSHOT + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + ../../ + + + + + org.junit.jupiter + junit-jupiter + 5.5.1 + test + + + org.springframework + spring-core + 5.0.9.RELEASE + + + org.springframework + spring-context + 5.0.9.RELEASE + + + org.springframework + spring-jdbc + 5.0.9.RELEASE + + + org.springframework + spring-test + 5.0.9.RELEASE + test + + + com.h2database + h2 + 1.4.199 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + diff --git a/core-java-modules/core-java-jndi/src/test/java/com/baeldung/jndi/JndiUnitTest.java b/core-java-modules/core-java-jndi/src/test/java/com/baeldung/jndi/JndiUnitTest.java new file mode 100644 index 0000000000..9eea420e7a --- /dev/null +++ b/core-java-modules/core-java-jndi/src/test/java/com/baeldung/jndi/JndiUnitTest.java @@ -0,0 +1,60 @@ +package com.baeldung.jndi; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.jndi.JndiTemplate; +import org.springframework.mock.jndi.SimpleNamingContextBuilder; + +import javax.naming.*; +import javax.sql.DataSource; + +import java.util.Enumeration; + +import static org.junit.jupiter.api.Assertions.*; + +class JndiUnitTest { + + private static InitialContext ctx; + private static DriverManagerDataSource ds; + + @BeforeAll + static void setUp() throws Exception { + SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); + ds = new DriverManagerDataSource("jdbc:h2:mem:mydb"); + builder.activate(); + + JndiTemplate jndiTemplate = new JndiTemplate(); + ctx = (InitialContext) jndiTemplate.getContext(); + } + + @Test + void givenACompositeName_whenAddingAnElement_thenNameIncludesIt() throws Exception { + Name objectName = new CompositeName("java:comp/env/jdbc"); + + Enumeration elements = objectName.getAll(); + while(elements.hasMoreElements()) { + System.out.println(elements.nextElement()); + } + + objectName.add("example"); + + assertEquals("env", objectName.get(1)); + assertEquals("example", objectName.get(objectName.size() - 1)); + } + + @Test + void givenADataSource_whenAddingDriver_thenBind() throws Exception { + ds.setDriverClassName("org.h2.Driver"); + ctx.bind("java:comp/env/jdbc/datasource", ds); + } + + @Test + void givenContext_whenLookupByName_thenValidDataSource() throws Exception { + DataSource ds = (DataSource) ctx.lookup("java:comp/env/jdbc/datasource"); + + assertNotNull(ds); + assertNotNull(ds.getConnection()); + } + +} diff --git a/core-java-modules/core-java-jndi/src/test/java/com/baeldung/jndi/exceptions/JndiExceptionsUnitTest.java b/core-java-modules/core-java-jndi/src/test/java/com/baeldung/jndi/exceptions/JndiExceptionsUnitTest.java new file mode 100644 index 0000000000..49d4facffb --- /dev/null +++ b/core-java-modules/core-java-jndi/src/test/java/com/baeldung/jndi/exceptions/JndiExceptionsUnitTest.java @@ -0,0 +1,42 @@ +package com.baeldung.jndi.exceptions; + +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.jndi.JndiTemplate; +import org.springframework.mock.jndi.SimpleNamingContextBuilder; + +import javax.naming.InitialContext; +import javax.naming.NameNotFoundException; +import javax.naming.NoInitialContextException; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class JndiExceptionsUnitTest { + + @Test + @Order(1) + void givenNoContext_whenLookupObject_thenThrowNoInitialContext() { + assertThrows(NoInitialContextException.class, () -> { + JndiTemplate jndiTemplate = new JndiTemplate(); + InitialContext ctx = (InitialContext) jndiTemplate.getContext(); + ctx.lookup("java:comp/env/jdbc/datasource"); + }).printStackTrace(); + } + + @Test + @Order(2) + void givenEmptyContext_whenLookupNotBounds_thenThrowNameNotFound() { + assertThrows(NameNotFoundException.class, () -> { + SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); + builder.activate(); + + JndiTemplate jndiTemplate = new JndiTemplate(); + InitialContext ctx = (InitialContext) jndiTemplate.getContext(); + ctx.lookup("badJndiName"); + }).printStackTrace(); + } + +} diff --git a/core-java-modules/core-java-networking-2/README.md b/core-java-modules/core-java-networking-2/README.md new file mode 100644 index 0000000000..6b6151248e --- /dev/null +++ b/core-java-modules/core-java-networking-2/README.md @@ -0,0 +1,3 @@ +### Relevant Articles + +- [Checking if a URL Exists in Java](https://www.baeldung.com/java-check-url-exists) diff --git a/core-java-modules/core-java-os/README.md b/core-java-modules/core-java-os/README.md index 5f5d373d9b..697af5e4d6 100644 --- a/core-java-modules/core-java-os/README.md +++ b/core-java-modules/core-java-os/README.md @@ -7,4 +7,4 @@ This module uses Java 9, so make sure to have the JDK 9 installed to run it. - [Java 9 Process API Improvements](http://www.baeldung.com/java-9-process-api) - [Guide to java.lang.Process API](https://www.baeldung.com/java-process-api) - [Guide to java.lang.ProcessBuilder API](https://www.baeldung.com/java-lang-processbuilder-api) - +- [Get the Current Working Directory in Java](https://www.baeldung.com/java-current-directory) diff --git a/java-math/src/main/java/com/baeldung/matrices/HomemadeMatrix.java b/java-math/src/main/java/com/baeldung/matrices/HomemadeMatrix.java new file mode 100644 index 0000000000..0676250959 --- /dev/null +++ b/java-math/src/main/java/com/baeldung/matrices/HomemadeMatrix.java @@ -0,0 +1,23 @@ +package com.baeldung.matrices; + +public class HomemadeMatrix { + public static double[][] multiplyMatrices(double[][] firstMatrix, double[][] secondMatrix) { + double[][] result = new double[firstMatrix.length][secondMatrix[0].length]; + + for (int row = 0; row < result.length; row++) { + for (int col = 0; col < result[row].length; col++) { + result[row][col] = multiplyMatricesCell(firstMatrix, secondMatrix, row, col); + } + } + + return result; + } + + private static double multiplyMatricesCell(double[][] firstMatrix, double[][] secondMatrix, int row, int col) { + double cell = 0; + for (int i = 0; i < secondMatrix.length; i++) { + cell += firstMatrix[row][i] * secondMatrix[i][col]; + } + return cell; + } +} \ No newline at end of file diff --git a/java-math/src/test/java/com/baeldung/algorithms/logarithm/LogarithmUnitTest.java b/java-math/src/test/java/com/baeldung/algorithms/logarithm/LogarithmUnitTest.java new file mode 100644 index 0000000000..facad1edc4 --- /dev/null +++ b/java-math/src/test/java/com/baeldung/algorithms/logarithm/LogarithmUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.algorithms.logarithm; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.Test; + +public class LogarithmUnitTest { + + @Test + public void givenLog10_shouldReturnValidResults() { + assertEquals(Math.log10(100), 2); + assertEquals(Math.log10(1000), 3); + } + + @Test + public void givenLogE_shouldReturnValidResults() { + assertEquals(Math.log(Math.E), 1); + assertEquals(Math.log(10), 2.30258, 0.00001); + } + + @Test + public void givenCustomLog_shouldReturnValidResults() { + assertEquals(customLog(2, 256), 8); + assertEquals(customLog(10, 100), 2); + } + + private static double customLog(double base, double logNumber) { + return Math.log(logNumber) / Math.log(base); + } + +} diff --git a/java-math/src/test/java/com/baeldung/matrices/MatrixMultiplicationBenchmarking.java b/java-math/src/test/java/com/baeldung/matrices/MatrixMultiplicationBenchmarking.java index 1e3b183aa7..171a1d28a4 100644 --- a/java-math/src/test/java/com/baeldung/matrices/MatrixMultiplicationBenchmarking.java +++ b/java-math/src/test/java/com/baeldung/matrices/MatrixMultiplicationBenchmarking.java @@ -1,9 +1,84 @@ package com.baeldung.matrices; +import cern.colt.matrix.DoubleFactory2D; +import cern.colt.matrix.DoubleMatrix2D; +import cern.colt.matrix.linalg.Algebra; +import org.apache.commons.math3.linear.Array2DRowRealMatrix; +import org.apache.commons.math3.linear.RealMatrix; +import org.ejml.simple.SimpleMatrix; +import org.la4j.Matrix; +import org.la4j.matrix.dense.Basic2DMatrix; +import org.nd4j.linalg.api.ndarray.INDArray; +import org.nd4j.linalg.factory.Nd4j; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.concurrent.TimeUnit; + public class MatrixMultiplicationBenchmarking { public static void main(String[] args) throws Exception { - org.openjdk.jmh.Main.main(args); + Options opt = new OptionsBuilder() + .include(MatrixMultiplicationBenchmarking.class.getSimpleName()) + .mode(Mode.AverageTime) + .forks(2) + .warmupIterations(5) + .measurementIterations(10) + .timeUnit(TimeUnit.MICROSECONDS) + .build(); + + new Runner(opt).run(); } -} + @Benchmark + public Object homemadeMatrixMultiplication(MatrixProvider matrixProvider) { + return HomemadeMatrix.multiplyMatrices(matrixProvider.getFirstMatrix(), matrixProvider.getSecondMatrix()); + } + + @Benchmark + public Object ejmlMatrixMultiplication(MatrixProvider matrixProvider) { + SimpleMatrix firstMatrix = new SimpleMatrix(matrixProvider.getFirstMatrix()); + SimpleMatrix secondMatrix = new SimpleMatrix(matrixProvider.getSecondMatrix()); + + return firstMatrix.mult(secondMatrix); + } + + @Benchmark + public Object apacheCommonsMatrixMultiplication(MatrixProvider matrixProvider) { + RealMatrix firstMatrix = new Array2DRowRealMatrix(matrixProvider.getFirstMatrix()); + RealMatrix secondMatrix = new Array2DRowRealMatrix(matrixProvider.getSecondMatrix()); + + return firstMatrix.multiply(secondMatrix); + } + + @Benchmark + public Object la4jMatrixMultiplication(MatrixProvider matrixProvider) { + Matrix firstMatrix = new Basic2DMatrix(matrixProvider.getFirstMatrix()); + Matrix secondMatrix = new Basic2DMatrix(matrixProvider.getSecondMatrix()); + + return firstMatrix.multiply(secondMatrix); + } + + @Benchmark + public Object nd4jMatrixMultiplication(MatrixProvider matrixProvider) { + INDArray firstMatrix = Nd4j.create(matrixProvider.getFirstMatrix()); + INDArray secondMatrix = Nd4j.create(matrixProvider.getSecondMatrix()); + + return firstMatrix.mmul(secondMatrix); + } + + @Benchmark + public Object coltMatrixMultiplication(MatrixProvider matrixProvider) { + DoubleFactory2D doubleFactory2D = DoubleFactory2D.dense; + + DoubleMatrix2D firstMatrix = doubleFactory2D.make(matrixProvider.getFirstMatrix()); + DoubleMatrix2D secondMatrix = doubleFactory2D.make(matrixProvider.getSecondMatrix()); + + Algebra algebra = new Algebra(); + return algebra.mult(firstMatrix, secondMatrix); + } + +} \ No newline at end of file diff --git a/java-math/src/test/java/com/baeldung/matrices/MatrixProvider.java b/java-math/src/test/java/com/baeldung/matrices/MatrixProvider.java new file mode 100644 index 0000000000..33bd074b6e --- /dev/null +++ b/java-math/src/test/java/com/baeldung/matrices/MatrixProvider.java @@ -0,0 +1,33 @@ +package com.baeldung.matrices; + +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; + +@State(Scope.Benchmark) +public class MatrixProvider { + private double[][] firstMatrix; + private double[][] secondMatrix; + + public MatrixProvider() { + firstMatrix = + new double[][] { + new double[] {1d, 5d}, + new double[] {2d, 3d}, + new double[] {1d ,7d} + }; + + secondMatrix = + new double[][] { + new double[] {1d, 2d, 3d, 7d}, + new double[] {5d, 2d, 8d, 1d} + }; + } + + public double[][] getFirstMatrix() { + return firstMatrix; + } + + public double[][] getSecondMatrix() { + return secondMatrix; + } +} \ No newline at end of file diff --git a/java-math/src/test/java/com/baeldung/matrices/apache/RealMatrixUnitTest.java b/java-math/src/test/java/com/baeldung/matrices/apache/RealMatrixUnitTest.java index 05944e7b3a..e7d99fbe3e 100644 --- a/java-math/src/test/java/com/baeldung/matrices/apache/RealMatrixUnitTest.java +++ b/java-math/src/test/java/com/baeldung/matrices/apache/RealMatrixUnitTest.java @@ -7,15 +7,10 @@ import org.openjdk.jmh.annotations.*; import static org.assertj.core.api.Assertions.assertThat; -@BenchmarkMode(Mode.AverageTime) -@Fork(value = 2) -@Warmup(iterations = 5) -@Measurement(iterations = 10) -public class RealMatrixUnitTest { +class RealMatrixUnitTest { @Test - @Benchmark - public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { RealMatrix firstMatrix = new Array2DRowRealMatrix( new double[][] { new double[] {1d, 5d}, @@ -43,5 +38,4 @@ public class RealMatrixUnitTest { assertThat(actual).isEqualTo(expected); } - } diff --git a/java-math/src/test/java/com/baeldung/matrices/colt/DoubleMatrix2DUnitTest.java b/java-math/src/test/java/com/baeldung/matrices/colt/DoubleMatrix2DUnitTest.java index fb4a419eb0..da66cd7d61 100644 --- a/java-math/src/test/java/com/baeldung/matrices/colt/DoubleMatrix2DUnitTest.java +++ b/java-math/src/test/java/com/baeldung/matrices/colt/DoubleMatrix2DUnitTest.java @@ -8,15 +8,10 @@ import org.openjdk.jmh.annotations.*; import static org.assertj.core.api.Assertions.assertThat; -@BenchmarkMode(Mode.AverageTime) -@Fork(value = 2) -@Warmup(iterations = 5) -@Measurement(iterations = 10) -public class DoubleMatrix2DUnitTest { +class DoubleMatrix2DUnitTest { @Test - @Benchmark - public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { DoubleFactory2D doubleFactory2D = DoubleFactory2D.dense; DoubleMatrix2D firstMatrix = doubleFactory2D.make( @@ -48,4 +43,4 @@ public class DoubleMatrix2DUnitTest { assertThat(actual).isEqualTo(expected); } -} +} \ No newline at end of file diff --git a/java-math/src/test/java/com/baeldung/matrices/ejml/SimpleMatrixUnitTest.java b/java-math/src/test/java/com/baeldung/matrices/ejml/SimpleMatrixUnitTest.java index b025266a1d..60381ece63 100644 --- a/java-math/src/test/java/com/baeldung/matrices/ejml/SimpleMatrixUnitTest.java +++ b/java-math/src/test/java/com/baeldung/matrices/ejml/SimpleMatrixUnitTest.java @@ -6,15 +6,10 @@ import org.openjdk.jmh.annotations.*; import static org.assertj.core.api.Assertions.assertThat; -@BenchmarkMode(Mode.AverageTime) -@Fork(value = 2) -@Warmup(iterations = 5) -@Measurement(iterations = 10) -public class SimpleMatrixUnitTest { +class SimpleMatrixUnitTest { @Test - @Benchmark - public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { SimpleMatrix firstMatrix = new SimpleMatrix( new double[][] { new double[] {1d, 5d}, @@ -43,4 +38,4 @@ public class SimpleMatrixUnitTest { assertThat(actual).matches(m -> m.isIdentical(expected, 0d)); } -} +} \ No newline at end of file diff --git a/java-math/src/test/java/com/baeldung/matrices/homemade/HomemadeMatrixUnitTest.java b/java-math/src/test/java/com/baeldung/matrices/homemade/HomemadeMatrixUnitTest.java index be9e483d5b..d1a062ee79 100644 --- a/java-math/src/test/java/com/baeldung/matrices/homemade/HomemadeMatrixUnitTest.java +++ b/java-math/src/test/java/com/baeldung/matrices/homemade/HomemadeMatrixUnitTest.java @@ -5,15 +5,10 @@ import org.openjdk.jmh.annotations.*; import static org.assertj.core.api.Assertions.assertThat; -@BenchmarkMode(Mode.AverageTime) -@Fork(value = 2) -@Warmup(iterations = 5) -@Measurement(iterations = 10) -public class HomemadeMatrixUnitTest { +class HomemadeMatrixUnitTest { @Test - @Benchmark - public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { double[][] firstMatrix = { new double[]{1d, 5d}, new double[]{2d, 3d}, @@ -55,4 +50,5 @@ public class HomemadeMatrixUnitTest { } return cell; } -} + +} \ No newline at end of file diff --git a/java-math/src/test/java/com/baeldung/matrices/la4j/Basic2DMatrixUnitTest.java b/java-math/src/test/java/com/baeldung/matrices/la4j/Basic2DMatrixUnitTest.java index afb84ff3db..01731a3dd5 100644 --- a/java-math/src/test/java/com/baeldung/matrices/la4j/Basic2DMatrixUnitTest.java +++ b/java-math/src/test/java/com/baeldung/matrices/la4j/Basic2DMatrixUnitTest.java @@ -7,15 +7,10 @@ import org.openjdk.jmh.annotations.*; import static org.assertj.core.api.Assertions.assertThat; -@BenchmarkMode(Mode.AverageTime) -@Fork(value = 2) -@Warmup(iterations = 5) -@Measurement(iterations = 10) -public class Basic2DMatrixUnitTest { +class Basic2DMatrixUnitTest { @Test - @Benchmark - public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { Matrix firstMatrix = new Basic2DMatrix( new double[][]{ new double[]{1d, 5d}, @@ -44,4 +39,4 @@ public class Basic2DMatrixUnitTest { assertThat(actual).isEqualTo(expected); } -} +} \ No newline at end of file diff --git a/java-math/src/test/java/com/baeldung/matrices/nd4j/INDArrayUnitTest.java b/java-math/src/test/java/com/baeldung/matrices/nd4j/INDArrayUnitTest.java index fb3030bccf..72ef60a571 100644 --- a/java-math/src/test/java/com/baeldung/matrices/nd4j/INDArrayUnitTest.java +++ b/java-math/src/test/java/com/baeldung/matrices/nd4j/INDArrayUnitTest.java @@ -7,14 +7,10 @@ import org.openjdk.jmh.annotations.*; import static org.assertj.core.api.Assertions.assertThat; -@BenchmarkMode(Mode.AverageTime) -@Fork(value = 2) -@Warmup(iterations = 5) -@Measurement(iterations = 10) -public class INDArrayUnitTest { +class INDArrayUnitTest { @Test - public void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { + void givenTwoMatrices_whenMultiply_thenMultiplicatedMatrix() { INDArray firstMatrix = Nd4j.create( new double[][]{ new double[]{1d, 5d}, @@ -43,4 +39,4 @@ public class INDArrayUnitTest { assertThat(actual).isEqualTo(expected); } -} +} \ No newline at end of file diff --git a/java-numbers-2/README.md b/java-numbers-2/README.md new file mode 100644 index 0000000000..52ffc822b9 --- /dev/null +++ b/java-numbers-2/README.md @@ -0,0 +1,2 @@ +## Relevant Articles +- [Lossy Conversion in Java](https://www.baeldung.com/java-lossy-conversion) diff --git a/java-strings-2/README.md b/java-strings-2/README.md index 55760bfac7..ad0a46fd96 100644 --- a/java-strings-2/README.md +++ b/java-strings-2/README.md @@ -23,3 +23,4 @@ - [Java Multi-line String](https://www.baeldung.com/java-multiline-string) - [Checking If a String Is a Repeated Substring](https://www.baeldung.com/java-repeated-substring) - [How to Reverse a String in Java](https://www.baeldung.com/java-reverse-string) +- [String toLowerCase and toUpperCase Methods in Java](https://www.baeldung.com/java-string-convert-case) diff --git a/jee-kotlin/README.md b/jee-kotlin/README.md index 7d843af9ea..43dcd992ca 100644 --- a/jee-kotlin/README.md +++ b/jee-kotlin/README.md @@ -1 +1,2 @@ ### Relevant Articles: +- [Java EE Application with Kotlin](https://www.baeldung.com/java-ee-kotlin-app) diff --git a/kotlin-quasar/README.md b/kotlin-quasar/README.md index b3b84e0446..b3693284f9 100644 --- a/kotlin-quasar/README.md +++ b/kotlin-quasar/README.md @@ -1,3 +1,4 @@ ### Relevant Articles - [Introduction to Quasar in Kotlin](https://www.baeldung.com/kotlin-quasar) +- [Advanced Quasar Usage for Kotlin](https://www.baeldung.com/kotlin-quasar-advanced) diff --git a/libraries-data-3/README.md b/libraries-data-3/README.md new file mode 100644 index 0000000000..7f939e7909 --- /dev/null +++ b/libraries-data-3/README.md @@ -0,0 +1,5 @@ +### Relevant articles +- [Parsing YAML with SnakeYAML](http://www.baeldung.com/java-snake-yaml) +- [Guide to JMapper](https://www.baeldung.com/jmapper) +- [An Introduction to SuanShu](https://www.baeldung.com/suanshu) +- [Intro to Derive4J](https://www.baeldung.com/derive4j) diff --git a/libraries-data-3/log4j.properties b/libraries-data-3/log4j.properties new file mode 100644 index 0000000000..2173c5d96f --- /dev/null +++ b/libraries-data-3/log4j.properties @@ -0,0 +1 @@ +log4j.rootLogger=INFO, stdout diff --git a/libraries-data-3/pom.xml b/libraries-data-3/pom.xml new file mode 100644 index 0000000000..f55701f51c --- /dev/null +++ b/libraries-data-3/pom.xml @@ -0,0 +1,55 @@ + + + + 4.0.0 + libraries-data-3 + libraries-data-3 + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.yaml + snakeyaml + ${snakeyaml.version} + + + com.googlecode.jmapper-framework + jmapper-core + ${jmapper.version} + + + com.numericalmethod + suanshu + ${suanshu.version} + + + org.derive4j + derive4j + ${derive4j.version} + + + + + + + nm-repo + Numerical Method's Maven Repository + http://repo.numericalmethod.com/maven/ + default + + + + + 1.21 + 1.6.0.1 + 4.0.0 + 1.1.0 + + \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/derive4j/adt/Either.java b/libraries-data-3/src/main/java/com/baeldung/derive4j/adt/Either.java similarity index 100% rename from libraries/src/main/java/com/baeldung/derive4j/adt/Either.java rename to libraries-data-3/src/main/java/com/baeldung/derive4j/adt/Either.java diff --git a/libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java b/libraries-data-3/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java similarity index 100% rename from libraries/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java rename to libraries-data-3/src/main/java/com/baeldung/derive4j/lazy/LazyRequest.java diff --git a/libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPRequest.java b/libraries-data-3/src/main/java/com/baeldung/derive4j/pattern/HTTPRequest.java similarity index 100% rename from libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPRequest.java rename to libraries-data-3/src/main/java/com/baeldung/derive4j/pattern/HTTPRequest.java diff --git a/libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPResponse.java b/libraries-data-3/src/main/java/com/baeldung/derive4j/pattern/HTTPResponse.java similarity index 100% rename from libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPResponse.java rename to libraries-data-3/src/main/java/com/baeldung/derive4j/pattern/HTTPResponse.java diff --git a/libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPServer.java b/libraries-data-3/src/main/java/com/baeldung/derive4j/pattern/HTTPServer.java similarity index 100% rename from libraries/src/main/java/com/baeldung/derive4j/pattern/HTTPServer.java rename to libraries-data-3/src/main/java/com/baeldung/derive4j/pattern/HTTPServer.java diff --git a/libraries-data/src/main/java/com/baeldung/jmapper/User.java b/libraries-data-3/src/main/java/com/baeldung/jmapper/User.java similarity index 100% rename from libraries-data/src/main/java/com/baeldung/jmapper/User.java rename to libraries-data-3/src/main/java/com/baeldung/jmapper/User.java diff --git a/libraries-data/src/main/java/com/baeldung/jmapper/UserDto.java b/libraries-data-3/src/main/java/com/baeldung/jmapper/UserDto.java similarity index 100% rename from libraries-data/src/main/java/com/baeldung/jmapper/UserDto.java rename to libraries-data-3/src/main/java/com/baeldung/jmapper/UserDto.java diff --git a/libraries-data/src/main/java/com/baeldung/jmapper/UserDto1.java b/libraries-data-3/src/main/java/com/baeldung/jmapper/UserDto1.java similarity index 100% rename from libraries-data/src/main/java/com/baeldung/jmapper/UserDto1.java rename to libraries-data-3/src/main/java/com/baeldung/jmapper/UserDto1.java diff --git a/libraries-data/src/main/java/com/baeldung/jmapper/relational/User.java b/libraries-data-3/src/main/java/com/baeldung/jmapper/relational/User.java similarity index 100% rename from libraries-data/src/main/java/com/baeldung/jmapper/relational/User.java rename to libraries-data-3/src/main/java/com/baeldung/jmapper/relational/User.java diff --git a/libraries-data/src/main/java/com/baeldung/jmapper/relational/UserDto1.java b/libraries-data-3/src/main/java/com/baeldung/jmapper/relational/UserDto1.java similarity index 100% rename from libraries-data/src/main/java/com/baeldung/jmapper/relational/UserDto1.java rename to libraries-data-3/src/main/java/com/baeldung/jmapper/relational/UserDto1.java diff --git a/libraries-data/src/main/java/com/baeldung/jmapper/relational/UserDto2.java b/libraries-data-3/src/main/java/com/baeldung/jmapper/relational/UserDto2.java similarity index 100% rename from libraries-data/src/main/java/com/baeldung/jmapper/relational/UserDto2.java rename to libraries-data-3/src/main/java/com/baeldung/jmapper/relational/UserDto2.java diff --git a/libraries/src/main/java/com/baeldung/snakeyaml/Address.java b/libraries-data-3/src/main/java/com/baeldung/snakeyaml/Address.java similarity index 100% rename from libraries/src/main/java/com/baeldung/snakeyaml/Address.java rename to libraries-data-3/src/main/java/com/baeldung/snakeyaml/Address.java diff --git a/libraries/src/main/java/com/baeldung/snakeyaml/Contact.java b/libraries-data-3/src/main/java/com/baeldung/snakeyaml/Contact.java similarity index 100% rename from libraries/src/main/java/com/baeldung/snakeyaml/Contact.java rename to libraries-data-3/src/main/java/com/baeldung/snakeyaml/Contact.java diff --git a/libraries/src/main/java/com/baeldung/snakeyaml/Customer.java b/libraries-data-3/src/main/java/com/baeldung/snakeyaml/Customer.java similarity index 100% rename from libraries/src/main/java/com/baeldung/snakeyaml/Customer.java rename to libraries-data-3/src/main/java/com/baeldung/snakeyaml/Customer.java diff --git a/libraries/src/main/java/com/baeldung/suanshu/SuanShuMath.java b/libraries-data-3/src/main/java/com/baeldung/suanshu/SuanShuMath.java similarity index 100% rename from libraries/src/main/java/com/baeldung/suanshu/SuanShuMath.java rename to libraries-data-3/src/main/java/com/baeldung/suanshu/SuanShuMath.java diff --git a/libraries-data-3/src/main/resources/user_jmapper.xml b/libraries-data-3/src/main/resources/user_jmapper.xml new file mode 100644 index 0000000000..f007de9f0a --- /dev/null +++ b/libraries-data-3/src/main/resources/user_jmapper.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/libraries-data-3/src/main/resources/user_jmapper1.xml b/libraries-data-3/src/main/resources/user_jmapper1.xml new file mode 100644 index 0000000000..abcfd77e1c --- /dev/null +++ b/libraries-data-3/src/main/resources/user_jmapper1.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/libraries-data-3/src/main/resources/user_jmapper2.xml b/libraries-data-3/src/main/resources/user_jmapper2.xml new file mode 100644 index 0000000000..1e708e14bf --- /dev/null +++ b/libraries-data-3/src/main/resources/user_jmapper2.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/src/test/java/com/baeldung/derive4j/adt/EitherUnitTest.java b/libraries-data-3/src/test/java/com/baeldung/derive4j/adt/EitherUnitTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/derive4j/adt/EitherUnitTest.java rename to libraries-data-3/src/test/java/com/baeldung/derive4j/adt/EitherUnitTest.java diff --git a/libraries/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java b/libraries-data-3/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java rename to libraries-data-3/src/test/java/com/baeldung/derive4j/lazy/LazyRequestUnitTest.java diff --git a/libraries/src/test/java/com/baeldung/derive4j/pattern/HTTPRequestUnitTest.java b/libraries-data-3/src/test/java/com/baeldung/derive4j/pattern/HTTPRequestUnitTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/derive4j/pattern/HTTPRequestUnitTest.java rename to libraries-data-3/src/test/java/com/baeldung/derive4j/pattern/HTTPRequestUnitTest.java diff --git a/libraries-data/src/test/java/com/baeldung/jmapper/JMapperIntegrationTest.java b/libraries-data-3/src/test/java/com/baeldung/jmapper/JMapperIntegrationTest.java similarity index 100% rename from libraries-data/src/test/java/com/baeldung/jmapper/JMapperIntegrationTest.java rename to libraries-data-3/src/test/java/com/baeldung/jmapper/JMapperIntegrationTest.java diff --git a/libraries-data/src/test/java/com/baeldung/jmapper/JMapperRelationalIntegrationTest.java b/libraries-data-3/src/test/java/com/baeldung/jmapper/JMapperRelationalIntegrationTest.java similarity index 100% rename from libraries-data/src/test/java/com/baeldung/jmapper/JMapperRelationalIntegrationTest.java rename to libraries-data-3/src/test/java/com/baeldung/jmapper/JMapperRelationalIntegrationTest.java diff --git a/libraries/src/test/java/com/baeldung/snakeyaml/JavaToYAMLSerializationUnitTest.java b/libraries-data-3/src/test/java/com/baeldung/snakeyaml/JavaToYAMLSerializationUnitTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/snakeyaml/JavaToYAMLSerializationUnitTest.java rename to libraries-data-3/src/test/java/com/baeldung/snakeyaml/JavaToYAMLSerializationUnitTest.java diff --git a/libraries/src/test/java/com/baeldung/snakeyaml/YAMLToJavaDeserialisationUnitTest.java b/libraries-data-3/src/test/java/com/baeldung/snakeyaml/YAMLToJavaDeserialisationUnitTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/snakeyaml/YAMLToJavaDeserialisationUnitTest.java rename to libraries-data-3/src/test/java/com/baeldung/snakeyaml/YAMLToJavaDeserialisationUnitTest.java diff --git a/libraries-data-3/src/test/resources/yaml/customer.yaml b/libraries-data-3/src/test/resources/yaml/customer.yaml new file mode 100644 index 0000000000..aa76141c7d --- /dev/null +++ b/libraries-data-3/src/test/resources/yaml/customer.yaml @@ -0,0 +1,3 @@ +firstName: "John" +lastName: "Doe" +age: 20 \ No newline at end of file diff --git a/libraries-data-3/src/test/resources/yaml/customer_with_contact_details.yaml b/libraries-data-3/src/test/resources/yaml/customer_with_contact_details.yaml new file mode 100644 index 0000000000..34563cbd21 --- /dev/null +++ b/libraries-data-3/src/test/resources/yaml/customer_with_contact_details.yaml @@ -0,0 +1,7 @@ +firstName: "John" +lastName: "Doe" +age: 31 +contactDetails: + - { type: "mobile", number: 123456789} + - { type: "landline", number: 456786868} + \ No newline at end of file diff --git a/libraries-data-3/src/test/resources/yaml/customer_with_contact_details_and_address.yaml b/libraries-data-3/src/test/resources/yaml/customer_with_contact_details_and_address.yaml new file mode 100644 index 0000000000..664afe8594 --- /dev/null +++ b/libraries-data-3/src/test/resources/yaml/customer_with_contact_details_and_address.yaml @@ -0,0 +1,13 @@ +firstName: "John" +lastName: "Doe" +age: 31 +contactDetails: + - type: "mobile" + number: 123456789 + - type: "landline" + number: 456786868 +homeAddress: + line: "Xyz, DEF Street" + city: "City Y" + state: "State Y" + zip: 345657 diff --git a/libraries-data-3/src/test/resources/yaml/customer_with_contact_details_and_tags.yaml b/libraries-data-3/src/test/resources/yaml/customer_with_contact_details_and_tags.yaml new file mode 100644 index 0000000000..145da256d9 --- /dev/null +++ b/libraries-data-3/src/test/resources/yaml/customer_with_contact_details_and_tags.yaml @@ -0,0 +1,6 @@ +firstName: "John" +lastName: "Doe" +age: 31 +contactDetails: + - !contact { type: "mobile", number: 123456789} + - !contact { type: "landline", number: 456786868} diff --git a/libraries-data-3/src/test/resources/yaml/customer_with_type.yaml b/libraries-data-3/src/test/resources/yaml/customer_with_type.yaml new file mode 100644 index 0000000000..6e13c26cea --- /dev/null +++ b/libraries-data-3/src/test/resources/yaml/customer_with_type.yaml @@ -0,0 +1,4 @@ +!!com.baeldung.snakeyaml.Customer +firstName: "John" +lastName: "Doe" +age: 20 \ No newline at end of file diff --git a/libraries-data-3/src/test/resources/yaml/customers.yaml b/libraries-data-3/src/test/resources/yaml/customers.yaml new file mode 100644 index 0000000000..23b9039c2e --- /dev/null +++ b/libraries-data-3/src/test/resources/yaml/customers.yaml @@ -0,0 +1,8 @@ +--- +firstName: "John" +lastName: "Doe" +age: 20 +--- +firstName: "Jack" +lastName: "Jones" +age: 25 \ No newline at end of file diff --git a/libraries-data/README.md b/libraries-data/README.md index 1ad7e94a1f..92c546c258 100644 --- a/libraries-data/README.md +++ b/libraries-data/README.md @@ -9,7 +9,6 @@ - [Introduction to JCache](http://www.baeldung.com/jcache) - [A Guide to Apache Ignite](http://www.baeldung.com/apache-ignite) - [Apache Ignite with Spring Data](http://www.baeldung.com/apache-ignite-spring-data) -- [Guide to JMapper](https://www.baeldung.com/jmapper) - [A Guide to Apache Crunch](https://www.baeldung.com/apache-crunch) - [Intro to Apache Storm](https://www.baeldung.com/apache-storm) - [Guide to Ebean ORM](https://www.baeldung.com/ebean-orm) diff --git a/libraries-data/pom.xml b/libraries-data/pom.xml index 88dcceafaa..e255236480 100644 --- a/libraries-data/pom.xml +++ b/libraries-data/pom.xml @@ -141,12 +141,7 @@ hazelcast ${hazelcast.version} - - - com.googlecode.jmapper-framework - jmapper-core - ${jmapper.version} - + org.apache.crunch @@ -460,7 +455,6 @@ 5.0.2 5.0.0-release 5.0.4 - 1.6.0.1 0.15.0 2.2.0 11.22.4 diff --git a/libraries-http/README.md b/libraries-http/README.md index dd8c6a5f67..d5eaed0736 100644 --- a/libraries-http/README.md +++ b/libraries-http/README.md @@ -5,3 +5,7 @@ - [A Guide to Google-Http-Client](http://www.baeldung.com/google-http-client) - [Asynchronous HTTP with async-http-client in Java](http://www.baeldung.com/async-http-client) - [WebSockets with AsyncHttpClient](http://www.baeldung.com/async-http-client-websockets) +- [Integrating Retrofit with RxJava](http://www.baeldung.com/retrofit-rxjava) +- [Introduction to Retrofit](http://www.baeldung.com/retrofit) +- [A Guide to Unirest](http://www.baeldung.com/unirest) +- [Creating REST Microservices with Javalin](http://www.baeldung.com/javalin-rest-microservices) \ No newline at end of file diff --git a/libraries-http/pom.xml b/libraries-http/pom.xml index 6006a93aef..44280d848c 100644 --- a/libraries-http/pom.xml +++ b/libraries-http/pom.xml @@ -44,6 +44,23 @@ ${googleclient.version} + + + com.squareup.retrofit2 + retrofit + ${retrofit.version} + + + com.squareup.retrofit2 + converter-gson + ${retrofit.version} + + + com.squareup.retrofit2 + adapter-rxjava + ${retrofit.version} + + org.asynchttpclient @@ -69,13 +86,52 @@ ${com.squareup.okhttp3.version} test + + + com.mashape.unirest + unirest-java + ${unirest.version} + + + + io.javalin + javalin + ${javalin.version} + + + com.squareup.okhttp3 + logging-interceptor + ${logging-interceptor.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + + commons-logging + commons-logging + + + + 4.5.3 + 2.9.8 3.6.2 3.14.2 1.23.0 2.2.0 + 2.3.0 + 1.4.9 + 1.6.0 + 3.9.0 diff --git a/libraries/src/main/java/com/baeldung/javalin/JavalinApp.java b/libraries-http/src/main/java/com/baeldung/javalin/JavalinApp.java similarity index 100% rename from libraries/src/main/java/com/baeldung/javalin/JavalinApp.java rename to libraries-http/src/main/java/com/baeldung/javalin/JavalinApp.java diff --git a/libraries/src/main/java/com/baeldung/javalin/User/User.java b/libraries-http/src/main/java/com/baeldung/javalin/User/User.java similarity index 100% rename from libraries/src/main/java/com/baeldung/javalin/User/User.java rename to libraries-http/src/main/java/com/baeldung/javalin/User/User.java diff --git a/libraries/src/main/java/com/baeldung/javalin/User/UserController.java b/libraries-http/src/main/java/com/baeldung/javalin/User/UserController.java similarity index 100% rename from libraries/src/main/java/com/baeldung/javalin/User/UserController.java rename to libraries-http/src/main/java/com/baeldung/javalin/User/UserController.java diff --git a/libraries/src/main/java/com/baeldung/javalin/User/UserDao.java b/libraries-http/src/main/java/com/baeldung/javalin/User/UserDao.java similarity index 100% rename from libraries/src/main/java/com/baeldung/javalin/User/UserDao.java rename to libraries-http/src/main/java/com/baeldung/javalin/User/UserDao.java diff --git a/libraries/src/main/java/com/baeldung/retrofit/basic/GitHubBasicApi.java b/libraries-http/src/main/java/com/baeldung/retrofit/basic/GitHubBasicApi.java similarity index 100% rename from libraries/src/main/java/com/baeldung/retrofit/basic/GitHubBasicApi.java rename to libraries-http/src/main/java/com/baeldung/retrofit/basic/GitHubBasicApi.java diff --git a/libraries/src/main/java/com/baeldung/retrofit/basic/GitHubBasicApp.java b/libraries-http/src/main/java/com/baeldung/retrofit/basic/GitHubBasicApp.java similarity index 100% rename from libraries/src/main/java/com/baeldung/retrofit/basic/GitHubBasicApp.java rename to libraries-http/src/main/java/com/baeldung/retrofit/basic/GitHubBasicApp.java diff --git a/libraries/src/main/java/com/baeldung/retrofit/basic/GitHubBasicService.java b/libraries-http/src/main/java/com/baeldung/retrofit/basic/GitHubBasicService.java similarity index 100% rename from libraries/src/main/java/com/baeldung/retrofit/basic/GitHubBasicService.java rename to libraries-http/src/main/java/com/baeldung/retrofit/basic/GitHubBasicService.java diff --git a/libraries/src/main/java/com/baeldung/retrofit/models/Contributor.java b/libraries-http/src/main/java/com/baeldung/retrofit/models/Contributor.java similarity index 100% rename from libraries/src/main/java/com/baeldung/retrofit/models/Contributor.java rename to libraries-http/src/main/java/com/baeldung/retrofit/models/Contributor.java diff --git a/libraries/src/main/java/com/baeldung/retrofit/models/Repository.java b/libraries-http/src/main/java/com/baeldung/retrofit/models/Repository.java similarity index 100% rename from libraries/src/main/java/com/baeldung/retrofit/models/Repository.java rename to libraries-http/src/main/java/com/baeldung/retrofit/models/Repository.java diff --git a/libraries/src/main/java/com/baeldung/retrofit/rx/GitHubRxApi.java b/libraries-http/src/main/java/com/baeldung/retrofit/rx/GitHubRxApi.java similarity index 100% rename from libraries/src/main/java/com/baeldung/retrofit/rx/GitHubRxApi.java rename to libraries-http/src/main/java/com/baeldung/retrofit/rx/GitHubRxApi.java diff --git a/libraries/src/main/java/com/baeldung/retrofit/rx/GitHubRxApp.java b/libraries-http/src/main/java/com/baeldung/retrofit/rx/GitHubRxApp.java similarity index 100% rename from libraries/src/main/java/com/baeldung/retrofit/rx/GitHubRxApp.java rename to libraries-http/src/main/java/com/baeldung/retrofit/rx/GitHubRxApp.java diff --git a/libraries/src/main/java/com/baeldung/retrofit/rx/GitHubRxService.java b/libraries-http/src/main/java/com/baeldung/retrofit/rx/GitHubRxService.java similarity index 100% rename from libraries/src/main/java/com/baeldung/retrofit/rx/GitHubRxService.java rename to libraries-http/src/main/java/com/baeldung/retrofit/rx/GitHubRxService.java diff --git a/libraries/src/main/java/com/baeldung/retrofitguide/GitHubServiceGenerator.java b/libraries-http/src/main/java/com/baeldung/retrofitguide/GitHubServiceGenerator.java similarity index 100% rename from libraries/src/main/java/com/baeldung/retrofitguide/GitHubServiceGenerator.java rename to libraries-http/src/main/java/com/baeldung/retrofitguide/GitHubServiceGenerator.java diff --git a/libraries/src/main/java/com/baeldung/retrofitguide/Main.java b/libraries-http/src/main/java/com/baeldung/retrofitguide/Main.java similarity index 100% rename from libraries/src/main/java/com/baeldung/retrofitguide/Main.java rename to libraries-http/src/main/java/com/baeldung/retrofitguide/Main.java diff --git a/libraries/src/main/java/com/baeldung/retrofitguide/User.java b/libraries-http/src/main/java/com/baeldung/retrofitguide/User.java similarity index 100% rename from libraries/src/main/java/com/baeldung/retrofitguide/User.java rename to libraries-http/src/main/java/com/baeldung/retrofitguide/User.java diff --git a/libraries/src/main/java/com/baeldung/retrofitguide/UserService.java b/libraries-http/src/main/java/com/baeldung/retrofitguide/UserService.java similarity index 100% rename from libraries/src/main/java/com/baeldung/retrofitguide/UserService.java rename to libraries-http/src/main/java/com/baeldung/retrofitguide/UserService.java diff --git a/libraries/src/test/java/com/baeldung/retrofit/basic/GitHubBasicApiLiveTest.java b/libraries-http/src/test/java/com/baeldung/retrofit/basic/GitHubBasicApiLiveTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/retrofit/basic/GitHubBasicApiLiveTest.java rename to libraries-http/src/test/java/com/baeldung/retrofit/basic/GitHubBasicApiLiveTest.java diff --git a/libraries/src/test/java/com/baeldung/retrofit/rx/GitHubRxLiveTest.java b/libraries-http/src/test/java/com/baeldung/retrofit/rx/GitHubRxLiveTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/retrofit/rx/GitHubRxLiveTest.java rename to libraries-http/src/test/java/com/baeldung/retrofit/rx/GitHubRxLiveTest.java diff --git a/libraries/src/test/java/com/baeldung/unirest/Article.java b/libraries-http/src/test/java/com/baeldung/unirest/Article.java similarity index 100% rename from libraries/src/test/java/com/baeldung/unirest/Article.java rename to libraries-http/src/test/java/com/baeldung/unirest/Article.java diff --git a/libraries/src/test/java/com/baeldung/unirest/HttpClientLiveTest.java b/libraries-http/src/test/java/com/baeldung/unirest/HttpClientLiveTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/unirest/HttpClientLiveTest.java rename to libraries-http/src/test/java/com/baeldung/unirest/HttpClientLiveTest.java diff --git a/libraries-security/README.md b/libraries-security/README.md index b9bbf11cdf..96f3fcdac6 100644 --- a/libraries-security/README.md +++ b/libraries-security/README.md @@ -3,3 +3,5 @@ - [Guide to ScribeJava](https://www.baeldung.com/scribejava) - [Guide to Passay](https://www.baeldung.com/java-passay) - [Guide to Google Tink](https://www.baeldung.com/google-tink) +- [Introduction to BouncyCastle with Java](https://www.baeldung.com/java-bouncy-castle) +- [Intro to Jasypt](https://www.baeldung.com/jasypt) diff --git a/libraries-security/pom.xml b/libraries-security/pom.xml index 17d57fe203..eb16575be8 100644 --- a/libraries-security/pom.xml +++ b/libraries-security/pom.xml @@ -25,6 +25,11 @@ spring-security-oauth2 ${spring-security-oauth2.version} + + org.springframework + spring-web + ${spring.version} + com.github.scribejava @@ -37,7 +42,16 @@ tink ${tink.version} - + + org.bouncycastle + bcprov-jdk15on + ${bouncycastle.version} + + + org.bouncycastle + bcpkix-jdk15on + ${bouncycastle.version} + junit junit @@ -54,6 +68,11 @@ cryptacular ${cryptacular.version} + + org.jasypt + jasypt + ${jasypt.version} + @@ -63,5 +82,8 @@ 1.3.1 1.2.2 1.2.2 + 1.9.2 + 1.58 + 4.3.8.RELEASE diff --git a/libraries/src/main/java/com/baeldung/bouncycastle/BouncyCastleCrypto.java b/libraries-security/src/main/java/com/baeldung/bouncycastle/BouncyCastleCrypto.java similarity index 98% rename from libraries/src/main/java/com/baeldung/bouncycastle/BouncyCastleCrypto.java rename to libraries-security/src/main/java/com/baeldung/bouncycastle/BouncyCastleCrypto.java index d7040407db..e351552c78 100644 --- a/libraries/src/main/java/com/baeldung/bouncycastle/BouncyCastleCrypto.java +++ b/libraries-security/src/main/java/com/baeldung/bouncycastle/BouncyCastleCrypto.java @@ -1,105 +1,105 @@ -package com.baeldung.bouncycastle; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.security.PrivateKey; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; - -import org.bouncycastle.asn1.ASN1InputStream; -import org.bouncycastle.asn1.cms.ContentInfo; -import org.bouncycastle.cert.X509CertificateHolder; -import org.bouncycastle.cert.jcajce.JcaCertStore; -import org.bouncycastle.cms.CMSAlgorithm; -import org.bouncycastle.cms.CMSEnvelopedData; -import org.bouncycastle.cms.CMSEnvelopedDataGenerator; -import org.bouncycastle.cms.CMSException; -import org.bouncycastle.cms.CMSProcessableByteArray; -import org.bouncycastle.cms.CMSSignedData; -import org.bouncycastle.cms.CMSSignedDataGenerator; -import org.bouncycastle.cms.CMSTypedData; -import org.bouncycastle.cms.KeyTransRecipientInformation; -import org.bouncycastle.cms.RecipientInformation; -import org.bouncycastle.cms.SignerInformation; -import org.bouncycastle.cms.SignerInformationStore; -import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; -import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; -import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder; -import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient; -import org.bouncycastle.cms.jcajce.JceKeyTransRecipient; -import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; -import org.bouncycastle.operator.ContentSigner; -import org.bouncycastle.operator.OperatorCreationException; -import org.bouncycastle.operator.OutputEncryptor; -import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; -import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; -import org.bouncycastle.util.Store; - -public class BouncyCastleCrypto { - - public static byte[] signData(byte[] data, final X509Certificate signingCertificate, final PrivateKey signingKey) throws CertificateEncodingException, OperatorCreationException, CMSException, IOException { - byte[] signedMessage = null; - List certList = new ArrayList(); - CMSTypedData cmsData = new CMSProcessableByteArray(data); - certList.add(signingCertificate); - Store certs = new JcaCertStore(certList); - CMSSignedDataGenerator cmsGenerator = new CMSSignedDataGenerator(); - ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256withRSA").build(signingKey); - cmsGenerator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()).build(contentSigner, signingCertificate)); - cmsGenerator.addCertificates(certs); - CMSSignedData cms = cmsGenerator.generate(cmsData, true); - signedMessage = cms.getEncoded(); - return signedMessage; - } - - public static boolean verifSignData(final byte[] signedData) throws CMSException, IOException, OperatorCreationException, CertificateException { - ByteArrayInputStream bIn = new ByteArrayInputStream(signedData); - ASN1InputStream aIn = new ASN1InputStream(bIn); - CMSSignedData s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); - aIn.close(); - bIn.close(); - Store certs = s.getCertificates(); - SignerInformationStore signers = s.getSignerInfos(); - Collection c = signers.getSigners(); - SignerInformation signer = c.iterator().next(); - Collection certCollection = certs.getMatches(signer.getSID()); - Iterator certIt = certCollection.iterator(); - X509CertificateHolder certHolder = certIt.next(); - boolean verifResult = signer.verify(new JcaSimpleSignerInfoVerifierBuilder().build(certHolder)); - if (!verifResult) { - return false; - } - return true; - } - - public static byte[] encryptData(final byte[] data, X509Certificate encryptionCertificate) throws CertificateEncodingException, CMSException, IOException { - byte[] encryptedData = null; - if (null != data && null != encryptionCertificate) { - CMSEnvelopedDataGenerator cmsEnvelopedDataGenerator = new CMSEnvelopedDataGenerator(); - JceKeyTransRecipientInfoGenerator jceKey = new JceKeyTransRecipientInfoGenerator(encryptionCertificate); - cmsEnvelopedDataGenerator.addRecipientInfoGenerator(jceKey); - CMSTypedData msg = new CMSProcessableByteArray(data); - OutputEncryptor encryptor = new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider("BC").build(); - CMSEnvelopedData cmsEnvelopedData = cmsEnvelopedDataGenerator.generate(msg, encryptor); - encryptedData = cmsEnvelopedData.getEncoded(); - } - return encryptedData; - } - - public static byte[] decryptData(final byte[] encryptedData, final PrivateKey decryptionKey) throws CMSException { - byte[] decryptedData = null; - if (null != encryptedData && null != decryptionKey) { - CMSEnvelopedData envelopedData = new CMSEnvelopedData(encryptedData); - Collection recip = envelopedData.getRecipientInfos().getRecipients(); - KeyTransRecipientInformation recipientInfo = (KeyTransRecipientInformation) recip.iterator().next(); - JceKeyTransRecipient recipient = new JceKeyTransEnvelopedRecipient(decryptionKey); - decryptedData = recipientInfo.getContent(recipient); - } - return decryptedData; - } -} +package com.baeldung.bouncycastle; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.security.PrivateKey; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; + +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.cms.ContentInfo; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.jcajce.JcaCertStore; +import org.bouncycastle.cms.CMSAlgorithm; +import org.bouncycastle.cms.CMSEnvelopedData; +import org.bouncycastle.cms.CMSEnvelopedDataGenerator; +import org.bouncycastle.cms.CMSException; +import org.bouncycastle.cms.CMSProcessableByteArray; +import org.bouncycastle.cms.CMSSignedData; +import org.bouncycastle.cms.CMSSignedDataGenerator; +import org.bouncycastle.cms.CMSTypedData; +import org.bouncycastle.cms.KeyTransRecipientInformation; +import org.bouncycastle.cms.RecipientInformation; +import org.bouncycastle.cms.SignerInformation; +import org.bouncycastle.cms.SignerInformationStore; +import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder; +import org.bouncycastle.cms.jcajce.JcaSimpleSignerInfoVerifierBuilder; +import org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder; +import org.bouncycastle.cms.jcajce.JceKeyTransEnvelopedRecipient; +import org.bouncycastle.cms.jcajce.JceKeyTransRecipient; +import org.bouncycastle.cms.jcajce.JceKeyTransRecipientInfoGenerator; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.operator.OutputEncryptor; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; +import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder; +import org.bouncycastle.util.Store; + +public class BouncyCastleCrypto { + + public static byte[] signData(byte[] data, final X509Certificate signingCertificate, final PrivateKey signingKey) throws CertificateEncodingException, OperatorCreationException, CMSException, IOException { + byte[] signedMessage = null; + List certList = new ArrayList(); + CMSTypedData cmsData = new CMSProcessableByteArray(data); + certList.add(signingCertificate); + Store certs = new JcaCertStore(certList); + CMSSignedDataGenerator cmsGenerator = new CMSSignedDataGenerator(); + ContentSigner contentSigner = new JcaContentSignerBuilder("SHA256withRSA").build(signingKey); + cmsGenerator.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().setProvider("BC").build()).build(contentSigner, signingCertificate)); + cmsGenerator.addCertificates(certs); + CMSSignedData cms = cmsGenerator.generate(cmsData, true); + signedMessage = cms.getEncoded(); + return signedMessage; + } + + public static boolean verifSignData(final byte[] signedData) throws CMSException, IOException, OperatorCreationException, CertificateException { + ByteArrayInputStream bIn = new ByteArrayInputStream(signedData); + ASN1InputStream aIn = new ASN1InputStream(bIn); + CMSSignedData s = new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + aIn.close(); + bIn.close(); + Store certs = s.getCertificates(); + SignerInformationStore signers = s.getSignerInfos(); + Collection c = signers.getSigners(); + SignerInformation signer = c.iterator().next(); + Collection certCollection = certs.getMatches(signer.getSID()); + Iterator certIt = certCollection.iterator(); + X509CertificateHolder certHolder = certIt.next(); + boolean verifResult = signer.verify(new JcaSimpleSignerInfoVerifierBuilder().build(certHolder)); + if (!verifResult) { + return false; + } + return true; + } + + public static byte[] encryptData(final byte[] data, X509Certificate encryptionCertificate) throws CertificateEncodingException, CMSException, IOException { + byte[] encryptedData = null; + if (null != data && null != encryptionCertificate) { + CMSEnvelopedDataGenerator cmsEnvelopedDataGenerator = new CMSEnvelopedDataGenerator(); + JceKeyTransRecipientInfoGenerator jceKey = new JceKeyTransRecipientInfoGenerator(encryptionCertificate); + cmsEnvelopedDataGenerator.addRecipientInfoGenerator(jceKey); + CMSTypedData msg = new CMSProcessableByteArray(data); + OutputEncryptor encryptor = new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES128_CBC).setProvider("BC").build(); + CMSEnvelopedData cmsEnvelopedData = cmsEnvelopedDataGenerator.generate(msg, encryptor); + encryptedData = cmsEnvelopedData.getEncoded(); + } + return encryptedData; + } + + public static byte[] decryptData(final byte[] encryptedData, final PrivateKey decryptionKey) throws CMSException { + byte[] decryptedData = null; + if (null != encryptedData && null != decryptionKey) { + CMSEnvelopedData envelopedData = new CMSEnvelopedData(encryptedData); + Collection recip = envelopedData.getRecipientInfos().getRecipients(); + KeyTransRecipientInformation recipientInfo = (KeyTransRecipientInformation) recip.iterator().next(); + JceKeyTransRecipient recipient = new JceKeyTransEnvelopedRecipient(decryptionKey); + decryptedData = recipientInfo.getContent(recipient); + } + return decryptedData; + } +} diff --git a/libraries-security/src/main/resources/Baeldung.cer b/libraries-security/src/main/resources/Baeldung.cer new file mode 100644 index 0000000000..72d0918424 --- /dev/null +++ b/libraries-security/src/main/resources/Baeldung.cer @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDPjCCAiagAwIBAgIJAPvd1gx14C3CMA0GCSqGSIb3DQEBBQUAMEcxCzAJBgNV +BAYTAk1BMRAwDgYDVQQIEwdNb3JvY2NvMRMwEQYDVQQHEwpDYXNhYmxhbmNhMREw +DwYDVQQDEwhCYWVsZHVuZzAeFw0xNzEwMTIxMDQzMTRaFw0yNzEwMTMxMDQzMTRa +MEcxCzAJBgNVBAYTAk1BMRAwDgYDVQQIEwdNb3JvY2NvMRMwEQYDVQQHEwpDYXNh +YmxhbmNhMREwDwYDVQQDEwhCYWVsZHVuZzCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAMyi5GmOeN4QaH/CP5gSOyHX8znb5TDHWV8wc+ZT7kNU8zt5tGMh +jozK6hax155/6tOsBDR0rSYBhL+Dm/+uCVS7qOlRHhf6cNGtzGF1gnNJB2WjI8oM +AYm24xpLj1WphKUwKrn3nTMPnQup5OoNAMYl99flANrRYVjjxrLQvDZDUio6Iujr +CZ2TtXGM0g/gP++28KT7g1KlUui3xtB0u33wx7UN8Fix3JmjOaPHGwxGpwP3VGSj +fs8cuhqVwRQaZpCOoHU/P8wpXKw80sSdhz+SRueMPtVYqK0CiLL5/O0h0Y3le4IV +whgg3KG1iTGOWn60UMFn1EYmQ18k5Nsma6UCAwEAAaMtMCswCQYDVR0TBAIwADAR +BglghkgBhvhCAQEEBAMCBPAwCwYDVR0PBAQDAgUgMA0GCSqGSIb3DQEBBQUAA4IB +AQC8DDBmJ3p4xytxBiE0s4p1715WT6Dm/QJHp0XC0hkSoyZKDh+XVmrzm+J3SiW1 +vpswb5hLgPo040YX9jnDmgOD+TpleTuKHxZRYj92UYWmdjkWLVtFMcvOh+gxBiAP +pHIqZsqo8lfcyAuh8Jx834IXbknfCUtERDLG/rU9P/3XJhrM2GC5qPQznrW4EYhU +CGPyIJXmvATMVvXMWCtfogAL+n42vjYXQXZoAWomHhLHoNbSJUErnNdWDOh4WoJt +XJCxA6U5LSBplqb3wB2hUTqw+0admKltvmy+KA1PD7OxoGiY7V544zeGqJam1qxU +ia7y5BL6uOa/4ShSV8pcJDYz +-----END CERTIFICATE----- diff --git a/libraries/src/test/java/com/baeldung/bouncycastle/BouncyCastleLiveTest.java b/libraries-security/src/test/java/com/baeldung/bouncycastle/BouncyCastleLiveTest.java similarity index 97% rename from libraries/src/test/java/com/baeldung/bouncycastle/BouncyCastleLiveTest.java rename to libraries-security/src/test/java/com/baeldung/bouncycastle/BouncyCastleLiveTest.java index 009119d97a..37e8e5f6ba 100644 --- a/libraries/src/test/java/com/baeldung/bouncycastle/BouncyCastleLiveTest.java +++ b/libraries-security/src/test/java/com/baeldung/bouncycastle/BouncyCastleLiveTest.java @@ -1,50 +1,50 @@ -package com.baeldung.bouncycastle; - -import static org.junit.Assert.assertTrue; - -import java.io.FileInputStream; -import java.io.IOException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.security.PrivateKey; -import java.security.Security; -import java.security.UnrecoverableKeyException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; - -import org.bouncycastle.cms.CMSException; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.bouncycastle.operator.OperatorCreationException; -import org.junit.Test; - -public class BouncyCastleLiveTest { - - String certificatePath = "src/main/resources/Baeldung.cer"; - String privateKeyPath = "src/main/resources/Baeldung.p12"; - char[] p12Password = "password".toCharArray(); - char[] keyPassword = "password".toCharArray(); - - @Test - public void givenCryptographicResource_whenOperationSuccess_returnTrue() throws CertificateException, NoSuchProviderException, NoSuchAlgorithmException, IOException, KeyStoreException, UnrecoverableKeyException, CMSException, OperatorCreationException { - Security.addProvider(new BouncyCastleProvider()); - - CertificateFactory certFactory = CertificateFactory.getInstance("X.509", "BC"); - X509Certificate certificate = (X509Certificate) certFactory.generateCertificate(new FileInputStream(certificatePath)); - KeyStore keystore = KeyStore.getInstance("PKCS12"); - keystore.load(new FileInputStream(privateKeyPath), p12Password); - PrivateKey privateKey = (PrivateKey) keystore.getKey("baeldung", keyPassword); - String secretMessage = "My password is 123456Seven"; - System.out.println("Original Message : " + secretMessage); - byte[] stringToEncrypt = secretMessage.getBytes(); - byte[] encryptedData = BouncyCastleCrypto.encryptData(stringToEncrypt, certificate); - byte[] rawData = BouncyCastleCrypto.decryptData(encryptedData, privateKey); - String decryptedMessage = new String(rawData); - assertTrue(decryptedMessage.equals(secretMessage)); - byte[] signedData = BouncyCastleCrypto.signData(rawData, certificate, privateKey); - Boolean check = BouncyCastleCrypto.verifSignData(signedData); - assertTrue(check); - } -} +package com.baeldung.bouncycastle; + +import static org.junit.Assert.assertTrue; + +import java.io.FileInputStream; +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.Security; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; + +import org.bouncycastle.cms.CMSException; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.operator.OperatorCreationException; +import org.junit.Test; + +public class BouncyCastleLiveTest { + + String certificatePath = "src/main/resources/Baeldung.cer"; + String privateKeyPath = "src/main/resources/Baeldung.p12"; + char[] p12Password = "password".toCharArray(); + char[] keyPassword = "password".toCharArray(); + + @Test + public void givenCryptographicResource_whenOperationSuccess_returnTrue() throws CertificateException, NoSuchProviderException, NoSuchAlgorithmException, IOException, KeyStoreException, UnrecoverableKeyException, CMSException, OperatorCreationException { + Security.addProvider(new BouncyCastleProvider()); + + CertificateFactory certFactory = CertificateFactory.getInstance("X.509", "BC"); + X509Certificate certificate = (X509Certificate) certFactory.generateCertificate(new FileInputStream(certificatePath)); + KeyStore keystore = KeyStore.getInstance("PKCS12"); + keystore.load(new FileInputStream(privateKeyPath), p12Password); + PrivateKey privateKey = (PrivateKey) keystore.getKey("baeldung", keyPassword); + String secretMessage = "My password is 123456Seven"; + System.out.println("Original Message : " + secretMessage); + byte[] stringToEncrypt = secretMessage.getBytes(); + byte[] encryptedData = BouncyCastleCrypto.encryptData(stringToEncrypt, certificate); + byte[] rawData = BouncyCastleCrypto.decryptData(encryptedData, privateKey); + String decryptedMessage = new String(rawData); + assertTrue(decryptedMessage.equals(secretMessage)); + byte[] signedData = BouncyCastleCrypto.signData(rawData, certificate, privateKey); + Boolean check = BouncyCastleCrypto.verifSignData(signedData); + assertTrue(check); + } +} diff --git a/libraries/src/test/java/com/baeldung/jasypt/JasyptUnitTest.java b/libraries-security/src/test/java/com/baeldung/jasypt/JasyptUnitTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/jasypt/JasyptUnitTest.java rename to libraries-security/src/test/java/com/baeldung/jasypt/JasyptUnitTest.java diff --git a/libraries-security/src/test/java/com/baeldung/tink/TinkUnitTest.java b/libraries-security/src/test/java/com/baeldung/tink/TinkLiveTest.java similarity index 96% rename from libraries-security/src/test/java/com/baeldung/tink/TinkUnitTest.java rename to libraries-security/src/test/java/com/baeldung/tink/TinkLiveTest.java index b98c698016..c4bd487457 100644 --- a/libraries-security/src/test/java/com/baeldung/tink/TinkUnitTest.java +++ b/libraries-security/src/test/java/com/baeldung/tink/TinkLiveTest.java @@ -18,7 +18,9 @@ import org.junit.Test; import java.security.GeneralSecurityException; -public class TinkUnitTest { +public class TinkLiveTest { + + //need to download policy files and put them into ${java.home}/jre/lib/security/ private static final String PLAINTEXT = "BAELDUNG"; private static final String DATA = "TINK"; diff --git a/libraries-testing/README.md b/libraries-testing/README.md new file mode 100644 index 0000000000..6b25a3b875 --- /dev/null +++ b/libraries-testing/README.md @@ -0,0 +1,8 @@ +### Relevant articles + +- [Introduction to Serenity BDD](http://www.baeldung.com/serenity-bdd) +- [Introduction to JSONassert](http://www.baeldung.com/jsonassert) +- [Serenity BDD and Screenplay](http://www.baeldung.com/serenity-screenplay) +- [Serenity BDD with Spring and JBehave](http://www.baeldung.com/serenity-spring-jbehave) +- [Introduction to Awaitlity](http://www.baeldung.com/awaitlity-testing) +- [Introduction to Hoverfly in Java](http://www.baeldung.com/hoverfly) \ No newline at end of file diff --git a/libraries-testing/log4j.properties b/libraries-testing/log4j.properties new file mode 100644 index 0000000000..ed367509d1 --- /dev/null +++ b/libraries-testing/log4j.properties @@ -0,0 +1,5 @@ +log4j.rootLogger=INFO, stdout +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n \ No newline at end of file diff --git a/libraries-testing/pom.xml b/libraries-testing/pom.xml new file mode 100644 index 0000000000..8f7a27bbfa --- /dev/null +++ b/libraries-testing/pom.xml @@ -0,0 +1,170 @@ + + + + 4.0.0 + libraries-testing + libraries-testing + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + net.serenity-bdd + serenity-core + ${serenity.version} + test + + + org.asciidoctor + asciidoctorj + + + + + net.serenity-bdd + serenity-junit + ${serenity.version} + test + + + net.serenity-bdd + serenity-jbehave + ${serenity.jbehave.version} + test + + + net.serenity-bdd + serenity-rest-assured + ${serenity.version} + test + + + net.serenity-bdd + serenity-jira-requirements-provider + ${serenity.jira.version} + test + + + net.serenity-bdd + serenity-spring + ${serenity.version} + test + + + org.springframework + spring-test + + + + + net.serenity-bdd + serenity-screenplay + ${serenity.version} + test + + + net.serenity-bdd + serenity-screenplay-webdriver + ${serenity.version} + test + + + org.skyscreamer + jsonassert + ${jsonassert.version} + + + org.awaitility + awaitility + ${awaitility.version} + test + + + org.awaitility + awaitility-proxy + ${awaitility.version} + test + + + io.specto + hoverfly-java + ${hoverfly-java.version} + + + org.springframework + spring-web + ${spring.version} + + + io.rest-assured + spring-mock-mvc + ${spring-mock-mvc.version} + test + + + org.assertj + assertj-core + ${assertj.version} + + + + net.serenity-bdd + serenity-core + ${serenity.version} + test + + + org.asciidoctor + asciidoctorj + + + + + org.asciidoctor + asciidoctor-maven-plugin + 1.5.7.1 + + + + + + + + + net.serenity-bdd.maven.plugins + serenity-maven-plugin + ${serenity.plugin.version} + + + serenity-reports + post-integration-test + + aggregate + + + + + + + + + + 1.9.26 + 1.41.0 + 1.9.0 + 1.9.27 + 1.5.0 + 3.0.0 + 0.8.1 + 4.3.8.RELEASE + 3.0.3 + 3.6.2 + + + diff --git a/libraries-testing/serenity.properties b/libraries-testing/serenity.properties new file mode 100644 index 0000000000..c77df9c0f7 --- /dev/null +++ b/libraries-testing/serenity.properties @@ -0,0 +1,4 @@ +jira.url= +jira.project= +jira.username= +jira.password= \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/awaitility/AsyncService.java b/libraries-testing/src/main/java/com/baeldung/awaitility/AsyncService.java similarity index 100% rename from libraries/src/main/java/com/baeldung/awaitility/AsyncService.java rename to libraries-testing/src/main/java/com/baeldung/awaitility/AsyncService.java diff --git a/libraries/src/main/java/com/baeldung/serenity/github/GitHubUser.java b/libraries-testing/src/main/java/com/baeldung/serenity/github/GitHubUser.java similarity index 100% rename from libraries/src/main/java/com/baeldung/serenity/github/GitHubUser.java rename to libraries-testing/src/main/java/com/baeldung/serenity/github/GitHubUser.java diff --git a/libraries/src/main/java/com/baeldung/serenity/membership/Commodity.java b/libraries-testing/src/main/java/com/baeldung/serenity/membership/Commodity.java similarity index 100% rename from libraries/src/main/java/com/baeldung/serenity/membership/Commodity.java rename to libraries-testing/src/main/java/com/baeldung/serenity/membership/Commodity.java diff --git a/libraries/src/main/java/com/baeldung/serenity/membership/Member.java b/libraries-testing/src/main/java/com/baeldung/serenity/membership/Member.java similarity index 100% rename from libraries/src/main/java/com/baeldung/serenity/membership/Member.java rename to libraries-testing/src/main/java/com/baeldung/serenity/membership/Member.java diff --git a/libraries/src/main/java/com/baeldung/serenity/membership/MemberGrade.java b/libraries-testing/src/main/java/com/baeldung/serenity/membership/MemberGrade.java similarity index 100% rename from libraries/src/main/java/com/baeldung/serenity/membership/MemberGrade.java rename to libraries-testing/src/main/java/com/baeldung/serenity/membership/MemberGrade.java diff --git a/libraries/src/main/java/com/baeldung/serenity/spring/AdderController.java b/libraries-testing/src/main/java/com/baeldung/serenity/spring/AdderController.java similarity index 100% rename from libraries/src/main/java/com/baeldung/serenity/spring/AdderController.java rename to libraries-testing/src/main/java/com/baeldung/serenity/spring/AdderController.java diff --git a/libraries/src/main/java/com/baeldung/serenity/spring/AdderService.java b/libraries-testing/src/main/java/com/baeldung/serenity/spring/AdderService.java similarity index 100% rename from libraries/src/main/java/com/baeldung/serenity/spring/AdderService.java rename to libraries-testing/src/main/java/com/baeldung/serenity/spring/AdderService.java diff --git a/libraries/src/main/java/com/baeldung/serenity/spring/PlainAdderController.java b/libraries-testing/src/main/java/com/baeldung/serenity/spring/PlainAdderController.java similarity index 100% rename from libraries/src/main/java/com/baeldung/serenity/spring/PlainAdderController.java rename to libraries-testing/src/main/java/com/baeldung/serenity/spring/PlainAdderController.java diff --git a/libraries/src/test/java/com/baeldung/awaitility/AsyncServiceLongRunningManualTest.java b/libraries-testing/src/test/java/com/baeldung/awaitility/AsyncServiceLongRunningManualTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/awaitility/AsyncServiceLongRunningManualTest.java rename to libraries-testing/src/test/java/com/baeldung/awaitility/AsyncServiceLongRunningManualTest.java diff --git a/libraries/src/test/java/com/baeldung/hoverfly/HoverflyApiLiveTest.java b/libraries-testing/src/test/java/com/baeldung/hoverfly/HoverflyApiLiveTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/hoverfly/HoverflyApiLiveTest.java rename to libraries-testing/src/test/java/com/baeldung/hoverfly/HoverflyApiLiveTest.java diff --git a/libraries/src/test/java/com/baeldung/jsonassert/JsonAssertUnitTest.java b/libraries-testing/src/test/java/com/baeldung/jsonassert/JsonAssertUnitTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/jsonassert/JsonAssertUnitTest.java rename to libraries-testing/src/test/java/com/baeldung/jsonassert/JsonAssertUnitTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/GithubUserProfilePayloadIntegrationTest.java b/libraries-testing/src/test/java/com/baeldung/serenity/GithubUserProfilePayloadIntegrationTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/GithubUserProfilePayloadIntegrationTest.java rename to libraries-testing/src/test/java/com/baeldung/serenity/GithubUserProfilePayloadIntegrationTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/GoogleSearchLiveTest.java b/libraries-testing/src/test/java/com/baeldung/serenity/GoogleSearchLiveTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/GoogleSearchLiveTest.java rename to libraries-testing/src/test/java/com/baeldung/serenity/GoogleSearchLiveTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/GoogleSearchPageObjectLiveTest.java b/libraries-testing/src/test/java/com/baeldung/serenity/GoogleSearchPageObjectLiveTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/GoogleSearchPageObjectLiveTest.java rename to libraries-testing/src/test/java/com/baeldung/serenity/GoogleSearchPageObjectLiveTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/GoogleSearchScreenplayLiveTest.java b/libraries-testing/src/test/java/com/baeldung/serenity/GoogleSearchScreenplayLiveTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/GoogleSearchScreenplayLiveTest.java rename to libraries-testing/src/test/java/com/baeldung/serenity/GoogleSearchScreenplayLiveTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/MemberStatusIntegrationTest.java b/libraries-testing/src/test/java/com/baeldung/serenity/MemberStatusIntegrationTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/MemberStatusIntegrationTest.java rename to libraries-testing/src/test/java/com/baeldung/serenity/MemberStatusIntegrationTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/github/GithubRestAssuredUserAPISteps.java b/libraries-testing/src/test/java/com/baeldung/serenity/github/GithubRestAssuredUserAPISteps.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/github/GithubRestAssuredUserAPISteps.java rename to libraries-testing/src/test/java/com/baeldung/serenity/github/GithubRestAssuredUserAPISteps.java diff --git a/libraries/src/test/java/com/baeldung/serenity/github/GithubRestUserAPISteps.java b/libraries-testing/src/test/java/com/baeldung/serenity/github/GithubRestUserAPISteps.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/github/GithubRestUserAPISteps.java rename to libraries-testing/src/test/java/com/baeldung/serenity/github/GithubRestUserAPISteps.java diff --git a/libraries/src/test/java/com/baeldung/serenity/github/GithubUserProfilePayloadStepDefinitions.java b/libraries-testing/src/test/java/com/baeldung/serenity/github/GithubUserProfilePayloadStepDefinitions.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/github/GithubUserProfilePayloadStepDefinitions.java rename to libraries-testing/src/test/java/com/baeldung/serenity/github/GithubUserProfilePayloadStepDefinitions.java diff --git a/libraries/src/test/java/com/baeldung/serenity/membership/MemberStatusSteps.java b/libraries-testing/src/test/java/com/baeldung/serenity/membership/MemberStatusSteps.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/membership/MemberStatusSteps.java rename to libraries-testing/src/test/java/com/baeldung/serenity/membership/MemberStatusSteps.java diff --git a/libraries/src/test/java/com/baeldung/serenity/pageobjects/GoogleSearchPageObject.java b/libraries-testing/src/test/java/com/baeldung/serenity/pageobjects/GoogleSearchPageObject.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/pageobjects/GoogleSearchPageObject.java rename to libraries-testing/src/test/java/com/baeldung/serenity/pageobjects/GoogleSearchPageObject.java diff --git a/libraries/src/test/java/com/baeldung/serenity/screenplay/GoogleSearchPage.java b/libraries-testing/src/test/java/com/baeldung/serenity/screenplay/GoogleSearchPage.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/screenplay/GoogleSearchPage.java rename to libraries-testing/src/test/java/com/baeldung/serenity/screenplay/GoogleSearchPage.java diff --git a/libraries/src/test/java/com/baeldung/serenity/screenplay/GoogleSearchResults.java b/libraries-testing/src/test/java/com/baeldung/serenity/screenplay/GoogleSearchResults.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/screenplay/GoogleSearchResults.java rename to libraries-testing/src/test/java/com/baeldung/serenity/screenplay/GoogleSearchResults.java diff --git a/libraries/src/test/java/com/baeldung/serenity/screenplay/SearchForKeyword.java b/libraries-testing/src/test/java/com/baeldung/serenity/screenplay/SearchForKeyword.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/screenplay/SearchForKeyword.java rename to libraries-testing/src/test/java/com/baeldung/serenity/screenplay/SearchForKeyword.java diff --git a/libraries/src/test/java/com/baeldung/serenity/screenplay/StartWith.java b/libraries-testing/src/test/java/com/baeldung/serenity/screenplay/StartWith.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/screenplay/StartWith.java rename to libraries-testing/src/test/java/com/baeldung/serenity/screenplay/StartWith.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/AdderClassDirtiesContextIntegrationTest.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderClassDirtiesContextIntegrationTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/AdderClassDirtiesContextIntegrationTest.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderClassDirtiesContextIntegrationTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/AdderIntegrationTest.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderIntegrationTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/AdderIntegrationTest.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderIntegrationTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextDependencyWorkaroundIntegrationTest.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextDependencyWorkaroundIntegrationTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextDependencyWorkaroundIntegrationTest.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextDependencyWorkaroundIntegrationTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextInitWorkaroundIntegrationTest.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextInitWorkaroundIntegrationTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextInitWorkaroundIntegrationTest.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextInitWorkaroundIntegrationTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextIntegrationTest.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextIntegrationTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextIntegrationTest.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderMethodDirtiesContextIntegrationTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/AdderMethodRuleIntegrationTest.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderMethodRuleIntegrationTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/AdderMethodRuleIntegrationTest.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderMethodRuleIntegrationTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/AdderMockMvcIntegrationTest.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderMockMvcIntegrationTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/AdderMockMvcIntegrationTest.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderMockMvcIntegrationTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/AdderServiceIntegrationTest.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderServiceIntegrationTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/AdderServiceIntegrationTest.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderServiceIntegrationTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/AdderSpringSerenityRunnerIntegrationTest.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderSpringSerenityRunnerIntegrationTest.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/AdderSpringSerenityRunnerIntegrationTest.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/AdderSpringSerenityRunnerIntegrationTest.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/RandomNumberUtil.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/RandomNumberUtil.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/RandomNumberUtil.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/RandomNumberUtil.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/steps/AdderConstructorDependencySteps.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/steps/AdderConstructorDependencySteps.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/steps/AdderConstructorDependencySteps.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/steps/AdderConstructorDependencySteps.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/steps/AdderRestSteps.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/steps/AdderRestSteps.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/steps/AdderRestSteps.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/steps/AdderRestSteps.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/steps/AdderServiceSteps.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/steps/AdderServiceSteps.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/steps/AdderServiceSteps.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/steps/AdderServiceSteps.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/steps/AdderSteps.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/steps/AdderSteps.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/steps/AdderSteps.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/steps/AdderSteps.java diff --git a/libraries/src/test/java/com/baeldung/serenity/spring/stories/AdderStory.java b/libraries-testing/src/test/java/com/baeldung/serenity/spring/stories/AdderStory.java similarity index 100% rename from libraries/src/test/java/com/baeldung/serenity/spring/stories/AdderStory.java rename to libraries-testing/src/test/java/com/baeldung/serenity/spring/stories/AdderStory.java diff --git a/libraries/src/test/resources/adder-beans.xml b/libraries-testing/src/test/resources/adder-beans.xml similarity index 100% rename from libraries/src/test/resources/adder-beans.xml rename to libraries-testing/src/test/resources/adder-beans.xml diff --git a/libraries/README.md b/libraries/README.md index 375863a5ab..ebf087ccd8 100644 --- a/libraries/README.md +++ b/libraries/README.md @@ -1,58 +1,41 @@ ### Relevant articles -- [Intro to Jasypt](http://www.baeldung.com/jasypt) - [Introduction to Javatuples](http://www.baeldung.com/java-tuples) - [Introduction to Javassist](http://www.baeldung.com/javassist) - [Introduction to Apache Flink with Java](http://www.baeldung.com/apache-flink) -- [Introduction to JSONassert](http://www.baeldung.com/jsonassert) - [Intro to JaVers](http://www.baeldung.com/javers) -- [Introduction to Serenity BDD](http://www.baeldung.com/serenity-bdd) - [Merging Streams in Java](http://www.baeldung.com/java-merge-streams) -- [Serenity BDD and Screenplay](http://www.baeldung.com/serenity-screenplay) - [Introduction to Quartz](http://www.baeldung.com/quartz) - [How to Warm Up the JVM](http://www.baeldung.com/java-jvm-warmup) - [Software Transactional Memory in Java Using Multiverse](http://www.baeldung.com/java-multiverse-stm) -- [Serenity BDD with Spring and JBehave](http://www.baeldung.com/serenity-spring-jbehave) - [Locality-Sensitive Hashing in Java Using Java-LSH](http://www.baeldung.com/locality-sensitive-hashing) -- [Introduction to Awaitlity](http://www.baeldung.com/awaitlity-testing) - [Introduction to Neuroph](http://www.baeldung.com/neuroph) - [Quick Guide to RSS with Rome](http://www.baeldung.com/rome-rss) - [Introduction to PCollections](http://www.baeldung.com/java-pcollections) -- [Introduction to Hoverfly in Java](http://www.baeldung.com/hoverfly) - [Introduction to Eclipse Collections](http://www.baeldung.com/eclipse-collections) - [DistinctBy in the Java Stream API](http://www.baeldung.com/java-streams-distinct-by) - [Introduction to NoException](http://www.baeldung.com/no-exception) - [Spring Yarg Integration](http://www.baeldung.com/spring-yarg) - [Delete a Directory Recursively in Java](http://www.baeldung.com/java-delete-directory) - [Guide to JDeferred](http://www.baeldung.com/jdeferred) -- [Integrating Retrofit with RxJava](http://www.baeldung.com/retrofit-rxjava) - [Introduction to MBassador](http://www.baeldung.com/mbassador) -- [Introduction to Retrofit](http://www.baeldung.com/retrofit) - [Using Pairs in Java](http://www.baeldung.com/java-pairs) - [Introduction to Caffeine](http://www.baeldung.com/java-caching-caffeine) - [Introduction to StreamEx](http://www.baeldung.com/streamex) -- [Introduction to BouncyCastle with Java](http://www.baeldung.com/java-bouncy-castle) - [A Docker Guide for Java](http://www.baeldung.com/docker-java-api) - [Introduction to Akka Actors in Java](http://www.baeldung.com/akka-actors-java) -- [A Guide to Unirest](http://www.baeldung.com/unirest) -- [Introduction to Akka Actors in Java](http://www.baeldung.com/akka-actors-java) - [A Guide to Byte Buddy](http://www.baeldung.com/byte-buddy) - [Introduction to jOOL](http://www.baeldung.com/jool) - [Consumer Driven Contracts with Pact](http://www.baeldung.com/pact-junit-consumer-driven-contracts) - [Introduction to Atlassian Fugue](http://www.baeldung.com/java-fugue) - [Publish and Receive Messages with Nats Java Client](http://www.baeldung.com/nats-java-client) - [Java Concurrency Utility with JCTools](http://www.baeldung.com/java-concurrency-jc-tools) -- [Creating REST Microservices with Javalin](http://www.baeldung.com/javalin-rest-microservices) - [Introduction to JavaPoet](http://www.baeldung.com/java-poet) - [Convert String to Date in Java](http://www.baeldung.com/java-string-to-date) - [Guide to Resilience4j](http://www.baeldung.com/resilience4j) -- [Parsing YAML with SnakeYAML](http://www.baeldung.com/java-snake-yaml) -- [Guide to JMapper](http://www.baeldung.com/jmapper) - [Exactly Once Processing in Kafka](https://www.baeldung.com/kafka-exactly-once) -- [An Introduction to SuanShu](https://www.baeldung.com/suanshu) - [Implementing a FTP-Client in Java](http://www.baeldung.com/java-ftp-client) - [Introduction to Functional Java](https://www.baeldung.com/java-functional-library) -- [Intro to Derive4J](https://www.baeldung.com/derive4j) - [A Guide to the Reflections Library](https://www.baeldung.com/reflections-library) The libraries module contains examples related to small libraries that are relatively easy to use and does not require any separate module of its own. diff --git a/libraries/pom.xml b/libraries/pom.xml index 438fe6a519..a8ded19a1e 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -46,11 +46,7 @@ commons-net ${commons-net.version} - - org.jasypt - jasypt - ${jasypt.version} - + org.javatuples javatuples @@ -106,17 +102,17 @@ - net.serenity-bdd - serenity-core - ${serenity.version} - test - - - org.asciidoctor - asciidoctorj - - - + net.serenity-bdd + serenity-core + ${serenity.version} + test + + + org.asciidoctor + asciidoctorj + + + net.serenity-bdd serenity-junit @@ -367,22 +363,7 @@ ${vavr.version} - - - com.squareup.retrofit2 - retrofit - ${retrofit.version} - - - com.squareup.retrofit2 - converter-gson - ${retrofit.version} - - - com.squareup.retrofit2 - adapter-rxjava - ${retrofit.version} - + com.squareup.okhttp3 logging-interceptor @@ -453,16 +434,6 @@ caffeine ${caffeine.version} - - org.bouncycastle - bcprov-jdk15on - ${bouncycastle.version} - - - org.bouncycastle - bcpkix-jdk15on - ${bouncycastle.version} - com.google.http-client google-http-client @@ -540,18 +511,9 @@ test test - - com.mashape.unirest - unirest-java - ${unirest.version} - - - - io.javalin - javalin - ${javalin.version} - + + io.atlassian.fugue @@ -608,24 +570,6 @@ test - - org.yaml - snakeyaml - ${snakeyaml.version} - - - - com.numericalmethod - suanshu - ${suanshu.version} - - - - org.derive4j - derive4j - ${derive4j.version} - true - org.mockftpserver MockFtpServer @@ -765,12 +709,10 @@ - 4.0.0 - 1.21 + 1.23.0 0.7.0 3.2.7 - 1.9.2 1.2 3.21.0-GA 3.6.2 @@ -799,7 +741,7 @@ 0.9.0 15.2 1.5.1 - 2.3.0 + 2.10 1.5.1 1.15 @@ -810,7 +752,7 @@ v4-rev493-1.21.0 2.0.0 3.0.14 - 1.4.9 + 2.1.2 1.10.L001 0.9.4.0006L @@ -840,13 +782,10 @@ 1.2.6 4.8.1 1.0.1 - 1.58 1.19.4 - 1.6.0 4.5.1 3.3.0 3.0.2 - 1.1.0 2.7.1 3.6 0.9.11 diff --git a/patterns/design-patterns-2/pom.xml b/patterns/design-patterns-2/pom.xml index 17afff87ae..f99bb4dc9c 100644 --- a/patterns/design-patterns-2/pom.xml +++ b/patterns/design-patterns-2/pom.xml @@ -30,6 +30,12 @@ org.apache.commons commons-lang3 ${commons-lang3.version} + + + org.assertj + assertj-core + ${assertj.version} + test org.inferred @@ -49,6 +55,7 @@ 1.8 1.8 16.0.2 + 3.12.2 2.4.1 3.0.2 diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/memento/TextEditor.java b/patterns/design-patterns-2/src/main/java/com/baeldung/memento/TextEditor.java new file mode 100644 index 0000000000..37ac962773 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/memento/TextEditor.java @@ -0,0 +1,27 @@ +package com.baeldung.memento; + +public class TextEditor { + + private TextWindow textWindow; + private TextWindowState savedTextWindow; + + public TextEditor(TextWindow textWindow) { + this.textWindow = textWindow; + } + + public void write(String text) { + textWindow.addText(text); + } + + public String print() { + return textWindow.getCurrentText(); + } + + public void hitSave() { + savedTextWindow = textWindow.save(); + } + + public void hitUndo() { + textWindow.restore(savedTextWindow); + } +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/memento/TextWindow.java b/patterns/design-patterns-2/src/main/java/com/baeldung/memento/TextWindow.java new file mode 100644 index 0000000000..08778561b0 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/memento/TextWindow.java @@ -0,0 +1,26 @@ +package com.baeldung.memento; + +public class TextWindow { + + private StringBuilder currentText; + + public TextWindow() { + this.currentText = new StringBuilder(); + } + + public String getCurrentText() { + return currentText.toString(); + } + + public void addText(String text) { + currentText.append(text); + } + + public TextWindowState save() { + return new TextWindowState(currentText.toString()); + } + + public void restore(TextWindowState save) { + currentText = new StringBuilder(save.getText()); + } +} diff --git a/patterns/design-patterns-2/src/main/java/com/baeldung/memento/TextWindowState.java b/patterns/design-patterns-2/src/main/java/com/baeldung/memento/TextWindowState.java new file mode 100644 index 0000000000..10015a84d1 --- /dev/null +++ b/patterns/design-patterns-2/src/main/java/com/baeldung/memento/TextWindowState.java @@ -0,0 +1,14 @@ +package com.baeldung.memento; + +public class TextWindowState { + + private String text; + + public TextWindowState(String text) { + this.text = text; + } + + public String getText() { + return text; + } +} diff --git a/patterns/design-patterns-2/src/test/java/com/baeldung/memento/TextEditorUnitTest.java b/patterns/design-patterns-2/src/test/java/com/baeldung/memento/TextEditorUnitTest.java new file mode 100644 index 0000000000..09f6df70a2 --- /dev/null +++ b/patterns/design-patterns-2/src/test/java/com/baeldung/memento/TextEditorUnitTest.java @@ -0,0 +1,20 @@ +package com.baeldung.memento; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class TextEditorUnitTest { + + @Test + void givenTextEditor_whenAddTextSaveAddMoreAndUndo_thenSavecStateRestored() { + TextEditor textEditor = new TextEditor(new TextWindow()); + textEditor.write("The Memento Design Pattern\n"); + textEditor.write("How to implement it in Java?\n"); + textEditor.hitSave(); + textEditor.write("Buy milk and eggs before coming home\n"); + textEditor.hitUndo(); + + assertThat(textEditor.print()).isEqualTo("The Memento Design Pattern\nHow to implement it in Java?\n"); + } +} \ No newline at end of file diff --git a/persistence-modules/java-jpa-2/README.md b/persistence-modules/java-jpa-2/README.md index 7a7429008b..579dcbdab0 100644 --- a/persistence-modules/java-jpa-2/README.md +++ b/persistence-modules/java-jpa-2/README.md @@ -1,6 +1,4 @@ # Relevant Articles -<<<<<<< HEAD - [JPA Query Parameters Usage](http://www.baeldung.com/jpa-query-parameters-usage) -======= ->>>>>>> refs/heads/master +- [Mapping Entitiy Class Names to SQL Table Names with JPA](https://www.baeldung.com/jpa-entity-table-names) diff --git a/persistence-modules/java-mongodb/README.md b/persistence-modules/java-mongodb/README.md index 045b245030..f1542e3ee9 100644 --- a/persistence-modules/java-mongodb/README.md +++ b/persistence-modules/java-mongodb/README.md @@ -4,3 +4,4 @@ - [A Simple Tagging Implementation with MongoDB](http://www.baeldung.com/mongodb-tagging) - [MongoDB BSON Guide](https://www.baeldung.com/mongodb-bson) - [Geospatial Support in MongoDB](https://www.baeldung.com/mongodb-geospatial-support) +- [Introduction to Morphia – Java ODM for MongoDB](https://www.baeldung.com/mongodb-morphia) diff --git a/persistence-modules/java-sql2o/README.md b/persistence-modules/java-sql2o/README.md index d3586dc9ed..340ad0fc97 100644 --- a/persistence-modules/java-sql2o/README.md +++ b/persistence-modules/java-sql2o/README.md @@ -1,3 +1,3 @@ ### Relevant Articles: -- [A Guide to Sql2o](https://www.baeldung.com/java-sql2o) +- [A Guide to the sql2o JDBC Wrapper](https://www.baeldung.com/java-sql2o) diff --git a/persistence-modules/spring-hibernate-5/README.md b/persistence-modules/spring-hibernate-5/README.md index dfcc4e7eb8..adfb152afd 100644 --- a/persistence-modules/spring-hibernate-5/README.md +++ b/persistence-modules/spring-hibernate-5/README.md @@ -4,3 +4,4 @@ - [Programmatic Transactions in the Spring TestContext Framework](http://www.baeldung.com/spring-test-programmatic-transactions) - [JPA Criteria Queries](http://www.baeldung.com/hibernate-criteria-queries) - [Introduction to Hibernate Search](http://www.baeldung.com/hibernate-search) +- [@DynamicUpdate with Spring Data JPA](https://www.baeldung.com/spring-data-jpa-dynamicupdate) diff --git a/persistence-modules/spring-mybatis/README.md b/persistence-modules/spring-mybatis/README.md new file mode 100644 index 0000000000..5be328285f --- /dev/null +++ b/persistence-modules/spring-mybatis/README.md @@ -0,0 +1,3 @@ +##Relevant Articles + +- [MyBatis with Spring](https://www.baeldung.com/spring-mybatis) diff --git a/pom.xml b/pom.xml index afe165cf4d..fc3567be51 100644 --- a/pom.xml +++ b/pom.xml @@ -507,6 +507,7 @@ libraries-data-2 libraries-apache-commons libraries-primitive + libraries-testing libraries-security libraries-server libraries-http @@ -650,6 +651,7 @@ spring-boot-keycloak spring-boot-kotlin spring-boot-logging-log4j2 + spring-boot-management spring-boot-mvc spring-boot-mvc-birt spring-boot-ops @@ -1200,6 +1202,7 @@ libraries-data libraries-data-2 libraries-apache-commons + libraries-testing libraries-security libraries-server libraries-http @@ -1326,6 +1329,7 @@ spring-boot-jasypt spring-boot-keycloak spring-boot-logging-log4j2 + spring-boot-management spring-boot-mvc spring-boot-mvc-birt spring-boot-ops diff --git a/resteasy/bin/pom.xml b/resteasy/bin/pom.xml deleted file mode 100644 index 15d8b5bd18..0000000000 --- a/resteasy/bin/pom.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - 4.0.0 - com.baeldung - resteasy-tutorial - 1.0 - war - - - com.baeldung - resteasy-tutorial - 1.0 - - - - RestEasyTutorial - - - org.codehaus.cargo - cargo-maven2-plugin - ${cargo-maven2-plugin.version} - - true - - jetty8x - embedded - - - - 8082 - - - - - - - - - - - - - org.jboss.resteasy - resteasy-servlet-initializer - ${resteasy.version} - - - - - org.jboss.resteasy - resteasy-client - ${resteasy.version} - - - - - - org.jboss.resteasy - resteasy-jaxb-provider - ${resteasy.version} - - - - org.jboss.resteasy - resteasy-jackson-provider - ${resteasy.version} - - - - commons-io - commons-io - ${commons-io.version} - - - - - 3.0.19.Final - 2.5 - 1.6.1 - - \ No newline at end of file diff --git a/resteasy/bin/src/main/webapp/WEB-INF/classes/logback.xml b/resteasy/bin/src/main/webapp/WEB-INF/classes/logback.xml deleted file mode 100644 index ec0dc2469a..0000000000 --- a/resteasy/bin/src/main/webapp/WEB-INF/classes/logback.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - web - %date [%thread] %-5level %logger{36} - %message%n - - - - - - - - - - - - - - \ No newline at end of file diff --git a/resteasy/bin/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/resteasy/bin/src/main/webapp/WEB-INF/jboss-deployment-structure.xml deleted file mode 100644 index cb258374a1..0000000000 --- a/resteasy/bin/src/main/webapp/WEB-INF/jboss-deployment-structure.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/resteasy/bin/src/main/webapp/WEB-INF/jboss-web.xml b/resteasy/bin/src/main/webapp/WEB-INF/jboss-web.xml deleted file mode 100644 index 694bb71332..0000000000 --- a/resteasy/bin/src/main/webapp/WEB-INF/jboss-web.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/resteasy/bin/src/main/webapp/WEB-INF/web.xml b/resteasy/bin/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index d5f00293f4..0000000000 --- a/resteasy/bin/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - RestEasy Example - - - resteasy.servlet.mapping.prefix - /rest - - - \ No newline at end of file diff --git a/resteasy/bin/src/main/webapp/script.js b/resteasy/bin/src/main/webapp/script.js deleted file mode 100644 index 88198887b0..0000000000 --- a/resteasy/bin/src/main/webapp/script.js +++ /dev/null @@ -1,16 +0,0 @@ -function call(url, type, data) { - var request = $.ajax({ - url : url, - method : "GET", - data : (data) ? JSON.stringify(data) : "", - dataType : type - }); - - request.done(function(resp) { - console.log(resp); - }); - - request.fail(function(jqXHR, textStatus) { - console.log("Request failed: " + textStatus); - }); -}; \ No newline at end of file diff --git a/resteasy/bin/src/test/resources/com/baeldung/server/movies/batman.json b/resteasy/bin/src/test/resources/com/baeldung/server/movies/batman.json deleted file mode 100644 index 82aaaa8f40..0000000000 --- a/resteasy/bin/src/test/resources/com/baeldung/server/movies/batman.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Batman", - "imdbId": "tt0096895" -} \ No newline at end of file diff --git a/resteasy/bin/src/test/resources/com/baeldung/server/movies/transformer.json b/resteasy/bin/src/test/resources/com/baeldung/server/movies/transformer.json deleted file mode 100644 index 634cefc73c..0000000000 --- a/resteasy/bin/src/test/resources/com/baeldung/server/movies/transformer.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Transformers", - "imdbId": "tt0418279" -} \ No newline at end of file diff --git a/spring-5-data-reactive/README.md b/spring-5-data-reactive/README.md index f3205c23bc..4c2347dc77 100644 --- a/spring-5-data-reactive/README.md +++ b/spring-5-data-reactive/README.md @@ -7,3 +7,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Reactive Flow with MongoDB, Kotlin, and Spring WebFlux](http://www.baeldung.com/kotlin-mongodb-spring-webflux) - [Spring Data Reactive Repositories with MongoDB](http://www.baeldung.com/spring-data-mongodb-reactive) - [Spring Data MongoDB Tailable Cursors](https://www.baeldung.com/spring-data-mongodb-tailable-cursors) +- [A Quick Look at R2DBC with Spring Data](https://www.baeldung.com/spring-data-r2dbc) diff --git a/spring-5-reactive-2/README.md b/spring-5-reactive-2/README.md index bbb45e9f8c..7aec8f94bf 100644 --- a/spring-5-reactive-2/README.md +++ b/spring-5-reactive-2/README.md @@ -1 +1,2 @@ ## Spring 5 Reactive Project +- [Spring WebClient vs. RestTemplate](https://www.baeldung.com/spring-webclient-resttemplate) diff --git a/spring-5-reactive/pom.xml b/spring-5-reactive/pom.xml index 8d5324a673..99cdd11f24 100644 --- a/spring-5-reactive/pom.xml +++ b/spring-5-reactive/pom.xml @@ -120,6 +120,12 @@ ${project-reactor-test} test + + org.apache.httpcomponents + httpclient + ${httpclient.version} + + @@ -165,6 +171,7 @@ 1.0 4.1 3.2.3.RELEASE + 4.5.8 diff --git a/spring-all/README.md b/spring-all/README.md index 22c51525f3..c5825b47fb 100644 --- a/spring-all/README.md +++ b/spring-all/README.md @@ -33,4 +33,3 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Spring Events](https://www.baeldung.com/spring-events) - [Spring Null-Safety Annotations](https://www.baeldung.com/spring-null-safety-annotations) - [Using @Autowired in Abstract Classes](https://www.baeldung.com/spring-autowired-abstract-class) -- [The Spring @Qualifier Annotation](https://www.baeldung.com/spring-qualifier-annotation) diff --git a/spring-boot-angular/src/main/java/com/baeldung/pom.xml b/spring-boot-angular/src/main/java/com/baeldung/pom.xml deleted file mode 100644 index ac86f932b4..0000000000 --- a/spring-boot-angular/src/main/java/com/baeldung/pom.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - 4.0.0 - com.baeldung.springbootangular - spring-boot-angular - 1.0 - jar - Spring Boot Angular Application - - - org.springframework.boot - spring-boot-starter-parent - 2.1.3.RELEASE - - - - - - org.springframework.boot - spring-boot-starter-data-jpa - - - org.springframework.boot - spring-boot-starter-web - - - com.h2database - h2 - runtime - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - - 1.8 - - \ No newline at end of file diff --git a/spring-boot-crud/README.md b/spring-boot-crud/README.md index 566cb327a8..ab2cbe1e3a 100644 --- a/spring-boot-crud/README.md +++ b/spring-boot-crud/README.md @@ -1,2 +1,3 @@ ### Relevant Articles: - [Spring Boot CRUD Application with Thymeleaf](https://www.baeldung.com/spring-boot-crud-thymeleaf) +- [Using a Spring Boot Application as a Dependency](https://www.baeldung.com/spring-boot-dependency) diff --git a/spring-boot-management/pom.xml b/spring-boot-management/pom.xml new file mode 100644 index 0000000000..2b3e8f5d06 --- /dev/null +++ b/spring-boot-management/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + com.baeldung + spring-boot-management + 0.0.1-SNAPSHOT + spring-boot-management + + + 1.8 + + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-boot-management/src/main/java/com/baeldung/spring/boot/management/trace/App.java b/spring-boot-management/src/main/java/com/baeldung/spring/boot/management/trace/App.java new file mode 100644 index 0000000000..150e451c57 --- /dev/null +++ b/spring-boot-management/src/main/java/com/baeldung/spring/boot/management/trace/App.java @@ -0,0 +1,13 @@ +package com.baeldung.spring.boot.management.trace; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class App { + + public static void main(String[] args) { + SpringApplication.run(App.class); + } + +} diff --git a/spring-boot-management/src/main/java/com/baeldung/spring/boot/management/trace/CustomTraceRepository.java b/spring-boot-management/src/main/java/com/baeldung/spring/boot/management/trace/CustomTraceRepository.java new file mode 100644 index 0000000000..d85c043dc0 --- /dev/null +++ b/spring-boot-management/src/main/java/com/baeldung/spring/boot/management/trace/CustomTraceRepository.java @@ -0,0 +1,29 @@ +package com.baeldung.spring.boot.management.trace; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + +import org.springframework.boot.actuate.trace.http.HttpTrace; +import org.springframework.boot.actuate.trace.http.HttpTraceRepository; +import org.springframework.stereotype.Repository; + +@Repository +public class CustomTraceRepository implements HttpTraceRepository { + + AtomicReference lastTrace = new AtomicReference<>(); + + @Override + public List findAll() { + return Collections.singletonList(lastTrace.get()); + } + + @Override + public void add(HttpTrace trace) { + if ("GET".equals(trace.getRequest() + .getMethod())) { + lastTrace.set(trace); + } + } + +} diff --git a/spring-boot-management/src/main/java/com/baeldung/spring/boot/management/trace/EchoController.java b/spring-boot-management/src/main/java/com/baeldung/spring/boot/management/trace/EchoController.java new file mode 100644 index 0000000000..70bc27a3bb --- /dev/null +++ b/spring-boot-management/src/main/java/com/baeldung/spring/boot/management/trace/EchoController.java @@ -0,0 +1,15 @@ +package com.baeldung.spring.boot.management.trace; + +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController("echo") +public class EchoController { + + @GetMapping + public String echo(@RequestParam("msg") String msg) { + return "echoing " + msg; + } + +} diff --git a/spring-boot-management/src/main/java/com/baeldung/spring/boot/management/trace/TraceRequestFilter.java b/spring-boot-management/src/main/java/com/baeldung/spring/boot/management/trace/TraceRequestFilter.java new file mode 100644 index 0000000000..fd6312df47 --- /dev/null +++ b/spring-boot-management/src/main/java/com/baeldung/spring/boot/management/trace/TraceRequestFilter.java @@ -0,0 +1,27 @@ +package com.baeldung.spring.boot.management.trace; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +import org.springframework.boot.actuate.trace.http.HttpExchangeTracer; +import org.springframework.boot.actuate.trace.http.HttpTraceRepository; +import org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter; +import org.springframework.stereotype.Component; + +@Component +public class TraceRequestFilter extends HttpTraceFilter { + /** + * Create a new {@link HttpTraceFilter} instance. + * + * @param repository the trace repository + * @param tracer used to trace exchanges + */ + public TraceRequestFilter(HttpTraceRepository repository, HttpExchangeTracer tracer) { + super(repository, tracer); + } + + @Override + protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { + return request.getServletPath().contains("actuator"); + } +} diff --git a/spring-boot-management/src/main/resources/application.properties b/spring-boot-management/src/main/resources/application.properties new file mode 100644 index 0000000000..835ca64eac --- /dev/null +++ b/spring-boot-management/src/main/resources/application.properties @@ -0,0 +1,3 @@ +management.endpoints.web.exposure.include=httptrace +management.trace.http.include=RESPONSE_HEADERS + diff --git a/spring-boot-properties/README.md b/spring-boot-properties/README.md index e467e129dd..9aea5b4871 100644 --- a/spring-boot-properties/README.md +++ b/spring-boot-properties/README.md @@ -1,10 +1,10 @@ ### Relevant Articles: -- [Reloading Properties in Spring](https://www.baeldung.com/reloading-properties-files-in-spring/) +- [Reloading Properties Files in Spring](https://www.baeldung.com/spring-reloading-properties) - [Guide to @ConfigurationProperties in Spring Boot](http://www.baeldung.com/configuration-properties-in-spring-boot) - [Load Spring Boot Properties From a JSON File](https://www.baeldung.com/spring-boot-json-properties) - [Guide to @EnableConfigurationProperties](https://www.baeldung.com/spring-enable-config-properties) -- [Properties with Spring and Spring Boot](http://www.baeldung.com/properties-with-spring) - checkout the `org.baeldung.properties` package for all scenarios of properties injection and usage +- [Properties with Spring and Spring Boot](http://www.baeldung.com/properties-with-spring) - checkout the `com.baeldung.properties` package for all scenarios of properties injection and usage - [A Quick Guide to Spring @Value](http://www.baeldung.com/spring-value-annotation) - [Spring YAML Configuration](http://www.baeldung.com/spring-yaml) - [Using Spring @Value with Defaults](http://www.baeldung.com/spring-value-defaults) -- [How to Inject a Property Value Into a Class Not Managed by Spring?](http://www.baeldung.com/inject-properties-value-non-spring-class) \ No newline at end of file +- [How to Inject a Property Value Into a Class Not Managed by Spring?](http://www.baeldung.com/inject-properties-value-non-spring-class) diff --git a/spring-boot-testing/README.MD b/spring-boot-testing/README.MD index 99d7db5743..7a4c4f53a1 100644 --- a/spring-boot-testing/README.MD +++ b/spring-boot-testing/README.MD @@ -6,3 +6,4 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring - [Testing with Spring and Spock](https://www.baeldung.com/spring-spock-testing) - [Exclude Auto-Configuration Classes in Spring Boot Tests](https://www.baeldung.com/spring-boot-exclude-auto-configuration-test) - [Setting the Log Level in Spring Boot when Testing](https://www.baeldung.com/spring-boot-testing-log-level) +- [Embedded Redis Server with Spring Boot Test](https://www.baeldung.com/spring-embedded-redis) diff --git a/spring-di/README.md b/spring-di/README.md new file mode 100644 index 0000000000..a61ebe5127 --- /dev/null +++ b/spring-di/README.md @@ -0,0 +1,3 @@ +### Relevant Articles + +- [The Spring @Qualifier Annotation](https://www.baeldung.com/spring-qualifier-annotation) diff --git a/spring-jooq/src/test/java/com/baeldung/jooq/introduction/QueryIntegrationTest.java b/spring-jooq/src/test/java/com/baeldung/jooq/introduction/QueryIntegrationTest.java index 28bc4c63c7..ff1e8dc6f8 100644 --- a/spring-jooq/src/test/java/com/baeldung/jooq/introduction/QueryIntegrationTest.java +++ b/spring-jooq/src/test/java/com/baeldung/jooq/introduction/QueryIntegrationTest.java @@ -47,12 +47,14 @@ public class QueryIntegrationTest { .from(AUTHOR) .join(AUTHOR_BOOK).on(AUTHOR.ID.equal(AUTHOR_BOOK.AUTHOR_ID)) .join(BOOK).on(AUTHOR_BOOK.BOOK_ID.equal(BOOK.ID)) - .groupBy(AUTHOR.LAST_NAME).fetch(); + .groupBy(AUTHOR.LAST_NAME) + .orderBy(AUTHOR.LAST_NAME.desc()) + .fetch(); assertEquals(3, result.size()); assertEquals("Sierra", result.getValue(0, AUTHOR.LAST_NAME)); assertEquals(Integer.valueOf(2), result.getValue(0, DSL.count())); - assertEquals("Schildt", result.getValue(2, AUTHOR.LAST_NAME)); + assertEquals("Bates", result.getValue(2, AUTHOR.LAST_NAME)); assertEquals(Integer.valueOf(1), result.getValue(2, DSL.count())); } diff --git a/spring-jooq/src/test/java/com/baeldung/jooq/springboot/SpringBootIntegrationTest.java b/spring-jooq/src/test/java/com/baeldung/jooq/springboot/SpringBootIntegrationTest.java index 5e76fb3c93..3b3e865108 100644 --- a/spring-jooq/src/test/java/com/baeldung/jooq/springboot/SpringBootIntegrationTest.java +++ b/spring-jooq/src/test/java/com/baeldung/jooq/springboot/SpringBootIntegrationTest.java @@ -49,12 +49,13 @@ public class SpringBootIntegrationTest { .from(AUTHOR).join(AUTHOR_BOOK).on(AUTHOR.ID.equal(AUTHOR_BOOK.AUTHOR_ID)) .join(BOOK).on(AUTHOR_BOOK.BOOK_ID.equal(BOOK.ID)) .groupBy(AUTHOR.LAST_NAME) + .orderBy(AUTHOR.LAST_NAME.desc()) .fetch(); assertEquals(3, result.size()); assertEquals("Sierra", result.getValue(0, AUTHOR.LAST_NAME)); assertEquals(Integer.valueOf(2), result.getValue(0, DSL.count())); - assertEquals("Schildt", result.getValue(2, AUTHOR.LAST_NAME)); + assertEquals("Bates", result.getValue(2, AUTHOR.LAST_NAME)); assertEquals(Integer.valueOf(1), result.getValue(2, DSL.count())); } diff --git a/spring-roo/pom.xml b/spring-roo/pom.xml index baa0e7f5e6..eb3a680d93 100644 --- a/spring-roo/pom.xml +++ b/spring-roo/pom.xml @@ -604,14 +604,14 @@ - 2.0.0.RC1 + 2.0.0.RELEASE 8 UTF-8 1.8 1.5.4 - 1.4.1.RELEASE + 2.1.7.RELEASE 1.8 - 1.2.0.RC1 + 1.2.0.RELEASE 1.1.2 3.0.0.RELEASE 2.0.0 diff --git a/spring-thymeleaf-2/README.md b/spring-thymeleaf-2/README.md index 9bd441a6bd..9e12f2d99f 100644 --- a/spring-thymeleaf-2/README.md +++ b/spring-thymeleaf-2/README.md @@ -1,3 +1,4 @@ ## Relevant Articles: - [Working with Enums in Thymeleaf](https://www.baeldung.com/thymeleaf-enums) +- [Changing the Thymeleaf Template Directory in Spring Boot](https://www.baeldung.com/spring-thymeleaf-template-directory) diff --git a/spring-thymeleaf/README.md b/spring-thymeleaf/README.md index b6824003db..082a65f55b 100644 --- a/spring-thymeleaf/README.md +++ b/spring-thymeleaf/README.md @@ -18,6 +18,7 @@ - [Spring with Thymeleaf Pagination for a List](http://www.baeldung.com/spring-thymeleaf-pagination) - [Working with Select and Option in Thymeleaf](http://www.baeldung.com/thymeleaf-select-option) - [Working With Custom HTML Attributes in Thymeleaf](https://www.baeldung.com/thymeleaf-custom-html-attributes) +- [Spring Request Parameters with Thymeleaf](https://www.baeldung.com/spring-thymeleaf-request-parameters) ### Build the Project diff --git a/testing-modules/junit-5-basics/README.md b/testing-modules/junit-5-basics/README.md index dbe6803401..31eb75a792 100644 --- a/testing-modules/junit-5-basics/README.md +++ b/testing-modules/junit-5-basics/README.md @@ -8,3 +8,4 @@ - [JUnit 5 @Test Annotation](http://www.baeldung.com/junit-5-test-annotation) - [Migrating from JUnit 4 to JUnit 5](http://www.baeldung.com/junit-5-migration) - [Assert an Exception is Thrown in JUnit 4 and 5](http://www.baeldung.com/junit-assert-exception) +- [The Difference Between Failure and Error in JUnit](https://www.baeldung.com/junit-failure-vs-error) diff --git a/testing-modules/rest-assured/pom.xml b/testing-modules/rest-assured/pom.xml index eb85c6c8be..75f33c26f1 100644 --- a/testing-modules/rest-assured/pom.xml +++ b/testing-modules/rest-assured/pom.xml @@ -162,11 +162,6 @@ commons-collections ${commons-collections.version} - - - org.springframework.boot - spring-boot-starter-security - diff --git a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/controller/AppControllerIntegrationTest.java b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/controller/AppControllerIntegrationTest.java index a55c0a69e4..83a6e544b7 100644 --- a/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/controller/AppControllerIntegrationTest.java +++ b/testing-modules/rest-assured/src/test/java/com/baeldung/restassured/controller/AppControllerIntegrationTest.java @@ -17,7 +17,7 @@ import java.util.Set; import javax.annotation.PostConstruct; -import org.junit.jupiter.api.Test; +import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;