diff --git a/apache-poi-2/src/test/java/com/baeldung/poi/excel/lastrow/LastRowUnitTest.java b/apache-poi-2/src/test/java/com/baeldung/poi/excel/lastrow/LastRowUnitTest.java new file mode 100644 index 0000000000..ea838be4ce --- /dev/null +++ b/apache-poi-2/src/test/java/com/baeldung/poi/excel/lastrow/LastRowUnitTest.java @@ -0,0 +1,67 @@ +package com.baeldung.poi.excel.lastrow; + +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Paths; + +import static org.junit.jupiter.api.Assertions.*; + +public class LastRowUnitTest { + private static final String FILE_NAME = "lastRowTest.xlsx"; + private String fileLocation; + + @Before + public void setup() throws URISyntaxException { + fileLocation = Paths.get(ClassLoader.getSystemResource(FILE_NAME).toURI()).toString(); + } + + @Test + public void givenExampleGrid_whenGetRow_thenReturnRowObjectIfModified() throws IOException { + Workbook workbook = new XSSFWorkbook(fileLocation); + Sheet sheet = workbook.getSheetAt(0); + + assertEquals(7, sheet.getLastRowNum()); + assertEquals(6, sheet.getPhysicalNumberOfRows()); + + assertNotNull(sheet.getRow(0)); + assertNotNull(sheet.getRow(1)); + assertNotNull(sheet.getRow(2)); + assertNotNull(sheet.getRow(3)); + assertNull(sheet.getRow(4)); + assertNull(sheet.getRow(5)); + assertNotNull(sheet.getRow(6)); + assertNotNull(sheet.getRow(7)); + assertNull(sheet.getRow(8)); + + assertSame(sheet.getRow(7), getLastRowFromSheet(sheet)); + } + + @Test + public void givenEmptySheet_whenGetRow_thenReturnNull() throws IOException { + Workbook workbook = new XSSFWorkbook(fileLocation); + Sheet sheet = workbook.getSheetAt(1); + + assertEquals(-1, sheet.getLastRowNum()); + assertEquals(0, sheet.getPhysicalNumberOfRows()); + + assertNull(sheet.getRow(0)); + + assertSame(sheet.getRow(0), getLastRowFromSheet(sheet)); + } + + public static Row getLastRowFromSheet(Sheet sheet) { + Row lastRow = null; + int lastRowNum = sheet.getLastRowNum(); + if (lastRowNum >= 0) { + lastRow = sheet.getRow(lastRowNum); + } + return lastRow; + } +} diff --git a/apache-poi-2/src/test/resources/lastRowTest.xlsx b/apache-poi-2/src/test/resources/lastRowTest.xlsx new file mode 100644 index 0000000000..3980ceb1f2 Binary files /dev/null and b/apache-poi-2/src/test/resources/lastRowTest.xlsx differ diff --git a/core-java-modules/core-java-collections-maps-4/README.md b/core-java-modules/core-java-collections-maps-4/README.md index 795f0df702..92da12fbf9 100644 --- a/core-java-modules/core-java-collections-maps-4/README.md +++ b/core-java-modules/core-java-collections-maps-4/README.md @@ -6,3 +6,5 @@ This module contains articles about Map data structures in Java. - [Using a Custom Class as a Key in a Java HashMap](https://www.baeldung.com/java-custom-class-map-key) - [Nested HashMaps Examples in Java](https://www.baeldung.com/java-nested-hashmaps) - [Java HashMap With Different Value Types](https://www.baeldung.com/java-hashmap-different-value-types) +- [Difference Between Map and HashMap in Java](https://www.baeldung.com/java-map-vs-hashmap) +- [How to Create a New Entry in a Map](https://www.baeldung.com/java-map-new-entry) diff --git a/core-java-modules/core-java-concurrency-advanced-4/README.md b/core-java-modules/core-java-concurrency-advanced-4/README.md index 446a553b88..ba838dbc72 100644 --- a/core-java-modules/core-java-concurrency-advanced-4/README.md +++ b/core-java-modules/core-java-concurrency-advanced-4/README.md @@ -4,3 +4,4 @@ - [Bad Practices With Synchronization](https://www.baeldung.com/java-synchronization-bad-practices) - [Start Two Threads at the Exact Same Time in Java](https://www.baeldung.com/java-start-two-threads-at-same-time) - [Volatile Variables and Thread Safety](https://www.baeldung.com/java-volatile-variables-thread-safety) +- [Producer-Consumer Problem With Example in Java](https://www.baeldung.com/java-producer-consumer-problem) diff --git a/core-java-modules/core-java-exceptions-4/README.md b/core-java-modules/core-java-exceptions-4/README.md index 259feb685c..e77787a8a3 100644 --- a/core-java-modules/core-java-exceptions-4/README.md +++ b/core-java-modules/core-java-exceptions-4/README.md @@ -1,3 +1,4 @@ ### Relevant Articles: - [Java ArrayIndexOutOfBoundsException](https://www.baeldung.com/java-arrayindexoutofboundsexception) +- [Java Missing Return Statement](https://www.baeldung.com/java-missing-return-statement) diff --git a/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/variablemightnothavebeeninitialized/VariableMightNotHaveBeenInitialized.java b/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/variablemightnothavebeeninitialized/VariableMightNotHaveBeenInitialized.java deleted file mode 100644 index 64118e6307..0000000000 --- a/core-java-modules/core-java-exceptions-4/src/main/java/com/baeldung/exception/variablemightnothavebeeninitialized/VariableMightNotHaveBeenInitialized.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.baeldung.exception.variablemightnothavebeeninitialized; - -public class VariableMightNotHaveBeenInitialized { - - private static int instanceVariableCount; - - /** - * Method would not compile if lines 14 and 18 are uncommented. - */ - public static void countEven() { - //uninstantiated - int count; - int[] arr = new int[]{23, 56, 89, 12, 23}; - for (int i = 0; i < arr.length; i++) { - if ((arr[i] % 2) == 0) { - // count++; - } - - } - // System.out.println("Total Even Numbers : " + count); - } - - public static int countEvenUsingInstanceVariable(int[] arr) { - - for (int i = 0; i < arr.length; i++) { - if ((arr[i] % 2) == 0) { - instanceVariableCount++; - } - - } - return instanceVariableCount; - } - - public static int countEvenUsingIfElse(int[] arr, int args) { - int count; - count = args > 0 ? args : 0; - for (int i = 0; i < arr.length; i++) { - if ((arr[i] % 2) == 0) { - count++; - } - - } - return count; - } -} diff --git a/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/variablemightnothavebeeninitialized/VariableMightNotHaveBeenInitializedUnitTest.java b/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/variablemightnothavebeeninitialized/VariableMightNotHaveBeenInitializedUnitTest.java deleted file mode 100644 index c4773d6442..0000000000 --- a/core-java-modules/core-java-exceptions-4/src/test/java/com/baeldung/exception/variablemightnothavebeeninitialized/VariableMightNotHaveBeenInitializedUnitTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.baeldung.exception.variablemightnothavebeeninitialized; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; - -public class VariableMightNotHaveBeenInitializedUnitTest { - - @Test - public void usingInstanceVariable_returnCount() { - int[] arr = new int[]{1, 2, 3, 4, 5, 6}; - int value = VariableMightNotHaveBeenInitialized.countEvenUsingInstanceVariable(arr); - - assertEquals(3, value); - } - - @Test - public void usingArgumentsAndIfElse_returnCount() { - int[] arr = new int[]{1, 2, 3, 4, 5, 6}; - int value = VariableMightNotHaveBeenInitialized.countEvenUsingIfElse(arr, 2); - - assertEquals(5, value); - } -} diff --git a/core-java-modules/core-java-io-4/src/main/java/com/baeldung/filetomap/FileToHashMap.java b/core-java-modules/core-java-io-4/src/main/java/com/baeldung/filetomap/FileToHashMap.java new file mode 100644 index 0000000000..f88404a1a4 --- /dev/null +++ b/core-java-modules/core-java-io-4/src/main/java/com/baeldung/filetomap/FileToHashMap.java @@ -0,0 +1,83 @@ +package com.baeldung.filetomap; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class FileToHashMap { + + enum DupKeyOption { + OVERWRITE, DISCARD + } + + public static Map byBufferedReader(String filePath, DupKeyOption dupKeyOption) { + HashMap map = new HashMap<>(); + String line; + try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) { + while ((line = reader.readLine()) != null) { + String[] keyValuePair = line.split(":", 2); + if (keyValuePair.length > 1) { + String key = keyValuePair[0]; + String value = keyValuePair[1]; + if (DupKeyOption.OVERWRITE == dupKeyOption) { + map.put(key, value); + } else if (DupKeyOption.DISCARD == dupKeyOption) { + map.putIfAbsent(key, value); + } + } else { + System.out.println("No Key:Value found in line, ignoring: " + line); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + return map; + } + + public static Map byStream(String filePath, DupKeyOption dupKeyOption) { + Map map = new HashMap<>(); + try (Stream lines = Files.lines(Paths.get(filePath))) { + lines.filter(line -> line.contains(":")) + .forEach(line -> { + String[] keyValuePair = line.split(":", 2); + String key = keyValuePair[0]; + String value = keyValuePair[1]; + if (DupKeyOption.OVERWRITE == dupKeyOption) { + map.put(key, value); + } else if (DupKeyOption.DISCARD == dupKeyOption) { + map.putIfAbsent(key, value); + } + }); + } catch (IOException e) { + e.printStackTrace(); + } + return map; + } + + public static Map> aggregateByKeys(String filePath) { + Map> map = new HashMap<>(); + try (Stream lines = Files.lines(Paths.get(filePath))) { + lines.filter(line -> line.contains(":")) + .forEach(line -> { + String[] keyValuePair = line.split(":", 2); + String key = keyValuePair[0]; + String value = keyValuePair[1]; + if (map.containsKey(key)) { + map.get(key).add(value); + } else { + map.put(key, Stream.of(value).collect(Collectors.toList())); + } + }); + } catch (IOException e) { + e.printStackTrace(); + } + return map; + } +} diff --git a/core-java-modules/core-java-io-4/src/test/java/com/baeldung/filetomap/FileToHashMapUnitTest.java b/core-java-modules/core-java-io-4/src/test/java/com/baeldung/filetomap/FileToHashMapUnitTest.java new file mode 100644 index 0000000000..c89f26de69 --- /dev/null +++ b/core-java-modules/core-java-io-4/src/test/java/com/baeldung/filetomap/FileToHashMapUnitTest.java @@ -0,0 +1,66 @@ +package com.baeldung.filetomap; + +import org.junit.Before; +import org.junit.Test; + +import java.net.URISyntaxException; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +public class FileToHashMapUnitTest { + + private String filePath; + + private static final Map EXPECTED_MAP_DISCARD = Stream.of(new String[][]{ + {"title", "The Lord of the Rings: The Return of the King"}, + {"director", "Peter Jackson"}, + {"actor", "Sean Astin"} + }).collect(Collectors.toMap(data -> data[0], data -> data[1])); + + private static final Map EXPECTED_MAP_OVERWRITE = Stream.of(new String[][]{ + {"title", "The Lord of the Rings: The Return of the King"}, + {"director", "Peter Jackson"}, + {"actor", "Ian McKellen"} + }).collect(Collectors.toMap(data -> data[0], data -> data[1])); + + private static final Map> EXPECTED_MAP_AGGREGATE = Stream.of(new String[][]{ + {"title", "The Lord of the Rings: The Return of the King"}, + {"director", "Peter Jackson"}, + {"actor", "Sean Astin", "Ian McKellen"} + }).collect(Collectors.toMap(arr -> arr[0], arr -> Arrays.asList(Arrays.copyOfRange(arr, 1, arr.length)))); + + @Before + public void setPath() throws URISyntaxException { + if (filePath == null) { + filePath = Paths.get(ClassLoader.getSystemResource("filetomap/theLordOfRings.txt").toURI()).toString(); + } + } + + @Test + public void givenInputFile_whenInvokeByBufferedReaderPriorToJava8_shouldGetExpectedMap() { + Map mapOverwrite = FileToHashMap.byBufferedReader(filePath, FileToHashMap.DupKeyOption.OVERWRITE); + Map mapDiscard = FileToHashMap.byBufferedReader(filePath, FileToHashMap.DupKeyOption.DISCARD); + assertThat(mapOverwrite).isEqualTo(EXPECTED_MAP_OVERWRITE); + assertThat(mapDiscard).isEqualTo(EXPECTED_MAP_DISCARD); + } + + @Test + public void givenInputFile_whenInvokeByStream_shouldGetExpectedMap() { + Map mapOverwrite = FileToHashMap.byStream(filePath, FileToHashMap.DupKeyOption.OVERWRITE); + Map mapDiscard = FileToHashMap.byStream(filePath, FileToHashMap.DupKeyOption.DISCARD); + assertThat(mapOverwrite).isEqualTo(EXPECTED_MAP_OVERWRITE); + assertThat(mapDiscard).isEqualTo(EXPECTED_MAP_DISCARD); + } + + @Test + public void givenInputFile_whenInvokeAggregateByKeys_shouldGetExpectedMap() { + Map> mapAgg = FileToHashMap.aggregateByKeys(filePath); + assertThat(mapAgg).isEqualTo(EXPECTED_MAP_AGGREGATE); + } +} diff --git a/core-java-modules/core-java-io-4/src/test/resources/filetomap/theLordOfRings.txt b/core-java-modules/core-java-io-4/src/test/resources/filetomap/theLordOfRings.txt new file mode 100644 index 0000000000..1ab069e533 --- /dev/null +++ b/core-java-modules/core-java-io-4/src/test/resources/filetomap/theLordOfRings.txt @@ -0,0 +1,6 @@ +title:The Lord of the Rings: The Return of the King +director:Peter Jackson +actor:Sean Astin +actor:Ian McKellen +Gandalf and Aragorn lead the World of Men against Sauron's +army to draw his gaze from Frodo and Sam as they approach Mount Doom with the One Ring. \ No newline at end of file diff --git a/docker/README.md b/docker/README.md index 0adf1c9b51..b2ae5d56c9 100644 --- a/docker/README.md +++ b/docker/README.md @@ -7,3 +7,4 @@ - [Dockerfile Strategies for Git](https://www.baeldung.com/ops/dockerfile-git-strategies) - [How to Get Docker-Compose to Always Use the Latest Image](https://www.baeldung.com/ops/docker-compose-latest-image) - [How to Include Files Outside of Docker’s Build Context](https://www.baeldung.com/ops/docker-include-files-outside-build-context) +- [Caching Maven Dependencies with Docker](https://www.baeldung.com/ops/docker-cache-maven-dependencies) diff --git a/graphql/graphql-java/pom.xml b/graphql/graphql-java/pom.xml index 4e2444c1fb..f2733bf671 100644 --- a/graphql/graphql-java/pom.xml +++ b/graphql/graphql-java/pom.xml @@ -12,8 +12,24 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT + ../../ + + + jitpack.io + https://jitpack.io + + + + false + + central + Central Repository + https://repo.maven.apache.org/maven2 + + + com.graphql-java @@ -25,11 +41,114 @@ ratpack-core ${ratpack-core.version} + + com.github.americanexpress.nodes + nodes + 0.5.0 + + + com.graphql-java + graphql-java + 9.2 + + + com.graphql-java + graphql-java-tools + 5.2.4 + + + com.graphql-java + graphql-java-servlet + 6.1.3 + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + org.apache.commons + commons-lang3 + 3.12.0 + + + org.mock-server + mockserver-netty + 5.11.2 + + + org.mock-server + mockserver-client-java + 5.11.2 + + + com.graphql-java-generator + graphql-java-runtime + ${graphql.java.generator.version} + + + org.junit.jupiter + junit-jupiter-engine + 5.8.2 + test + + + org.assertj + assertj-core + 3.22.0 + test + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.eclipse.jetty + jetty-maven-plugin + 10.0.7 + + + maven-war-plugin + 3.1.0 + + + com.graphql-java-generator + graphql-maven-plugin + ${graphql.java.generator.version} + + + + generateClientCode + + + + + com.baeldung.graphql.generated + false + false + true + + + + + 3.0.3 1.4.6 + 3.1 + 1.8 + 1.8 + 1.18 \ No newline at end of file diff --git a/graphql/graphql-java/src/main/java/com/baeldung/graphql/clients/AmericanExpressNodes.java b/graphql/graphql-java/src/main/java/com/baeldung/graphql/clients/AmericanExpressNodes.java new file mode 100644 index 0000000000..446dbd416e --- /dev/null +++ b/graphql/graphql-java/src/main/java/com/baeldung/graphql/clients/AmericanExpressNodes.java @@ -0,0 +1,24 @@ +package com.baeldung.graphql.clients; + +import com.baeldung.graphql.data.Data; +import io.aexp.nodes.graphql.GraphQLRequestEntity; +import io.aexp.nodes.graphql.GraphQLResponseEntity; +import io.aexp.nodes.graphql.GraphQLTemplate; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; + +public class AmericanExpressNodes { + + public static GraphQLResponseEntity callGraphQLService(String url, String query) throws IOException { + GraphQLTemplate graphQLTemplate = new GraphQLTemplate(); + + GraphQLRequestEntity requestEntity = GraphQLRequestEntity.Builder() + .url(StringUtils.join(url, "?query=", query)) + .request(Data.class) + .build(); + + return graphQLTemplate.query(requestEntity, Data.class); + } + +} diff --git a/graphql/graphql-java/src/main/java/com/baeldung/graphql/clients/ApacheHttpClient.java b/graphql/graphql-java/src/main/java/com/baeldung/graphql/clients/ApacheHttpClient.java new file mode 100644 index 0000000000..d4f88e62f5 --- /dev/null +++ b/graphql/graphql-java/src/main/java/com/baeldung/graphql/clients/ApacheHttpClient.java @@ -0,0 +1,25 @@ +package com.baeldung.graphql.clients; + +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.HttpClientBuilder; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +public class ApacheHttpClient { + + public static HttpResponse callGraphQLService(String url, String query) throws URISyntaxException, IOException { + HttpClient client = HttpClientBuilder.create().build(); + HttpGet request = new HttpGet(url); + URI uri = new URIBuilder(request.getURI()) + .addParameter("query", query) + .build(); + request.setURI(uri); + return client.execute(request); + } + +} diff --git a/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/Author.java b/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/Author.java new file mode 100644 index 0000000000..876df27769 --- /dev/null +++ b/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/Author.java @@ -0,0 +1,31 @@ +package com.baeldung.graphql.data; + +import org.apache.commons.lang3.StringUtils; + +public class Author { + + private String name; + private String surname; + + public Author() { + + } + + public Author(String name, String surname) { + this.name = name; + this.surname = surname; + } + + public String getName() { + return name; + } + + public String getSurname() { + return surname; + } + + public String getFullName() { + return StringUtils.join(getName(), " ", getSurname()); + } + +} diff --git a/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/Book.java b/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/Book.java new file mode 100644 index 0000000000..6e6188368b --- /dev/null +++ b/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/Book.java @@ -0,0 +1,25 @@ +package com.baeldung.graphql.data; + +public class Book { + + private String title; + private Author author; + + public Book() { + + } + + public Book(String title, Author author) { + this.title = title; + this.author = author; + } + + public String getTitle() { + return title; + } + + public Author getAuthor() { + return author; + } + +} diff --git a/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/BookRepository.java b/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/BookRepository.java new file mode 100644 index 0000000000..f812ed088d --- /dev/null +++ b/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/BookRepository.java @@ -0,0 +1,19 @@ +package com.baeldung.graphql.data; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class BookRepository { + + private static final List books = Stream.of( + new Book("Title 1", new Author("Pero", "Peric")), + new Book("Title 2", new Author("Marko", "Maric")) + ).collect(Collectors.toList()); + + public List getAllBooks() { + return Collections.unmodifiableList(books); + } + +} diff --git a/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/Data.java b/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/Data.java new file mode 100644 index 0000000000..63263a496b --- /dev/null +++ b/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/Data.java @@ -0,0 +1,22 @@ +package com.baeldung.graphql.data; + +import java.util.Collections; +import java.util.List; + +public class Data { + + private List allBooks; + + public Data() { + + } + + public Data(List allBooks) { + this.allBooks = allBooks; + } + + public List getAllBooks() { + return Collections.unmodifiableList(allBooks); + } + +} diff --git a/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/Response.java b/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/Response.java new file mode 100644 index 0000000000..eedd13e04e --- /dev/null +++ b/graphql/graphql-java/src/main/java/com/baeldung/graphql/data/Response.java @@ -0,0 +1,19 @@ +package com.baeldung.graphql.data; + +public class Response { + + private Data data; + + public Response() { + + } + + public Response(Data data) { + this.data = data; + } + + public Data getData() { + return data; + } + +} diff --git a/graphql/graphql-java/src/main/java/com/baeldung/graphql/server/GraphQLEndpoint.java b/graphql/graphql-java/src/main/java/com/baeldung/graphql/server/GraphQLEndpoint.java new file mode 100644 index 0000000000..c69144c9f5 --- /dev/null +++ b/graphql/graphql-java/src/main/java/com/baeldung/graphql/server/GraphQLEndpoint.java @@ -0,0 +1,36 @@ +package com.baeldung.graphql.server; + +import com.baeldung.graphql.data.BookRepository; +import com.coxautodev.graphql.tools.SchemaParser; +import graphql.schema.GraphQLSchema; +import graphql.servlet.SimpleGraphQLHttpServlet; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@WebServlet(urlPatterns = "/graphql") +public class GraphQLEndpoint extends HttpServlet { + + private SimpleGraphQLHttpServlet graphQLServlet; + + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + graphQLServlet.service(req, resp); + } + + @Override + public void init() { + GraphQLSchema schema = SchemaParser.newParser() + .resolvers(new GraphQLQuery(new BookRepository())) + .file("schema.graphqls") + .build() + .makeExecutableSchema(); + graphQLServlet = SimpleGraphQLHttpServlet + .newBuilder(schema) + .build(); + } +} diff --git a/graphql/graphql-java/src/main/java/com/baeldung/graphql/server/GraphQLQuery.java b/graphql/graphql-java/src/main/java/com/baeldung/graphql/server/GraphQLQuery.java new file mode 100644 index 0000000000..8ba9fa25c5 --- /dev/null +++ b/graphql/graphql-java/src/main/java/com/baeldung/graphql/server/GraphQLQuery.java @@ -0,0 +1,21 @@ +package com.baeldung.graphql.server; + +import com.baeldung.graphql.data.Book; +import com.baeldung.graphql.data.BookRepository; +import com.coxautodev.graphql.tools.GraphQLQueryResolver; + +import java.util.List; + +public class GraphQLQuery implements GraphQLQueryResolver { + + private final BookRepository repository; + + public GraphQLQuery(BookRepository repository) { + this.repository = repository; + } + + public List allBooks() { + return repository.getAllBooks(); + } + +} diff --git a/graphql/graphql-java/src/main/resources/schema.graphqls b/graphql/graphql-java/src/main/resources/schema.graphqls new file mode 100644 index 0000000000..b0834e04b7 --- /dev/null +++ b/graphql/graphql-java/src/main/resources/schema.graphqls @@ -0,0 +1,17 @@ +type Book { + title: String! + author: Author +} + +type Author { + name: String! + surname: String! +} + +type Query { + allBooks: [Book] +} + +schema { + query: Query +} \ No newline at end of file diff --git a/graphql/graphql-java/src/test/java/com/baeldung/graphql/GraphQLMockServer.java b/graphql/graphql-java/src/test/java/com/baeldung/graphql/GraphQLMockServer.java new file mode 100644 index 0000000000..fb5a789428 --- /dev/null +++ b/graphql/graphql-java/src/test/java/com/baeldung/graphql/GraphQLMockServer.java @@ -0,0 +1,85 @@ +package com.baeldung.graphql; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.mockserver.client.MockServerClient; +import org.mockserver.integration.ClientAndServer; +import org.mockserver.model.HttpStatusCode; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.URISyntaxException; + +import static org.mockserver.integration.ClientAndServer.startClientAndServer; +import static org.mockserver.matchers.Times.exactly; +import static org.mockserver.model.HttpRequest.request; +import static org.mockserver.model.HttpResponse.response; + +public class GraphQLMockServer { + + public static ClientAndServer mockServer; + public static String serviceUrl; + + private static int serverPort; + + public static final String SERVER_ADDRESS = "127.0.0.1"; + public static final String HTTP_GET_POST = "GET"; + public static final String PATH = "/graphql"; + + @BeforeAll + static void startServer() throws IOException, URISyntaxException { + serverPort = getFreePort(); + serviceUrl = "http://" + SERVER_ADDRESS + ":" + serverPort + PATH; + mockServer = startClientAndServer(serverPort); + mockAllBooksTitleRequest(); + mockAllBooksTitleAuthorRequest(); + } + + @AfterAll + static void stopServer() { + mockServer.stop(); + } + + private static void mockAllBooksTitleAuthorRequest() { + String requestQuery = "{allBooks{title,author{name,surname}}}"; + String responseJson = "{\"data\":{\"allBooks\":[{\"title\":\"Title 1\",\"author\":{\"name\":\"Pero\",\"surname\":\"Peric\"}},{\"title\":\"Title 2\",\"author\":{\"name\":\"Marko\",\"surname\":\"Maric\"}}]}}"; + + new MockServerClient(SERVER_ADDRESS, serverPort) + .when( + request() + .withPath(PATH) + .withQueryStringParameter("query", requestQuery), + exactly(1) + ) + .respond( + response() + .withStatusCode(HttpStatusCode.OK_200.code()) + .withBody(responseJson) + ); + } + + private static void mockAllBooksTitleRequest() { + String requestQuery = "{allBooks{title}}"; + String responseJson = "{\"data\":{\"allBooks\":[{\"title\":\"Title 1\"},{\"title\":\"Title 2\"}]}}"; + + new MockServerClient(SERVER_ADDRESS, serverPort) + .when( + request() + .withPath(PATH) + .withQueryStringParameter("query", requestQuery), + exactly(1) + ) + .respond( + response() + .withStatusCode(HttpStatusCode.OK_200.code()) + .withBody(responseJson) + ); + } + + private static int getFreePort () throws IOException { + try (ServerSocket serverSocket = new ServerSocket(0)) { + return serverSocket.getLocalPort(); + } + } + +} diff --git a/graphql/graphql-java/src/test/java/com/baeldung/graphql/clients/AmericanExpressNodesUnitTest.java b/graphql/graphql-java/src/test/java/com/baeldung/graphql/clients/AmericanExpressNodesUnitTest.java new file mode 100644 index 0000000000..8466cdee76 --- /dev/null +++ b/graphql/graphql-java/src/test/java/com/baeldung/graphql/clients/AmericanExpressNodesUnitTest.java @@ -0,0 +1,39 @@ +package com.baeldung.graphql.clients; + +import com.baeldung.graphql.GraphQLMockServer; +import com.baeldung.graphql.data.Data; +import io.aexp.nodes.graphql.GraphQLResponseEntity; +import org.junit.jupiter.api.Test; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +class AmericanExpressNodesUnitTest extends GraphQLMockServer { + + @Test + void givenGraphQLEndpoint_whenRequestingAllBooksWithTitle_thenExpectedJsonIsReturned() throws IOException { + GraphQLResponseEntity responseEntity = AmericanExpressNodes.callGraphQLService(serviceUrl, "{allBooks{title}}"); + + assertAll( + () -> assertThat(responseEntity.getResponse().getAllBooks()).hasSize(2), + () -> assertThat(responseEntity.getResponse().getAllBooks().get(0).getTitle()).isEqualTo("Title 1"), + () -> assertThat(responseEntity.getResponse().getAllBooks().get(1).getTitle()).isEqualTo("Title 2") + ); + } + + @Test + void givenGraphQLEndpoint_whenRequestingAllBooksWithTitleAndAuthor_thenExpectedJsonIsReturned() throws IOException { + GraphQLResponseEntity responseEntity = AmericanExpressNodes.callGraphQLService(serviceUrl, "{allBooks{title,author{name,surname}}}"); + + assertAll( + () -> assertThat(responseEntity.getResponse().getAllBooks()).hasSize(2), + () -> assertThat(responseEntity.getResponse().getAllBooks().get(0).getTitle()).isEqualTo("Title 1"), + () -> assertThat(responseEntity.getResponse().getAllBooks().get(0).getAuthor().getFullName()).isEqualTo("Pero Peric"), + () -> assertThat(responseEntity.getResponse().getAllBooks().get(1).getTitle()).isEqualTo("Title 2"), + () -> assertThat(responseEntity.getResponse().getAllBooks().get(1).getAuthor().getFullName()).isEqualTo("Marko Maric") + ); + } + +} diff --git a/graphql/graphql-java/src/test/java/com/baeldung/graphql/clients/ApacheHttpClientUnitTest.java b/graphql/graphql-java/src/test/java/com/baeldung/graphql/clients/ApacheHttpClientUnitTest.java new file mode 100644 index 0000000000..17d97e0d14 --- /dev/null +++ b/graphql/graphql-java/src/test/java/com/baeldung/graphql/clients/ApacheHttpClientUnitTest.java @@ -0,0 +1,49 @@ +package com.baeldung.graphql.clients; + +import com.baeldung.graphql.GraphQLMockServer; +import com.baeldung.graphql.data.Response; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.io.IOUtils; +import org.apache.http.HttpResponse; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertAll; + +class ApacheHttpClientUnitTest extends GraphQLMockServer { + + private static final ObjectMapper objectMapper = new ObjectMapper(); + + @Test + void givenGraphQLEndpoint_whenRequestingAllBooksWithTitle_thenExpectedJsonIsReturned() throws IOException, URISyntaxException { + HttpResponse httpResponse = ApacheHttpClient.callGraphQLService(serviceUrl, "{allBooks{title}}"); + String actualResponse = IOUtils.toString(httpResponse.getEntity().getContent(), StandardCharsets.UTF_8.name()); + Response parsedResponse = objectMapper.readValue(actualResponse, Response.class); + + assertAll( + () -> assertThat(parsedResponse.getData().getAllBooks()).hasSize(2), + () -> assertThat(parsedResponse.getData().getAllBooks().get(0).getTitle()).isEqualTo("Title 1"), + () -> assertThat(parsedResponse.getData().getAllBooks().get(1).getTitle()).isEqualTo("Title 2") + ); + } + + @Test + void givenGraphQLEndpoint_whenRequestingAllBooksWithTitleAndAuthor_thenExpectedJsonIsReturned() throws IOException, URISyntaxException { + HttpResponse httpResponse = ApacheHttpClient.callGraphQLService(serviceUrl, "{allBooks{title,author{name,surname}}}"); + String actualResponse = IOUtils.toString(httpResponse.getEntity().getContent(), StandardCharsets.UTF_8.name()); + Response parsedResponse = objectMapper.readValue(actualResponse, Response.class); + + assertAll( + () -> assertThat(parsedResponse.getData().getAllBooks()).hasSize(2), + () -> assertThat(parsedResponse.getData().getAllBooks().get(0).getTitle()).isEqualTo("Title 1"), + () -> assertThat(parsedResponse.getData().getAllBooks().get(0).getAuthor().getFullName()).isEqualTo("Pero Peric"), + () -> assertThat(parsedResponse.getData().getAllBooks().get(1).getTitle()).isEqualTo("Title 2"), + () -> assertThat(parsedResponse.getData().getAllBooks().get(1).getAuthor().getFullName()).isEqualTo("Marko Maric") + ); + } + +} diff --git a/javax-servlets-2/README.md b/javax-servlets-2/README.md index f126f17297..9a7ad02d39 100644 --- a/javax-servlets-2/README.md +++ b/javax-servlets-2/README.md @@ -3,3 +3,4 @@ This module contains articles about Servlets. ### Relevant Articles: +- [Check if a User Is Logged-in With Servlets and JSP](https://www.baeldung.com/servlets-jsp-check-user-login) diff --git a/javax-servlets/src/main/webapp/sample.txt b/javax-servlets/src/main/webapp/WEB-INF/sample.txt similarity index 100% rename from javax-servlets/src/main/webapp/sample.txt rename to javax-servlets/src/main/webapp/WEB-INF/sample.txt diff --git a/lombok-2/src/main/java/com/baeldung/lombok/tostring/Account.java b/lombok-2/src/main/java/com/baeldung/lombok/tostring/Account.java new file mode 100644 index 0000000000..641ad1e1a3 --- /dev/null +++ b/lombok-2/src/main/java/com/baeldung/lombok/tostring/Account.java @@ -0,0 +1,56 @@ +package com.baeldung.lombok.tostring; + +import lombok.ToString; + +@ToString +public class Account { + + private String name; + + // render this field before any others (the highest ranked) + @ToString.Include(rank = 1) + private String id; + + @ToString.Exclude + private String accountNumber; + + // automatically excluded + private String $ignored; + + @ToString.Include + String description() { + return "Account description"; + } + + public String getAccountNumber() { + return accountNumber; + } + + public void setAccountNumber(String accountNumber) { + this.accountNumber = accountNumber; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String get$ignored() { + return $ignored; + } + + public void set$ignored(String value) { + this.$ignored = value; + } +} diff --git a/lombok-2/src/main/java/com/baeldung/lombok/tostring/AccountType.java b/lombok-2/src/main/java/com/baeldung/lombok/tostring/AccountType.java new file mode 100644 index 0000000000..7f99b5ca35 --- /dev/null +++ b/lombok-2/src/main/java/com/baeldung/lombok/tostring/AccountType.java @@ -0,0 +1,9 @@ +package com.baeldung.lombok.tostring; + +import lombok.ToString; + +@ToString +public enum AccountType { + CHECKING, + SAVING +} diff --git a/lombok-2/src/main/java/com/baeldung/lombok/tostring/RewardAccount.java b/lombok-2/src/main/java/com/baeldung/lombok/tostring/RewardAccount.java new file mode 100644 index 0000000000..9ac9c6afa6 --- /dev/null +++ b/lombok-2/src/main/java/com/baeldung/lombok/tostring/RewardAccount.java @@ -0,0 +1,27 @@ +package com.baeldung.lombok.tostring; + +import lombok.ToString; + +@ToString +public class RewardAccount extends Account { + + private String rewardAccountId; + + private Object[] relatedAccounts; + + public String getRewardAccountId() { + return rewardAccountId; + } + + public void setRewardAccountId(String rewardAccountId) { + this.rewardAccountId = rewardAccountId; + } + + public Object[] getRelatedAccounts() { + return relatedAccounts; + } + + public void setRelatedAccounts(Object[] relatedAccounts) { + this.relatedAccounts = relatedAccounts; + } +} diff --git a/lombok-2/src/main/java/com/baeldung/lombok/tostring/SavingAccount.java b/lombok-2/src/main/java/com/baeldung/lombok/tostring/SavingAccount.java new file mode 100644 index 0000000000..dfba31cf27 --- /dev/null +++ b/lombok-2/src/main/java/com/baeldung/lombok/tostring/SavingAccount.java @@ -0,0 +1,17 @@ +package com.baeldung.lombok.tostring; + +import lombok.ToString; + +@ToString(callSuper = true) +public class SavingAccount extends Account { + + private String savingAccountId; + + public String getSavingAccountId() { + return savingAccountId; + } + + public void setSavingAccountId(String savingAccountId) { + this.savingAccountId = savingAccountId; + } +} diff --git a/lombok-2/src/test/java/com/baeldung/lombok/tostring/ToStringUnitTest.java b/lombok-2/src/test/java/com/baeldung/lombok/tostring/ToStringUnitTest.java new file mode 100644 index 0000000000..cb56ad912d --- /dev/null +++ b/lombok-2/src/test/java/com/baeldung/lombok/tostring/ToStringUnitTest.java @@ -0,0 +1,66 @@ +package com.baeldung.lombok.tostring; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class ToStringUnitTest { + + @Test + void whenPrintObject_thenOutputIsCorrect() { + Account account = new Account(); + account.setId("12345"); + account.setName("An account"); + account.setAccountNumber("11111"); // should not be present in output + account.set$ignored("ignored value"); // should not be present in output + + assertThat(account.toString()) + .isEqualTo("Account(id=12345, name=An account, description=Account description)"); + } + + @Test + void whenPrintSubclassWithSuper_thenOutputIsCorrect() { + SavingAccount savingAccount = new SavingAccount(); + savingAccount.setSavingAccountId("5678"); + savingAccount.setId("12345"); + savingAccount.setName("An account"); + + assertThat(savingAccount.toString()) + .isEqualTo("SavingAccount(super=Account(id=12345, name=An account, description=Account description), savingAccountId=5678)"); + } + +@Test +void whenPrintArrays_thenOutputIsCorrect() { + RewardAccount account = new RewardAccount(); + account.setRewardAccountId("12345"); + + // circular ref, just for demonstration + Object[] relatedAccounts = new Object[2]; + relatedAccounts[0] = "54321"; + relatedAccounts[1] = relatedAccounts; + + account.setRelatedAccounts(relatedAccounts); + + assertThat(account.toString()) + .isEqualTo("RewardAccount(rewardAccountId=12345, relatedAccounts=[54321, [...]])"); +} + + @Test + void whenPrintSubclassWithoutSuper_thenOutputIsCorrect() { + RewardAccount rewardAccount = new RewardAccount(); + rewardAccount.setRewardAccountId("12345"); + + assertThat(rewardAccount.toString()) + .isEqualTo("RewardAccount(rewardAccountId=12345, relatedAccounts=null)"); + } + + @Test + void whenPrintEnum_thenOutputIsCorrect() { + assertThat(AccountType.CHECKING.toString()) + .isEqualTo("AccountType.CHECKING"); + + assertThat(AccountType.SAVING.toString()) + .isEqualTo("AccountType.SAVING"); + } + +} diff --git a/maven-modules/maven-classifier/README.md b/maven-modules/maven-classifier/README.md new file mode 100644 index 0000000000..ab8a7f914f --- /dev/null +++ b/maven-modules/maven-classifier/README.md @@ -0,0 +1,3 @@ +### Relevant Articles: + +- [A Guide to Maven Artifact Classifiers](https://www.baeldung.com/maven-artifact-classifiers) diff --git a/maven-modules/maven-simple/maven-profiles/pom.xml b/maven-modules/maven-simple/maven-profiles/pom.xml index 322dada104..ba915038ad 100644 --- a/maven-modules/maven-simple/maven-profiles/pom.xml +++ b/maven-modules/maven-simple/maven-profiles/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.baeldung maven-profiles - 0.0.1-SNAPSHOT + 1.0.0-SNAPSHOT maven-profiles diff --git a/maven-modules/maven-simple/parent-project/core/pom.xml b/maven-modules/maven-simple/parent-project/core/pom.xml index ec25c9ace5..8f7371639f 100644 --- a/maven-modules/maven-simple/parent-project/core/pom.xml +++ b/maven-modules/maven-simple/parent-project/core/pom.xml @@ -10,7 +10,7 @@ parent-project com.baeldung - 1.0-SNAPSHOT + 1.0.0-SNAPSHOT diff --git a/maven-modules/maven-simple/parent-project/pom.xml b/maven-modules/maven-simple/parent-project/pom.xml index a68f8e63bc..fce9aa3f72 100644 --- a/maven-modules/maven-simple/parent-project/pom.xml +++ b/maven-modules/maven-simple/parent-project/pom.xml @@ -4,14 +4,13 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 parent-project - 1.0-SNAPSHOT parent-project pom com.baeldung maven-simple - 0.0.1-SNAPSHOT + 1.0.0-SNAPSHOT diff --git a/maven-modules/maven-simple/parent-project/service/pom.xml b/maven-modules/maven-simple/parent-project/service/pom.xml index 1953ec8638..39945af248 100644 --- a/maven-modules/maven-simple/parent-project/service/pom.xml +++ b/maven-modules/maven-simple/parent-project/service/pom.xml @@ -10,7 +10,7 @@ parent-project com.baeldung - 1.0-SNAPSHOT + 1.0.0-SNAPSHOT diff --git a/maven-modules/maven-simple/parent-project/webapp/pom.xml b/maven-modules/maven-simple/parent-project/webapp/pom.xml index bd13c5aeb8..1ab1321b20 100644 --- a/maven-modules/maven-simple/parent-project/webapp/pom.xml +++ b/maven-modules/maven-simple/parent-project/webapp/pom.xml @@ -10,7 +10,7 @@ parent-project com.baeldung - 1.0-SNAPSHOT + 1.0.0-SNAPSHOT diff --git a/maven-modules/maven-simple/plugin-management/pom.xml b/maven-modules/maven-simple/plugin-management/pom.xml index 2fb2d5ed41..3c4bd886ac 100644 --- a/maven-modules/maven-simple/plugin-management/pom.xml +++ b/maven-modules/maven-simple/plugin-management/pom.xml @@ -9,7 +9,7 @@ maven-simple com.baeldung - 0.0.1-SNAPSHOT + 1.0.0-SNAPSHOT @@ -56,8 +56,8 @@ - 3.8.1 - 3.2.0 + 3.10.0 + 3.3.0 \ No newline at end of file diff --git a/maven-modules/maven-simple/plugin-management/submodule-1/pom.xml b/maven-modules/maven-simple/plugin-management/submodule-1/pom.xml index c36e092254..ff08dec9a6 100644 --- a/maven-modules/maven-simple/plugin-management/submodule-1/pom.xml +++ b/maven-modules/maven-simple/plugin-management/submodule-1/pom.xml @@ -8,7 +8,7 @@ plugin-management com.baeldung - 0.0.1-SNAPSHOT + 1.0.0-SNAPSHOT diff --git a/maven-modules/maven-simple/plugin-management/submodule-2/pom.xml b/maven-modules/maven-simple/plugin-management/submodule-2/pom.xml index e50d3cc26d..5db76cebdb 100644 --- a/maven-modules/maven-simple/plugin-management/submodule-2/pom.xml +++ b/maven-modules/maven-simple/plugin-management/submodule-2/pom.xml @@ -8,7 +8,7 @@ plugin-management com.baeldung - 0.0.1-SNAPSHOT + 1.0.0-SNAPSHOT \ No newline at end of file diff --git a/maven-modules/maven-simple/pom.xml b/maven-modules/maven-simple/pom.xml index 938e2240f8..fe59259758 100644 --- a/maven-modules/maven-simple/pom.xml +++ b/maven-modules/maven-simple/pom.xml @@ -5,6 +5,7 @@ 4.0.0 maven-simple maven-simple + 1.0.0-SNAPSHOT pom diff --git a/muleesb/pom.xml b/muleesb/pom.xml index f6cfa7d5d1..d78cebada2 100644 --- a/muleesb/pom.xml +++ b/muleesb/pom.xml @@ -108,7 +108,7 @@ org.mule.tools.maven mule-maven-plugin - 2.2.1 + ${mule-maven-plugin.version} standalone ${mule.version} @@ -203,7 +203,7 @@ mulesoft-release mulesoft release repository default - https://repository.mulesoft.org/releases/ + https://repository.mulesoft.org/nexus/content/repositories/public/ false @@ -212,9 +212,10 @@ 3.9.0 - 1.2 + 1.8 1.3.6 - 1.7 + 1.10 + 2.2.1 diff --git a/persistence-modules/java-cassandra/pom.xml b/persistence-modules/java-cassandra/pom.xml index 6df75edc56..b0b98b040a 100644 --- a/persistence-modules/java-cassandra/pom.xml +++ b/persistence-modules/java-cassandra/pom.xml @@ -50,6 +50,25 @@ + + + integration-lite-first + + + + + org.apache.maven.plugins + maven-surefire-plugin + + 1 + true + + + + + + + 3.1.2 diff --git a/persistence-modules/java-mongodb/src/main/java/com/baeldung/mongo/update/MultipleFieldsExample.java b/persistence-modules/java-mongodb/src/main/java/com/baeldung/mongo/update/MultipleFieldsExample.java index b2fcddeafb..ebc56cbfd0 100644 --- a/persistence-modules/java-mongodb/src/main/java/com/baeldung/mongo/update/MultipleFieldsExample.java +++ b/persistence-modules/java-mongodb/src/main/java/com/baeldung/mongo/update/MultipleFieldsExample.java @@ -10,35 +10,35 @@ import com.mongodb.client.result.UpdateResult; public class MultipleFieldsExample { - public static void main(String[] args) { + public static void main(String[] args) { - // - // Connect to cluster (default is localhost:27017) - // + // + // Connect to cluster (default is localhost:27017) + // - MongoClient mongoClient = new MongoClient("localhost", 27017); - MongoDatabase database = mongoClient.getDatabase("baeldung"); - MongoCollection collection = database.getCollection("employee"); + MongoClient mongoClient = new MongoClient("localhost", 27017); + MongoDatabase database = mongoClient.getDatabase("baeldung"); + MongoCollection collection = database.getCollection("employee"); - // - // Filter on the basis of employee_id - // + // + // Filter on the basis of employee_id + // - BasicDBObject searchQuery = new BasicDBObject("employee_id", 794875); + BasicDBObject searchQuery = new BasicDBObject("employee_id", 794875); - // - // Update the fields in Document - // + // + // Update the fields in Document + // - BasicDBObject updateFields = new BasicDBObject(); - updateFields.append("department_id", 3); - updateFields.append("job", "Sales Manager"); - BasicDBObject setQuery = new BasicDBObject(); - setQuery.append("$set", updateFields); - UpdateResult updateResult = collection.updateMany(searchQuery, setQuery); + BasicDBObject updateFields = new BasicDBObject(); + updateFields.append("department_id", 3); + updateFields.append("job", "Sales Manager"); + BasicDBObject setQuery = new BasicDBObject(); + setQuery.append("$set", updateFields); + UpdateResult updateResult = collection.updateMany(searchQuery, setQuery); - System.out.println("updateResult:- " + updateResult); - System.out.println("updateResult:- " + updateResult.getModifiedCount()); + System.out.println("updateResult:- " + updateResult); + System.out.println("updateResult:- " + updateResult.getModifiedCount()); - } + } } diff --git a/persistence-modules/java-mongodb/src/main/java/com/baeldung/mongo/update/UpdateMultipleFields.java b/persistence-modules/java-mongodb/src/main/java/com/baeldung/mongo/update/UpdateMultipleFields.java index 20af6d99cb..96dd086ed7 100644 --- a/persistence-modules/java-mongodb/src/main/java/com/baeldung/mongo/update/UpdateMultipleFields.java +++ b/persistence-modules/java-mongodb/src/main/java/com/baeldung/mongo/update/UpdateMultipleFields.java @@ -11,26 +11,25 @@ import com.mongodb.client.result.UpdateResult; public class UpdateMultipleFields { - public static void main(String[] args) { + public static void main(String[] args) { - // - // Connect to cluster - // + // + // Connect to cluster + // - MongoClient mongoClient = new MongoClient("localhost", 27007); - MongoDatabase database = mongoClient.getDatabase("baeldung"); - MongoCollection collection = database.getCollection("employee"); + MongoClient mongoClient = new MongoClient("localhost", 27007); + MongoDatabase database = mongoClient.getDatabase("baeldung"); + MongoCollection collection = database.getCollection("employee"); - // - // Update query - // + // + // Update query + // - UpdateResult updateResult = collection.updateMany(Filters.eq("employee_id", 794875), - Updates.combine(Updates.set("department_id", 4), Updates.set("job", "Sales Manager"))); + UpdateResult updateResult = collection.updateMany(Filters.eq("employee_id", 794875), Updates.combine(Updates.set("department_id", 4), Updates.set("job", "Sales Manager"))); - System.out.println("updateResult:- " + updateResult); - System.out.println("updateResult:- " + updateResult.getModifiedCount()); + System.out.println("updateResult:- " + updateResult); + System.out.println("updateResult:- " + updateResult.getModifiedCount()); - } + } -} \ No newline at end of file +} diff --git a/persistence-modules/java-mongodb/src/test/java/com/baeldung/update/UpdateMultipleFieldsLiveTest.java b/persistence-modules/java-mongodb/src/test/java/com/baeldung/update/UpdateMultipleFieldsLiveTest.java index d1538d5312..d06de23423 100644 --- a/persistence-modules/java-mongodb/src/test/java/com/baeldung/update/UpdateMultipleFieldsLiveTest.java +++ b/persistence-modules/java-mongodb/src/test/java/com/baeldung/update/UpdateMultipleFieldsLiveTest.java @@ -2,8 +2,6 @@ package com.baeldung.update; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertSame; import org.bson.Document; import org.junit.Before; @@ -15,7 +13,6 @@ import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Updates; -import com.mongodb.client.result.UpdateResult; public class UpdateMultipleFieldsLiveTest { @@ -30,8 +27,7 @@ public class UpdateMultipleFieldsLiveTest { db = mongoClient.getDatabase("baeldung"); collection = db.getCollection("employee"); - collection.insertOne(Document.parse( - "{'employee_id':794875,'employee_name': 'David smith','job': 'Sales Representative','department_id': 2,'salary': 20000,'hire_date': NumberLong(\"1643969311817\")}")); + collection.insertOne(Document.parse("{'employee_id':794875,'employee_name': 'David Smith','job': 'Sales Representative','department_id': 2,'salary': 20000,'hire_date': NumberLong(\"1643969311817\")}")); } } @@ -47,7 +43,8 @@ public class UpdateMultipleFieldsLiveTest { collection.updateMany(searchQuery, setQuery); - Document nameDoc = collection.find(Filters.eq("employee_id", 794875)).first(); + Document nameDoc = collection.find(Filters.eq("employee_id", 794875)) + .first(); assertNotNull(nameDoc); assertFalse(nameDoc.isEmpty()); @@ -62,10 +59,10 @@ public class UpdateMultipleFieldsLiveTest { @Test public void updateMultipleFieldsUsingDocument() { - collection.updateMany(Filters.eq("employee_id", 794875), - Updates.combine(Updates.set("department_id", 4), Updates.set("job", "Sales Manager"))); + collection.updateMany(Filters.eq("employee_id", 794875), Updates.combine(Updates.set("department_id", 4), Updates.set("job", "Sales Manager"))); - Document nameDoc = collection.find(Filters.eq("employee_id", 794875)).first(); + Document nameDoc = collection.find(Filters.eq("employee_id", 794875)) + .first(); assertNotNull(nameDoc); assertFalse(nameDoc.isEmpty()); @@ -78,3 +75,4 @@ public class UpdateMultipleFieldsLiveTest { } } + diff --git a/pom.xml b/pom.xml index edc5302390..1243eb4522 100644 --- a/pom.xml +++ b/pom.xml @@ -518,7 +518,7 @@ micronaut microprofile msf4j - + muleesb mustache mybatis @@ -1001,7 +1001,7 @@ micronaut microprofile msf4j - + muleesb mustache mybatis diff --git a/spring-cloud/spring-cloud-gateway/README.md b/spring-cloud/spring-cloud-gateway/README.md index 6b199977e3..808536ce80 100644 --- a/spring-cloud/spring-cloud-gateway/README.md +++ b/spring-cloud/spring-cloud-gateway/README.md @@ -9,3 +9,4 @@ This module contains articles about Spring Cloud Gateway - [Spring Cloud Gateway Routing Predicate Factories](https://www.baeldung.com/spring-cloud-gateway-routing-predicate-factories) - [Spring Cloud Gateway WebFilter Factories](https://www.baeldung.com/spring-cloud-gateway-webfilter-factories) - [Using Spring Cloud Gateway with OAuth 2.0 Patterns](https://www.baeldung.com/spring-cloud-gateway-oauth2) +- [URL Rewriting With Spring Cloud Gateway](https://www.baeldung.com/spring-cloud-gateway-url-rewriting) diff --git a/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2resttemplate/AppController.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2resttemplate/AppController.java new file mode 100644 index 0000000000..3c3efd950f --- /dev/null +++ b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2resttemplate/AppController.java @@ -0,0 +1,32 @@ +package com.baeldung.oauth2resttemplate; + +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; + +import java.security.Principal; +import java.util.Collection; + +@Controller +public class AppController { + + OAuth2RestTemplate restTemplate; + + public AppController(OAuth2RestTemplate restTemplate) { + this.restTemplate = restTemplate; + } + + @GetMapping("/home") + public String welcome(Model model, Principal principal) { + model.addAttribute("name", principal.getName()); + return "home"; + } + + @GetMapping("/repos") + public String repos(Model model) { + Collection repos = restTemplate.getForObject("https://api.github.com/user/repos", Collection.class); + model.addAttribute("repos", repos); + return "repositories"; + } +} diff --git a/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2resttemplate/GithubRepo.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2resttemplate/GithubRepo.java new file mode 100644 index 0000000000..48cc05c1de --- /dev/null +++ b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2resttemplate/GithubRepo.java @@ -0,0 +1,22 @@ +package com.baeldung.oauth2resttemplate; + +public class GithubRepo { + Long id; + String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2resttemplate/SecurityConfig.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2resttemplate/SecurityConfig.java new file mode 100644 index 0000000000..fa274d1c9b --- /dev/null +++ b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2resttemplate/SecurityConfig.java @@ -0,0 +1,73 @@ +package com.baeldung.oauth2resttemplate; + +import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties; +import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.Ordered; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.oauth2.client.OAuth2ClientContext; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter; +import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client; +import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; + +import javax.servlet.Filter; + +@Configuration +@EnableOAuth2Client +public class SecurityConfig extends WebSecurityConfigurerAdapter { + OAuth2ClientContext oauth2ClientContext; + + public SecurityConfig(OAuth2ClientContext oauth2ClientContext) { + this.oauth2ClientContext = oauth2ClientContext; + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authorizeRequests().antMatchers("/", "/login**", "/error**") + .permitAll().anyRequest().authenticated() + .and().logout().logoutUrl("/logout").logoutSuccessUrl("/") + .and().addFilterBefore(oauth2ClientFilter(), BasicAuthenticationFilter.class); + } + + @Bean + public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) { + FilterRegistrationBean registration = new FilterRegistrationBean<>(); + registration.setFilter(filter); + registration.setOrder(Ordered.HIGHEST_PRECEDENCE + 1); + return registration; + } + + @Bean + public OAuth2RestTemplate restTemplate() { + return new OAuth2RestTemplate(githubClient(), oauth2ClientContext); + } + + @Bean + @ConfigurationProperties("github.client") + public AuthorizationCodeResourceDetails githubClient() { + return new AuthorizationCodeResourceDetails(); + } + + private Filter oauth2ClientFilter() { + OAuth2ClientAuthenticationProcessingFilter oauth2ClientFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/github"); + OAuth2RestTemplate restTemplate = restTemplate(); + oauth2ClientFilter.setRestTemplate(restTemplate); + UserInfoTokenServices tokenServices = new UserInfoTokenServices(githubResource().getUserInfoUri(), githubClient().getClientId()); + tokenServices.setRestTemplate(restTemplate); + oauth2ClientFilter.setTokenServices(tokenServices); + return oauth2ClientFilter; + } + + @Bean + @ConfigurationProperties("github.resource") + public ResourceServerProperties githubResource() { + return new ResourceServerProperties(); + } +} diff --git a/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2resttemplate/SpringSecurityOauth2ClientApplication.java b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2resttemplate/SpringSecurityOauth2ClientApplication.java new file mode 100644 index 0000000000..846169e5bf --- /dev/null +++ b/spring-security-modules/spring-5-security-oauth/src/main/java/com/baeldung/oauth2resttemplate/SpringSecurityOauth2ClientApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.oauth2resttemplate; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.PropertySource; + +@SpringBootApplication +@PropertySource("classpath:application-oauth2-rest-template.properties") +public class SpringSecurityOauth2ClientApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringSecurityOauth2ClientApplication.class, args); + } + +} diff --git a/spring-security-modules/spring-5-security-oauth/src/main/resources/application-oauth2-rest-template.properties b/spring-security-modules/spring-5-security-oauth/src/main/resources/application-oauth2-rest-template.properties new file mode 100644 index 0000000000..15d34b76be --- /dev/null +++ b/spring-security-modules/spring-5-security-oauth/src/main/resources/application-oauth2-rest-template.properties @@ -0,0 +1,9 @@ +github.client.clientId=[CLIENT_ID] +github.client.clientSecret=[CLIENT_SECRET] +github.client.userAuthorizationUri=https://github.com/login/oauth/authorize +github.client.accessTokenUri=https://github.com/login/oauth/access_token +github.client.clientAuthenticationScheme=form + +github.resource.userInfoUri=https://api.github.com/user + +spring.thymeleaf.prefix=classpath:/templates/oauth2resttemplate/ \ No newline at end of file diff --git a/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth2resttemplate/error.html b/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth2resttemplate/error.html new file mode 100644 index 0000000000..45bcddf654 --- /dev/null +++ b/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth2resttemplate/error.html @@ -0,0 +1,9 @@ + + + + Error + + +

An error occurred.

+ + \ No newline at end of file diff --git a/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth2resttemplate/home.html b/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth2resttemplate/home.html new file mode 100644 index 0000000000..3eba3615d6 --- /dev/null +++ b/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth2resttemplate/home.html @@ -0,0 +1,18 @@ + + + + Home + + +

+ Welcome [[${name}]] +

+

+ View Repositories

+

+ +
+ +
+ + \ No newline at end of file diff --git a/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth2resttemplate/index.html b/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth2resttemplate/index.html new file mode 100644 index 0000000000..4db3b78d23 --- /dev/null +++ b/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth2resttemplate/index.html @@ -0,0 +1,16 @@ + + + + OAuth2Client + + +

+ + Go to Home + + + GitHub Login + +

+ + \ No newline at end of file diff --git a/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth2resttemplate/repositories.html b/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth2resttemplate/repositories.html new file mode 100644 index 0000000000..1eabf2270f --- /dev/null +++ b/spring-security-modules/spring-5-security-oauth/src/main/resources/templates/oauth2resttemplate/repositories.html @@ -0,0 +1,14 @@ + + + + Repositories + + +

+

Repos

+

+
    +
  • +
+ + \ No newline at end of file diff --git a/spring-security-modules/spring-security-web-boot-3/README.md b/spring-security-modules/spring-security-web-boot-3/README.md index 45fede7a4c..2f98e0f4a0 100644 --- a/spring-security-modules/spring-security-web-boot-3/README.md +++ b/spring-security-modules/spring-security-web-boot-3/README.md @@ -12,4 +12,5 @@ The "REST With Spring" Classes: http://github.learnspringsecurity.com - [Spring Security – Cache Control Headers](https://www.baeldung.com/spring-security-cache-control-headers) - [Fixing 401s with CORS Preflights and Spring Security](https://www.baeldung.com/spring-security-cors-preflight) - [Content Security Policy with Spring Security](https://www.baeldung.com/spring-security-csp) +- [Enable Logging for Spring Security](https://www.baeldung.com/spring-security-enable-logging) - More articles: [[<-- prev]](/spring-security-modules/spring-security-web-boot-2) diff --git a/spring-sleuth/pom.xml b/spring-sleuth/pom.xml index 5fd109e968..a6fba5ea56 100644 --- a/spring-sleuth/pom.xml +++ b/spring-sleuth/pom.xml @@ -39,7 +39,7 @@ - 2.0.2.RELEASE + 3.1.0 \ No newline at end of file diff --git a/spring-sleuth/src/main/java/com/baeldung/sleuth/traceid/SleuthCurrentTraceIdApp.java b/spring-sleuth/src/main/java/com/baeldung/sleuth/traceid/SleuthCurrentTraceIdApp.java new file mode 100644 index 0000000000..bae1d310a2 --- /dev/null +++ b/spring-sleuth/src/main/java/com/baeldung/sleuth/traceid/SleuthCurrentTraceIdApp.java @@ -0,0 +1,11 @@ +package com.baeldung.sleuth.traceid; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class SleuthCurrentTraceIdApp { + public static void main(String[] args) { + SpringApplication.run(SleuthCurrentTraceIdApp.class, args); + } +} diff --git a/spring-sleuth/src/main/java/com/baeldung/sleuth/traceid/SleuthTraceIdController.java b/spring-sleuth/src/main/java/com/baeldung/sleuth/traceid/SleuthTraceIdController.java new file mode 100644 index 0000000000..07dca487d0 --- /dev/null +++ b/spring-sleuth/src/main/java/com/baeldung/sleuth/traceid/SleuthTraceIdController.java @@ -0,0 +1,32 @@ +package com.baeldung.sleuth.traceid; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import brave.Span; +import brave.Tracer; + +@RestController +public class SleuthTraceIdController { + + private static final Logger logger = LoggerFactory.getLogger(SleuthTraceIdController.class); + + @Autowired + private Tracer tracer; + + @GetMapping("/traceid") + public String getSleuthTraceId() { + logger.info("Hello with Sleuth"); + Span span = tracer.currentSpan(); + if (span != null) { + logger.info("Span ID hex {}", span.context().spanIdString()); + logger.info("Span ID decimal {}", span.context().spanId()); + logger.info("Trace ID hex {}", span.context().traceIdString()); + logger.info("Trace ID decimal {}", span.context().traceId()); + } + return "Hello from Sleuth"; + } +}