diff --git a/.gitignore b/.gitignore index d22c792f43..0b6bd24070 100644 --- a/.gitignore +++ b/.gitignore @@ -124,4 +124,7 @@ devDb*.db *.xjb #neo4j -persistence-modules/neo4j/data/** \ No newline at end of file +persistence-modules/neo4j/data/** +/deep-shallow-copy/.mvn/wrapper +/deep-shallow-copy/mvnw +/deep-shallow-copy/mvnw.cmd diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/latlondistance/EquirectangularApproximation.java b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/latlondistance/EquirectangularApproximation.java new file mode 100644 index 0000000000..e42475c17e --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/latlondistance/EquirectangularApproximation.java @@ -0,0 +1,19 @@ +package com.baeldung.algorithms.latlondistance; + +public class EquirectangularApproximation { + + private static final int EARTH_RADIUS = 6371; // Approx Earth radius in KM + + public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) { + double lat1Rad = Math.toRadians(lat1); + double lat2Rad = Math.toRadians(lat2); + double lon1Rad = Math.toRadians(lon1); + double lon2Rad = Math.toRadians(lon2); + + double x = (lon2Rad - lon1Rad) * Math.cos((lat1Rad + lat2Rad) / 2); + double y = (lat2Rad - lat1Rad); + double distance = Math.sqrt(x * x + y * y) * EARTH_RADIUS; + + return distance; + } +} \ No newline at end of file diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/latlondistance/HaversineDistance.java b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/latlondistance/HaversineDistance.java new file mode 100644 index 0000000000..69074ec559 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/latlondistance/HaversineDistance.java @@ -0,0 +1,24 @@ +package com.baeldung.algorithms.latlondistance; + +public class HaversineDistance { + private static final int EARTH_RADIUS = 6371; // Approx Earth radius in KM + + public static double calculateDistance(double startLat, double startLong, + double endLat, double endLong) { + + double dLat = Math.toRadians((endLat - startLat)); + double dLong = Math.toRadians((endLong - startLong)); + + startLat = Math.toRadians(startLat); + endLat = Math.toRadians(endLat); + + double a = haversine(dLat) + Math.cos(startLat) * Math.cos(endLat) * haversine(dLong); + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + + return EARTH_RADIUS * c; + } + + public static double haversine(double val) { + return Math.pow(Math.sin(val / 2), 2); + } +} diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/latlondistance/VincentyDistance.java b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/latlondistance/VincentyDistance.java new file mode 100644 index 0000000000..7d0b0b907f --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/main/java/com/baeldung/algorithms/latlondistance/VincentyDistance.java @@ -0,0 +1,53 @@ +package com.baeldung.algorithms.latlondistance; + +public class VincentyDistance { + + // Constants for WGS84 ellipsoid model of Earth + private static final double SEMI_MAJOR_AXIS_MT = 6378137; + private static final double SEMI_MINOR_AXIS_MT = 6356752.314245; + private static final double FLATTENING = 1 / 298.257223563; + private static final double ERROR_TOLERANCE = 1e-12; + + public static double calculateDistance(double latitude1, double longitude1, double latitude2, double longitude2) { + double U1 = Math.atan((1 - FLATTENING) * Math.tan(Math.toRadians(latitude1))); + double U2 = Math.atan((1 - FLATTENING) * Math.tan(Math.toRadians(latitude2))); + + double sinU1 = Math.sin(U1); + double cosU1 = Math.cos(U1); + double sinU2 = Math.sin(U2); + double cosU2 = Math.cos(U2); + + double longitudeDifference = Math.toRadians(longitude2 - longitude1); + double previousLongitudeDifference; + + double sinSigma, cosSigma, sigma, sinAlpha, cosSqAlpha, cos2SigmaM; + + do { + sinSigma = Math.sqrt(Math.pow(cosU2 * Math.sin(longitudeDifference), 2) + + Math.pow(cosU1 * sinU2 - sinU1 * cosU2 * Math.cos(longitudeDifference), 2)); + cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * Math.cos(longitudeDifference); + sigma = Math.atan2(sinSigma, cosSigma); + sinAlpha = cosU1 * cosU2 * Math.sin(longitudeDifference) / sinSigma; + cosSqAlpha = 1 - Math.pow(sinAlpha, 2); + cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha; + if (Double.isNaN(cos2SigmaM)) { + cos2SigmaM = 0; + } + previousLongitudeDifference = longitudeDifference; + double C = FLATTENING / 16 * cosSqAlpha * (4 + FLATTENING * (4 - 3 * cosSqAlpha)); + longitudeDifference = Math.toRadians(longitude2 - longitude1) + (1 - C) * FLATTENING * sinAlpha * + (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * Math.pow(cos2SigmaM, 2)))); + } while (Math.abs(longitudeDifference - previousLongitudeDifference) > ERROR_TOLERANCE); + + double uSq = cosSqAlpha * (Math.pow(SEMI_MAJOR_AXIS_MT, 2) - Math.pow(SEMI_MINOR_AXIS_MT, 2)) / Math.pow(SEMI_MINOR_AXIS_MT, 2); + + double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq))); + double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq))); + + double deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * Math.pow(cos2SigmaM, 2)) - + B / 6 * cos2SigmaM * (-3 + 4 * Math.pow(sinSigma, 2)) * (-3 + 4 * Math.pow(cos2SigmaM, 2)))); + + double distanceMt = SEMI_MINOR_AXIS_MT * A * (sigma - deltaSigma); + return distanceMt / 1000; + } +} \ No newline at end of file diff --git a/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/latlondistance/GeoDistanceUnitTest.java b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/latlondistance/GeoDistanceUnitTest.java new file mode 100644 index 0000000000..9e72f86287 --- /dev/null +++ b/algorithms-modules/algorithms-miscellaneous-7/src/test/java/com/baeldung/algorithms/latlondistance/GeoDistanceUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.algorithms.latlondistance; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +class GeoDistanceUnitTest { + @Test + public void testCalculateDistance() { + double lat1 = 40.714268; // New York + double lon1 = -74.005974; + double lat2 = 34.0522; // Los Angeles + double lon2 = -118.2437; + + double equirectangularDistance = EquirectangularApproximation.calculateDistance(lat1, lon1, lat2, lon2); + double haversineDistance = HaversineDistance.calculateDistance(lat1, lon1, lat2, lon2); + double vincentyDistance = VincentyDistance.calculateDistance(lat1, lon1, lat2, lon2); + + double expectedDistance = 3944; + assertTrue(Math.abs(equirectangularDistance - expectedDistance) < 100); + assertTrue(Math.abs(haversineDistance - expectedDistance) < 10); + assertTrue(Math.abs(vincentyDistance - expectedDistance) < 0.5); + + } + +} \ No newline at end of file diff --git a/apache-httpclient-2/src/main/java/com/baeldung/tlsversion/ClientTlsVersionExamples.java b/apache-httpclient-2/src/main/java/com/baeldung/tlsversion/ClientTlsVersionExamples.java index c58763b1c0..818d0c3cd9 100644 --- a/apache-httpclient-2/src/main/java/com/baeldung/tlsversion/ClientTlsVersionExamples.java +++ b/apache-httpclient-2/src/main/java/com/baeldung/tlsversion/ClientTlsVersionExamples.java @@ -1,36 +1,43 @@ package com.baeldung.tlsversion; -import javax.net.ssl.SSLSocket; - -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.ssl.SSLContexts; -import org.apache.http.util.EntityUtils; - import java.io.IOException; +import javax.net.ssl.SSLSocket; + +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.config.TlsConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder; +import org.apache.hc.client5.http.io.HttpClientConnectionManager; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.core5.http.HttpEntity; +import org.apache.hc.core5.http.io.entity.EntityUtils; +import org.apache.hc.core5.http.ssl.TLS; +import org.apache.hc.core5.ssl.SSLContexts; +import org.apache.hc.core5.util.Timeout; + public class ClientTlsVersionExamples { - public static CloseableHttpClient setViaSocketFactory() { - SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( - SSLContexts.createDefault(), - new String[] { "TLSv1.2", "TLSv1.3" }, - null, - SSLConnectionSocketFactory.getDefaultHostnameVerifier()); + final HttpClientConnectionManager cm = PoolingHttpClientConnectionManagerBuilder.create() + .setDefaultTlsConfig(TlsConfig.custom() + .setHandshakeTimeout(Timeout.ofSeconds(30)) + .setSupportedProtocols(TLS.V_1_2, TLS.V_1_3) + .build()) + .build(); - return HttpClients.custom().setSSLSocketFactory(sslsf).build(); + return HttpClients.custom() + .setConnectionManager(cm) + .build(); } public static CloseableHttpClient setTlsVersionPerConnection() { SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(SSLContexts.createDefault()) { - @Override protected void prepareSocket(SSLSocket socket) { - String hostname = socket.getInetAddress().getHostName(); + String hostname = socket.getInetAddress() + .getHostName(); if (hostname.endsWith("internal.system.com")) { socket.setEnabledProtocols(new String[] { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" }); } else { @@ -39,7 +46,14 @@ public class ClientTlsVersionExamples { } }; - return HttpClients.custom().setSSLSocketFactory(sslsf).build(); + HttpClientConnectionManager connManager = PoolingHttpClientConnectionManagerBuilder.create() + .setSSLSocketFactory(sslsf) + .build(); + + return HttpClients.custom() + .setConnectionManager(connManager) + .build(); + } // To configure the TLS versions for the client, set the https.protocols system property during runtime. @@ -47,15 +61,11 @@ public class ClientTlsVersionExamples { public static CloseableHttpClient setViaSystemProperties() { return HttpClients.createSystem(); // Alternatively: - // return HttpClients.custom().useSystemProperties().build(); + //return HttpClients.custom().useSystemProperties().build(); } public static void main(String[] args) throws IOException { - // Alternatively: - // CloseableHttpClient httpClient = setTlsVersionPerConnection(); - // CloseableHttpClient httpClient = setViaSystemProperties(); - try (CloseableHttpClient httpClient = setViaSocketFactory(); - CloseableHttpResponse response = httpClient.execute(new HttpGet("https://httpbin.org/"))) { + try (CloseableHttpClient httpClient = setViaSocketFactory(); CloseableHttpResponse response = httpClient.execute(new HttpGet("https://httpbin.org/"))) { HttpEntity entity = response.getEntity(); EntityUtils.consume(entity); diff --git a/apache-httpclient/src/test/java/com/baeldung/httpclient/advancedconfig/HttpClientAdvancedConfigurationIntegrationTest.java b/apache-httpclient/src/test/java/com/baeldung/httpclient/advancedconfig/HttpClientAdvancedConfigurationIntegrationTest.java index 2235d0e9d0..3f2c1328e8 100644 --- a/apache-httpclient/src/test/java/com/baeldung/httpclient/advancedconfig/HttpClientAdvancedConfigurationIntegrationTest.java +++ b/apache-httpclient/src/test/java/com/baeldung/httpclient/advancedconfig/HttpClientAdvancedConfigurationIntegrationTest.java @@ -1,29 +1,5 @@ package com.baeldung.httpclient.advancedconfig; - -import com.github.tomakehurst.wiremock.junit.WireMockRule; -import org.apache.http.HttpHeaders; -import org.apache.http.HttpHost; -import org.apache.http.HttpResponse; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.AuthCache; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.entity.StringEntity; -import org.apache.http.impl.auth.BasicScheme; -import org.apache.http.impl.client.BasicAuthCache; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.conn.DefaultProxyRoutePlanner; -import org.junit.Rule; -import org.junit.Test; - -import java.io.IOException; - import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.client.WireMock.containing; import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; @@ -34,6 +10,30 @@ import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; import static org.junit.Assert.assertEquals; +import java.io.IOException; + +import org.apache.hc.client5.http.auth.AuthCache; +import org.apache.hc.client5.http.auth.AuthScope; +import org.apache.hc.client5.http.auth.CredentialsProvider; +import org.apache.hc.client5.http.auth.StandardAuthScheme; +import org.apache.hc.client5.http.classic.HttpClient; +import org.apache.hc.client5.http.classic.methods.HttpGet; +import org.apache.hc.client5.http.classic.methods.HttpPost; +import org.apache.hc.client5.http.impl.auth.BasicAuthCache; +import org.apache.hc.client5.http.impl.auth.BasicScheme; +import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner; +import org.apache.hc.client5.http.protocol.HttpClientContext; +import org.apache.hc.core5.http.HttpHeaders; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.HttpResponse; +import org.apache.hc.core5.http.io.entity.StringEntity; +import org.junit.Rule; +import org.junit.Test; + +import com.github.tomakehurst.wiremock.junit.WireMockRule; + public class HttpClientAdvancedConfigurationIntegrationTest { @Rule @@ -59,7 +59,7 @@ public class HttpClientAdvancedConfigurationIntegrationTest { HttpResponse response = httpClient.execute(httpGet); //then - assertEquals(response.getStatusLine().getStatusCode(), 200); + assertEquals(response.getCode(), 200); } @Test @@ -82,7 +82,7 @@ public class HttpClientAdvancedConfigurationIntegrationTest { HttpResponse response = httpClient.execute(httpPost); //then - assertEquals(response.getStatusLine().getStatusCode(), 200); + assertEquals(response.getCode(), 200); } @@ -107,7 +107,7 @@ public class HttpClientAdvancedConfigurationIntegrationTest { HttpResponse response = httpclient.execute(httpGet); //then - assertEquals(response.getStatusLine().getStatusCode(), 200); + assertEquals(response.getCode(), 200); proxyMock.verify(getRequestedFor(urlEqualTo("/private"))); serviceMock.verify(getRequestedFor(urlEqualTo("/private"))); } @@ -125,14 +125,12 @@ public class HttpClientAdvancedConfigurationIntegrationTest { DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy); // Client credentials - CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(new AuthScope(proxy), - new UsernamePasswordCredentials("username_admin", "secret_password")); - + CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create() + .add(new AuthScope(proxy), "username_admin", "secret_password".toCharArray()) + .build(); // Create AuthCache instance AuthCache authCache = new BasicAuthCache(); - // Generate BASIC scheme object and add it to the local auth cache BasicScheme basicAuth = new BasicScheme(); authCache.put(proxy, basicAuth); @@ -149,10 +147,11 @@ public class HttpClientAdvancedConfigurationIntegrationTest { //when final HttpGet httpGet = new HttpGet("http://localhost:8089/private"); + httpGet.setHeader("Authorization", StandardAuthScheme.BASIC); HttpResponse response = httpclient.execute(httpGet, context); //then - assertEquals(response.getStatusLine().getStatusCode(), 200); + assertEquals(response.getCode(), 200); proxyMock.verify(getRequestedFor(urlEqualTo("/private")).withHeader("Authorization", containing("Basic"))); serviceMock.verify(getRequestedFor(urlEqualTo("/private"))); } diff --git a/apache-httpclient4/src/main/java/com/baeldung/tlsversion/ClientTlsVersionExamples.java b/apache-httpclient4/src/main/java/com/baeldung/tlsversion/ClientTlsVersionExamples.java new file mode 100644 index 0000000000..c58763b1c0 --- /dev/null +++ b/apache-httpclient4/src/main/java/com/baeldung/tlsversion/ClientTlsVersionExamples.java @@ -0,0 +1,64 @@ +package com.baeldung.tlsversion; + +import javax.net.ssl.SSLSocket; + +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.ssl.SSLContexts; +import org.apache.http.util.EntityUtils; + +import java.io.IOException; + +public class ClientTlsVersionExamples { + + public static CloseableHttpClient setViaSocketFactory() { + SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( + SSLContexts.createDefault(), + new String[] { "TLSv1.2", "TLSv1.3" }, + null, + SSLConnectionSocketFactory.getDefaultHostnameVerifier()); + + return HttpClients.custom().setSSLSocketFactory(sslsf).build(); + } + + public static CloseableHttpClient setTlsVersionPerConnection() { + SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(SSLContexts.createDefault()) { + + @Override + protected void prepareSocket(SSLSocket socket) { + String hostname = socket.getInetAddress().getHostName(); + if (hostname.endsWith("internal.system.com")) { + socket.setEnabledProtocols(new String[] { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" }); + } else { + socket.setEnabledProtocols(new String[] { "TLSv1.3" }); + } + } + }; + + return HttpClients.custom().setSSLSocketFactory(sslsf).build(); + } + + // To configure the TLS versions for the client, set the https.protocols system property during runtime. + // For example: java -Dhttps.protocols=TLSv1.1,TLSv1.2,TLSv1.3 -jar webClient.jar + public static CloseableHttpClient setViaSystemProperties() { + return HttpClients.createSystem(); + // Alternatively: + // return HttpClients.custom().useSystemProperties().build(); + } + + public static void main(String[] args) throws IOException { + // Alternatively: + // CloseableHttpClient httpClient = setTlsVersionPerConnection(); + // CloseableHttpClient httpClient = setViaSystemProperties(); + try (CloseableHttpClient httpClient = setViaSocketFactory(); + CloseableHttpResponse response = httpClient.execute(new HttpGet("https://httpbin.org/"))) { + + HttpEntity entity = response.getEntity(); + EntityUtils.consume(entity); + } + } +} \ No newline at end of file diff --git a/apache-httpclient4/src/test/java/com/baeldung/httpclient/advancedconfig/HttpClientAdvancedConfigurationIntegrationTest.java b/apache-httpclient4/src/test/java/com/baeldung/httpclient/advancedconfig/HttpClientAdvancedConfigurationIntegrationTest.java new file mode 100644 index 0000000000..2235d0e9d0 --- /dev/null +++ b/apache-httpclient4/src/test/java/com/baeldung/httpclient/advancedconfig/HttpClientAdvancedConfigurationIntegrationTest.java @@ -0,0 +1,161 @@ +package com.baeldung.httpclient.advancedconfig; + + +import com.github.tomakehurst.wiremock.junit.WireMockRule; +import org.apache.http.HttpHeaders; +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.auth.AuthScope; +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.client.AuthCache; +import org.apache.http.client.CredentialsProvider; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.auth.BasicScheme; +import org.apache.http.impl.client.BasicAuthCache; +import org.apache.http.impl.client.BasicCredentialsProvider; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.conn.DefaultProxyRoutePlanner; +import org.junit.Rule; +import org.junit.Test; + +import java.io.IOException; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.containing; +import static com.github.tomakehurst.wiremock.client.WireMock.equalTo; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; +import static com.github.tomakehurst.wiremock.client.WireMock.post; +import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; +import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; +import static org.junit.Assert.assertEquals; + +public class HttpClientAdvancedConfigurationIntegrationTest { + + @Rule + public WireMockRule serviceMock = new WireMockRule(8089); + + @Rule + public WireMockRule proxyMock = new WireMockRule(8090); + + @Test + public void givenClientWithCustomUserAgentHeader_whenExecuteRequest_shouldReturn200() throws IOException { + //given + String userAgent = "BaeldungAgent/1.0"; + serviceMock.stubFor(get(urlEqualTo("/detail")) + .withHeader("User-Agent", equalTo(userAgent)) + .willReturn(aResponse() + .withStatus(200))); + + HttpClient httpClient = HttpClients.createDefault(); + HttpGet httpGet = new HttpGet("http://localhost:8089/detail"); + httpGet.setHeader(HttpHeaders.USER_AGENT, userAgent); + + //when + HttpResponse response = httpClient.execute(httpGet); + + //then + assertEquals(response.getStatusLine().getStatusCode(), 200); + } + + @Test + public void givenClientThatSendDataInBody_whenSendXmlInBody_shouldReturn200() throws IOException { + //given + String xmlBody = "1"; + serviceMock.stubFor(post(urlEqualTo("/person")) + .withHeader("Content-Type", equalTo("application/xml")) + .withRequestBody(equalTo(xmlBody)) + .willReturn(aResponse() + .withStatus(200))); + + HttpClient httpClient = HttpClients.createDefault(); + HttpPost httpPost = new HttpPost("http://localhost:8089/person"); + httpPost.setHeader("Content-Type", "application/xml"); + StringEntity xmlEntity = new StringEntity(xmlBody); + httpPost.setEntity(xmlEntity); + + //when + HttpResponse response = httpClient.execute(httpPost); + + //then + assertEquals(response.getStatusLine().getStatusCode(), 200); + + } + + @Test + public void givenServerThatIsBehindProxy_whenClientIsConfiguredToSendRequestViaProxy_shouldReturn200() throws IOException { + //given + proxyMock.stubFor(get(urlMatching(".*")) + .willReturn(aResponse().proxiedFrom("http://localhost:8089/"))); + + serviceMock.stubFor(get(urlEqualTo("/private")) + .willReturn(aResponse().withStatus(200))); + + + HttpHost proxy = new HttpHost("localhost", 8090); + DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy); + HttpClient httpclient = HttpClients.custom() + .setRoutePlanner(routePlanner) + .build(); + + //when + final HttpGet httpGet = new HttpGet("http://localhost:8089/private"); + HttpResponse response = httpclient.execute(httpGet); + + //then + assertEquals(response.getStatusLine().getStatusCode(), 200); + proxyMock.verify(getRequestedFor(urlEqualTo("/private"))); + serviceMock.verify(getRequestedFor(urlEqualTo("/private"))); + } + + @Test + public void givenServerThatIsBehindAuthorizationProxy_whenClientSendRequest_shouldAuthorizeProperly() throws IOException { + //given + proxyMock.stubFor(get(urlMatching("/private")) + .willReturn(aResponse().proxiedFrom("http://localhost:8089/"))); + serviceMock.stubFor(get(urlEqualTo("/private")) + .willReturn(aResponse().withStatus(200))); + + + HttpHost proxy = new HttpHost("localhost", 8090); + DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy); + + // Client credentials + CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(new AuthScope(proxy), + new UsernamePasswordCredentials("username_admin", "secret_password")); + + + // Create AuthCache instance + AuthCache authCache = new BasicAuthCache(); + + // Generate BASIC scheme object and add it to the local auth cache + BasicScheme basicAuth = new BasicScheme(); + authCache.put(proxy, basicAuth); + HttpClientContext context = HttpClientContext.create(); + context.setCredentialsProvider(credentialsProvider); + context.setAuthCache(authCache); + + + HttpClient httpclient = HttpClients.custom() + .setRoutePlanner(routePlanner) + .setDefaultCredentialsProvider(credentialsProvider) + .build(); + + + //when + final HttpGet httpGet = new HttpGet("http://localhost:8089/private"); + HttpResponse response = httpclient.execute(httpGet, context); + + //then + assertEquals(response.getStatusLine().getStatusCode(), 200); + proxyMock.verify(getRequestedFor(urlEqualTo("/private")).withHeader("Authorization", containing("Basic"))); + serviceMock.verify(getRequestedFor(urlEqualTo("/private"))); + } + + +} diff --git a/apache-kafka-2/README.md b/apache-kafka-2/README.md index 81239d4a7b..dc675a0811 100644 --- a/apache-kafka-2/README.md +++ b/apache-kafka-2/README.md @@ -12,3 +12,4 @@ You can build the project from the command line using: *mvn clean install*, or i - [Is a Key Required as Part of Sending Messages to Kafka?](https://www.baeldung.com/java-kafka-message-key) - [Read Data From the Beginning Using Kafka Consumer API](https://www.baeldung.com/java-kafka-consumer-api-read) - [Get Partition Count for a Topic in Kafka](https://www.baeldung.com/java-kafka-partition-count-topic) +- [bootstrap-server in Kafka Configuration](https://www.baeldung.com/java-kafka-bootstrap-server) diff --git a/apache-kafka-2/src/main/java/com/baeldung/kafka/consumer/SimpleConsumerWithBootStrapServers.java b/apache-kafka-2/src/main/java/com/baeldung/kafka/consumer/SimpleConsumerWithBootStrapServers.java new file mode 100644 index 0000000000..7501b40056 --- /dev/null +++ b/apache-kafka-2/src/main/java/com/baeldung/kafka/consumer/SimpleConsumerWithBootStrapServers.java @@ -0,0 +1,39 @@ +package com.baeldung.kafka.consumer; + +import org.apache.kafka.clients.consumer.*; +import org.apache.kafka.common.serialization.LongDeserializer; +import org.apache.kafka.common.serialization.StringDeserializer; + +import java.time.Duration; +import java.util.Arrays; +import java.util.Properties; + +public class SimpleConsumerWithBootStrapServers { + + public static void main(String[] args) { + try(final Consumer consumer = createConsumer()) { + ConsumerRecords records = consumer.poll(Duration.ofMinutes(1)); + for(ConsumerRecord record : records) { + System.out.println(record.value()); + } + } + } + + private static Consumer createConsumer() { + final Properties props = new Properties(); + props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, + "localhost:9092,another-host.com:29092"); + props.put(ConsumerConfig.GROUP_ID_CONFIG, + "MySampleConsumer"); + props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, + LongDeserializer.class.getName()); + props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, + StringDeserializer.class.getName()); + // Create the consumer using props. + final Consumer consumer = new KafkaConsumer(props); + // Subscribe to the topic. + consumer.subscribe(Arrays.asList("samples")); + return consumer; + } + +} diff --git a/apache-libraries-2/README.md b/apache-libraries-2/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apache-libraries-2/pom.xml b/apache-libraries-2/pom.xml new file mode 100644 index 0000000000..618ff4a188 --- /dev/null +++ b/apache-libraries-2/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + apache-libraries-2 + 0.0.1-SNAPSHOT + apache-libraries-2 + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + javax.validation + validation-api + ${javax.validation.validation-api.version} + + + + + + 2.0.1.Final + + + \ No newline at end of file diff --git a/apache-libraries-2/src/main/java/com/baeldung/xslt/XSLTProcessor.java b/apache-libraries-2/src/main/java/com/baeldung/xslt/XSLTProcessor.java new file mode 100644 index 0000000000..6bc0023485 --- /dev/null +++ b/apache-libraries-2/src/main/java/com/baeldung/xslt/XSLTProcessor.java @@ -0,0 +1,18 @@ +package com.baeldung.xslt; + +import javax.xml.transform.*; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; +import java.io.File; + +public class XSLTProcessor { + public static void transformXMLUsingXSLT(String inputXMLPath, String xsltPath, String outputHTMLPath) throws TransformerException { + Source xmlSource = new StreamSource(new File(inputXMLPath)); + Source xsltSource = new StreamSource(new File(xsltPath)); + Result output = new StreamResult(new File(outputHTMLPath)); + + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + Transformer transformer = transformerFactory.newTransformer(xsltSource); + transformer.transform(xmlSource, output); + } +} diff --git a/apache-libraries-2/src/main/resources/avroHttpRequest-schema.avsc b/apache-libraries-2/src/main/resources/avroHttpRequest-schema.avsc new file mode 100644 index 0000000000..18179a9cde --- /dev/null +++ b/apache-libraries-2/src/main/resources/avroHttpRequest-schema.avsc @@ -0,0 +1,47 @@ +{ + "type":"record", + "name":"AvroHttpRequest", + "namespace":"com.baeldung.avro.model", + "fields":[ + { + "name":"requestTime", + "type":"long" + }, + { + "name":"clientIdentifier", + "type":{ + "type":"record", + "name":"ClientIdentifier", + "fields":[ + { + "name":"hostName", + "type":"string" + }, + { + "name":"ipAddress", + "type":"string" + } + ] + } + }, + { + "name":"employeeNames", + "type":{ + "type":"array", + "items":"string" + }, + "default":null + }, + { + "name":"active", + "type":{ + "type":"enum", + "name":"Active", + "symbols":[ + "YES", + "NO" + ] + } + } + ] +} \ No newline at end of file diff --git a/apache-libraries-2/src/main/resources/log4j2.xml b/apache-libraries-2/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..d1ea5173fa --- /dev/null +++ b/apache-libraries-2/src/main/resources/log4j2.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core-java-modules/pre-jpms/src/main/resources/logback.xml b/apache-libraries-2/src/main/resources/logback.xml similarity index 55% rename from core-java-modules/pre-jpms/src/main/resources/logback.xml rename to apache-libraries-2/src/main/resources/logback.xml index 7c5914e58e..7d900d8ea8 100644 --- a/core-java-modules/pre-jpms/src/main/resources/logback.xml +++ b/apache-libraries-2/src/main/resources/logback.xml @@ -1,10 +1,13 @@ + - [%level] %msg%n + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + - + + \ No newline at end of file diff --git a/apache-libraries-2/src/test/java/com/baeldung/xslt/XSLTProcessorUnitTest.java b/apache-libraries-2/src/test/java/com/baeldung/xslt/XSLTProcessorUnitTest.java new file mode 100644 index 0000000000..cbfbf78c87 --- /dev/null +++ b/apache-libraries-2/src/test/java/com/baeldung/xslt/XSLTProcessorUnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.xslt; + +import org.junit.jupiter.api.Test; + +import javax.xml.transform.TransformerException; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class XSLTProcessorUnitTest { + + @Test + public void givenValidInputAndStylesheet_whenTransformingXML_thenOutputHTMLCreated() throws TransformerException, IOException { + // Given + String inputXMLPath = "src/test/resources/input.xml"; + String xsltPath = "src/test/resources/stylesheet.xslt"; + String outputHTMLPath = "src/test/resources/output.html"; + + + XSLTProcessor.transformXMLUsingXSLT(inputXMLPath, xsltPath, outputHTMLPath); + + + Path outputFile = Paths.get(outputHTMLPath); + assertTrue(Files.exists(outputFile)); + } +} diff --git a/apache-libraries-2/src/test/resources/input.xml b/apache-libraries-2/src/test/resources/input.xml new file mode 100644 index 0000000000..e283680337 --- /dev/null +++ b/apache-libraries-2/src/test/resources/input.xml @@ -0,0 +1,11 @@ + + + + John Doe + 30 + + + Jane Smith + 25 + + diff --git a/apache-libraries-2/src/test/resources/output.html b/apache-libraries-2/src/test/resources/output.html new file mode 100644 index 0000000000..b75e73ca15 --- /dev/null +++ b/apache-libraries-2/src/test/resources/output.html @@ -0,0 +1,3 @@ + +

Male person: John Doe, Age: 30

+

Female person: Jane Smith, Age: 25

diff --git a/apache-libraries-2/src/test/resources/stylesheet.xslt b/apache-libraries-2/src/test/resources/stylesheet.xslt new file mode 100644 index 0000000000..9f07852a2a --- /dev/null +++ b/apache-libraries-2/src/test/resources/stylesheet.xslt @@ -0,0 +1,22 @@ + + + + + + Male person: + + , Age: + + + + + + + Female person: + + , Age: + + + + + diff --git a/apache-poi-2/README.md b/apache-poi-2/README.md index 0132147201..65641e7c37 100644 --- a/apache-poi-2/README.md +++ b/apache-poi-2/README.md @@ -13,4 +13,5 @@ This module contains articles about Apache POI. - [Setting Formulas in Excel with Apache POI](https://www.baeldung.com/java-apache-poi-set-formulas) - [Set the Date Format Using Apache POI](https://www.baeldung.com/java-apache-poi-date-format) - [Replacing Variables in a Document Template with Java](https://www.baeldung.com/java-replace-pattern-word-document-doc-docx) +- [Lock Header Rows With Apache POI](https://www.baeldung.com/java-apache-poi-lock-header-rows) - More articles: [[<-- prev]](../apache-poi) diff --git a/apache-poi-2/src/main/java/com/baeldung/poi/excel/locksheet/LockSheet.java b/apache-poi-2/src/main/java/com/baeldung/poi/excel/locksheet/LockSheet.java new file mode 100644 index 0000000000..23df04065d --- /dev/null +++ b/apache-poi-2/src/main/java/com/baeldung/poi/excel/locksheet/LockSheet.java @@ -0,0 +1,19 @@ +package com.baeldung.poi.excel.locksheet; + +import org.apache.poi.ss.usermodel.*; + +public class LockSheet { + + public void lockFirstRow(Sheet sheet) { + sheet.createFreezePane(0, 1); + } + + public void lockTwoRows(Sheet sheet) { + sheet.createFreezePane(0, 2); + } + + public void lockFirstColumn(Sheet sheet) { + sheet.createFreezePane(1, 0); + } + +} \ No newline at end of file diff --git a/apache-poi-2/src/test/java/com/baeldung/poi/excel/locksheet/LockSheetUnitTest.java b/apache-poi-2/src/test/java/com/baeldung/poi/excel/locksheet/LockSheetUnitTest.java new file mode 100644 index 0000000000..5fe8a9ea4b --- /dev/null +++ b/apache-poi-2/src/test/java/com/baeldung/poi/excel/locksheet/LockSheetUnitTest.java @@ -0,0 +1,53 @@ +package com.baeldung.poi.excel.locksheet; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.io.IOException; + +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.junit.jupiter.api.*; + +class LockSheetUnitTest { + + private LockSheet lockSheet; + private Workbook workbook; + private Sheet sheet; + + @BeforeEach + void setup() { + workbook = new XSSFWorkbook(); + sheet = workbook.createSheet(); + Row row = sheet.createRow(0); + row.createCell(0).setCellValue("row 1 col 1"); + row.createCell(1).setCellValue("row 1 col 2"); + row = sheet.createRow(1); + row.createCell(0).setCellValue("row 2 col 1"); + row.createCell(1).setCellValue("row 2 col 2"); + lockSheet = new LockSheet(); + } + + @AfterEach + void cleanup() throws IOException { + workbook.close(); + } + + @Test + void whenLockFirstRow_thenFirstRowIsLocked() { + lockSheet.lockFirstRow(sheet); + assertEquals(sheet.getPaneInformation().getHorizontalSplitPosition(), 1); + } + + @Test + void whenLockTwoRows_thenTwoRowsAreLocked() { + lockSheet.lockTwoRows(sheet); + assertEquals(sheet.getPaneInformation().getHorizontalSplitPosition(), 2); + } + + @Test + void whenLockFirstColumn_thenFirstColumnIsLocked() { + lockSheet.lockFirstColumn(sheet); + assertEquals(sheet.getPaneInformation().getVerticalSplitPosition(), 1); + } + +} \ No newline at end of file diff --git a/aws-modules/aws-s3-update-object/pom.xml b/aws-modules/aws-s3-update-object/pom.xml new file mode 100644 index 0000000000..574a63977b --- /dev/null +++ b/aws-modules/aws-s3-update-object/pom.xml @@ -0,0 +1,42 @@ + + + 4.0.0 + aws-s3-update-object + 0.0.1-SNAPSHOT + aws-s3-update-object + Project demonstrating overwriting of S3 objects + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-test + test + + + com.amazonaws + aws-java-sdk + ${aws-java-sdk-version} + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + 1.12.523 + + diff --git a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/AwsS3UpdateObjectApplication.java b/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/AwsS3UpdateObjectApplication.java new file mode 100644 index 0000000000..24866c287b --- /dev/null +++ b/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/AwsS3UpdateObjectApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.awss3updateobject; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AwsS3UpdateObjectApplication { + + public static void main(String[] args) { + SpringApplication.run(AwsS3UpdateObjectApplication.class, args); + } + +} diff --git a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/controller/FileController.java b/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/controller/FileController.java new file mode 100644 index 0000000000..e87358ef56 --- /dev/null +++ b/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/controller/FileController.java @@ -0,0 +1,24 @@ +package com.baeldung.awss3updateobject.controller; + +import com.baeldung.awss3updateobject.service.FileService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +@RestController +@RequestMapping("api/v1/file") +public class FileController { + + @Autowired + FileService fileService; + + @PostMapping("/upload") + public String uploadFile(@RequestParam("file") MultipartFile multipartFile) throws Exception { + return this.fileService.uploadFile(multipartFile); + } + + @PostMapping("/update") + public String updateFile(@RequestParam("file") MultipartFile multipartFile, @RequestParam("filePath") String exitingFilePath) throws Exception { + return this.fileService.updateFile(multipartFile, exitingFilePath); + } +} diff --git a/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/service/FileService.java b/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/service/FileService.java new file mode 100644 index 0000000000..23eaad7913 --- /dev/null +++ b/aws-modules/aws-s3-update-object/src/main/java/com/baeldung/awss3updateobject/service/FileService.java @@ -0,0 +1,80 @@ +package com.baeldung.awss3updateobject.service; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.regions.Regions; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.amazonaws.services.s3.model.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.PostConstruct; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +@Service +public class FileService { + + private static final Logger logger = LoggerFactory.getLogger(FileService.class); + + public AmazonS3 amazonS3; + + @Value("${aws.s3bucket}") + public String awsS3Bucket; + + @PostConstruct + private void init(){ + AWSCredentials credentials = new BasicAWSCredentials( + "AWS AccessKey", + "AWS secretKey" + ); + this.amazonS3 = AmazonS3ClientBuilder.standard() + .withRegion(Regions.fromName("us-east-1")) + .withCredentials(new AWSStaticCredentialsProvider(credentials)) + .build(); + } + + public String uploadFile(MultipartFile multipartFile) throws Exception { + String key = "/documents/" + multipartFile.getOriginalFilename(); + return this.uploadDocument(this.awsS3Bucket, key, multipartFile); + } + + public String updateFile(MultipartFile multipartFile, String key) throws Exception { + return this.uploadDocument(this.awsS3Bucket, key, multipartFile); + } + + private String uploadDocument(String s3bucket, String key, MultipartFile multipartFile) throws Exception { + try { + ObjectMetadata metadata = new ObjectMetadata(); + metadata.setContentType(multipartFile.getContentType()); + Map attributes = new HashMap<>(); + attributes.put("document-content-size", String.valueOf(multipartFile.getSize())); + metadata.setUserMetadata(attributes); + InputStream documentStream = multipartFile.getInputStream(); + PutObjectResult putObjectResult = this.amazonS3.putObject(new PutObjectRequest(s3bucket, key, documentStream, metadata)); + + S3Object s3Object = this.amazonS3.getObject(s3bucket, key); + logger.info("Last Modified: " + s3Object.getObjectMetadata().getLastModified()); + return key; + } catch (AmazonS3Exception ex) { + if (ex.getErrorCode().equalsIgnoreCase("NoSuchBucket")) { + String msg = String.format("No bucket found with name %s", s3bucket); + throw new Exception(msg); + } else if (ex.getErrorCode().equalsIgnoreCase("AccessDenied")) { + String msg = String.format("Access denied to S3 bucket %s", s3bucket); + throw new Exception(msg); + } + throw ex; + } catch (IOException ex) { + String msg = String.format("Error saving file %s to AWS S3 bucket %s", key, s3bucket); + throw new Exception(msg); + } + } +} diff --git a/aws-modules/aws-s3-update-object/src/main/resources/application.properties b/aws-modules/aws-s3-update-object/src/main/resources/application.properties new file mode 100644 index 0000000000..c840d970a8 --- /dev/null +++ b/aws-modules/aws-s3-update-object/src/main/resources/application.properties @@ -0,0 +1 @@ +aws.s3bucket=baeldung-documents; diff --git a/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/controller/FileControllerUnitTest.java b/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/controller/FileControllerUnitTest.java new file mode 100644 index 0000000000..823391c139 --- /dev/null +++ b/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/controller/FileControllerUnitTest.java @@ -0,0 +1,62 @@ +package com.baeldung.awss3updateobject.controller; + +import com.baeldung.awss3updateobject.service.FileService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.multipart.MultipartFile; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; + +public class FileControllerUnitTest { + + private MockMvc mockMvc; + + @Mock + private FileService fileService; + + @InjectMocks + private FileController fileController; + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + this.mockMvc = MockMvcBuilders.standaloneSetup(fileController).build(); + } + + @Test + public void givenValidMultipartFile_whenUploadedViaEndpoint_thenCorrectPathIsReturned() throws Exception { + MockMultipartFile multipartFile = new MockMultipartFile("file", "test.txt", "text/plain", "sample file content".getBytes()); + String expectedResult = "File Uploaded Successfully"; + + when(fileService.uploadFile(multipartFile)).thenReturn(expectedResult); + + mockMvc.perform(multipart("/api/v1/file/upload").file(multipartFile)) + .andExpect(status().isOk()) + .andExpect(content().string(expectedResult)); + } + + @Test + public void givenValidMultipartFileAndExistingPath_whenUpdatedViaEndpoint_thenSamePathIsReturned() throws Exception { + MockMultipartFile multipartFile = new MockMultipartFile("file", "test.txt", "text/plain", "updated file content".getBytes()); + String filePath = "some/path/to/file"; + String expectedResult = "File Updated Successfully"; + + when(fileService.updateFile(multipartFile, filePath)).thenReturn(expectedResult); + + mockMvc.perform(multipart("/api/v1/file/update") + .file(multipartFile) + .param("filePath", filePath)) + .andExpect(status().isOk()) + .andExpect(content().string(expectedResult)); + } +} \ No newline at end of file diff --git a/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/service/FileServiceUnitTest.java b/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/service/FileServiceUnitTest.java new file mode 100644 index 0000000000..90ed77b148 --- /dev/null +++ b/aws-modules/aws-s3-update-object/src/test/java/com/baeldung/awss3updateobject/service/FileServiceUnitTest.java @@ -0,0 +1,99 @@ +package com.baeldung.awss3updateobject.service; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.AmazonS3Exception; +import com.amazonaws.services.s3.model.PutObjectRequest; +import com.amazonaws.services.s3.model.S3Object; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.io.InputStream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +public class FileServiceUnitTest { + + @Mock + private AmazonS3 amazonS3; + + @Mock + private MultipartFile multipartFile; + + @InjectMocks + private FileService fileService; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + fileService = new FileService(); + fileService.awsS3Bucket = "test-bucket"; + fileService.amazonS3 = amazonS3; + } + + @Test + public void givenValidFile_whenUploaded_thenKeyMatchesDocumentPath() throws Exception { + when(multipartFile.getName()).thenReturn("testFile"); + when(multipartFile.getOriginalFilename()).thenReturn("testFile"); + when(multipartFile.getContentType()).thenReturn("application/pdf"); + when(multipartFile.getSize()).thenReturn(1024L); + when(multipartFile.getInputStream()).thenReturn(mock(InputStream.class)); + + S3Object s3Object = new S3Object(); + when(amazonS3.putObject(any())).thenReturn(null); + when(amazonS3.getObject(anyString(), anyString())).thenReturn(s3Object); + + String key = fileService.uploadFile(multipartFile); + + assertEquals("/documents/testFile", key); + } + + @Test + public void givenValidFile_whenUploadFailsDueToNoBucket_thenExceptionIsThrown() throws Exception { + when(multipartFile.getName()).thenReturn("testFile"); + when(multipartFile.getOriginalFilename()).thenReturn("testFile"); + when(multipartFile.getContentType()).thenReturn("application/pdf"); + when(multipartFile.getSize()).thenReturn(1024L); + when(multipartFile.getInputStream()).thenReturn(mock(InputStream.class)); + + AmazonS3Exception exception = new AmazonS3Exception("Test exception"); + exception.setErrorCode("NoSuchBucket"); + when(amazonS3.putObject(any(PutObjectRequest.class))).thenThrow(exception); + + assertThrows(Exception.class, () -> fileService.uploadFile(multipartFile)); + } + + @Test + public void givenExistingFile_whenUpdated_thenSameKeyIsReturned() throws Exception { + when(multipartFile.getName()).thenReturn("testFile"); + when(multipartFile.getContentType()).thenReturn("application/pdf"); + when(multipartFile.getSize()).thenReturn(1024L); + when(multipartFile.getInputStream()).thenReturn(mock(InputStream.class)); + + S3Object s3Object = new S3Object(); + when(amazonS3.putObject(any(PutObjectRequest.class))).thenReturn(null); + when(amazonS3.getObject(anyString(), anyString())).thenReturn(s3Object); + + String key = "/documents/existingFile"; + String resultKey = fileService.updateFile(multipartFile, key); + + assertEquals(key, resultKey); + } + + @Test + public void givenFileWithIOException_whenUpdated_thenExceptionIsThrown() throws Exception { + when(multipartFile.getName()).thenReturn("testFile"); + when(multipartFile.getContentType()).thenReturn("application/pdf"); + when(multipartFile.getSize()).thenReturn(1024L); + when(multipartFile.getInputStream()).thenThrow(new IOException("Test IO Exception")); + + assertThrows(Exception.class, () -> fileService.updateFile(multipartFile, "/documents/existingFile")); + } +} \ No newline at end of file diff --git a/aws-modules/aws-s3-v2/README.md b/aws-modules/aws-s3-v2/README.md deleted file mode 100644 index 4ec342894e..0000000000 --- a/aws-modules/aws-s3-v2/README.md +++ /dev/null @@ -1,2 +0,0 @@ -## Relevant Articles -- [Listing All AWS S3 Objects in a Bucket Using Java](https://www.baeldung.com/java-aws-s3-list-bucket-objects) diff --git a/aws-modules/aws-s3-v2/pom.xml b/aws-modules/aws-s3-v2/pom.xml deleted file mode 100644 index 888d98e654..0000000000 --- a/aws-modules/aws-s3-v2/pom.xml +++ /dev/null @@ -1,50 +0,0 @@ - - 4.0.0 - com.baeldung.s3 - aws-s3-v2 - 1.0-SNAPSHOT - aws-s3-v2 - jar - - - com.baeldung - aws-modules - 1.0.0-SNAPSHOT - - - - UTF-8 - 2.20.52 - 3.6.1 - - - - - software.amazon.awssdk - s3 - ${aws.java.sdk.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - ${maven-shade-plugin.version} - - false - - - - package - - shade - - - - - - - diff --git a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/Main.java b/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/Main.java deleted file mode 100644 index 7b7c95a0d0..0000000000 --- a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/Main.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.s3.listobjects; - -import software.amazon.awssdk.regions.Region; - -public class Main { - - private static String AWS_BUCKET = "baeldung-tutorial-s3"; - public static Region AWS_REGION = Region.EU_CENTRAL_1; - - public static void main(String[] args) { - S3Service s3Service = new S3Service(AWS_REGION); - - s3Service.putObject(AWS_BUCKET, FileGenerator.generateFiles(1000, 1)); - s3Service.listBuckets(); - s3Service.listObjectsInBucket(AWS_BUCKET); - s3Service.listAllObjectsInBucket(AWS_BUCKET); - s3Service.listAllObjectsInBucketPaginated(AWS_BUCKET, 500); - s3Service.listAllObjectsInBucketPaginatedWithPrefix(AWS_BUCKET, 500, "backup/"); - - s3Service.cleanup(); - } -} diff --git a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/S3Service.java b/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/S3Service.java deleted file mode 100644 index 132123f214..0000000000 --- a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/S3Service.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.baeldung.s3.listobjects; - -import java.util.List; - -import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; -import software.amazon.awssdk.core.sync.RequestBody; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.*; -import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable; - -class S3Service { - - private S3Client s3Client; - - public S3Service(Region awsRegion) { - init(awsRegion); - } - - public S3Service(S3Client s3Client) { - this.s3Client = s3Client; - } - - public void init(Region awsRegion) { - this.s3Client = S3Client.builder() - .region(awsRegion) - .credentialsProvider(ProfileCredentialsProvider.create("default")) - .build(); - } - - public void listObjectsInBucket(String bucketName) { - ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() - .bucket(bucketName) - .build(); - ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request); - - List contents = listObjectsV2Response.contents(); - - System.out.println("Number of objects in the bucket: " + contents.stream().count()); - contents.stream().forEach(System.out::println); - } - - public void listAllObjectsInBucket(String bucketName) { - String nextContinuationToken = null; - long totalObjects = 0; - - do { - ListObjectsV2Request.Builder requestBuilder = ListObjectsV2Request.builder() - .bucket(bucketName) - .continuationToken(nextContinuationToken); - - ListObjectsV2Response response = s3Client.listObjectsV2(requestBuilder.build()); - nextContinuationToken = response.nextContinuationToken(); - - totalObjects += response.contents().stream() - .peek(System.out::println) - .reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum); - } while (nextContinuationToken != null); - System.out.println("Number of objects in the bucket: " + totalObjects); - } - - public void listAllObjectsInBucketPaginated(String bucketName, int pageSize) { - ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() - .bucket(bucketName) - .maxKeys(pageSize) // Set the maxKeys parameter to control the page size - .build(); - - ListObjectsV2Iterable listObjectsV2Iterable = s3Client.listObjectsV2Paginator(listObjectsV2Request); - long totalObjects = 0; - - for (ListObjectsV2Response page : listObjectsV2Iterable) { - long retrievedPageSize = page.contents().stream() - .peek(System.out::println) - .reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum); - totalObjects += retrievedPageSize; - System.out.println("Page size: " + retrievedPageSize); - } - System.out.println("Total objects in the bucket: " + totalObjects); - } - - public void listAllObjectsInBucketPaginatedWithPrefix(String bucketName, int pageSize, String prefix) { - ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() - .bucket(bucketName) - .maxKeys(pageSize) // Set the maxKeys parameter to control the page size - .prefix(prefix) - .build(); - - ListObjectsV2Iterable listObjectsV2Iterable = s3Client.listObjectsV2Paginator(listObjectsV2Request); - long totalObjects = 0; - - for (ListObjectsV2Response page : listObjectsV2Iterable) { - long retrievedPageSize = page.contents().stream() - .peek(System.out::println) - .reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum); - totalObjects += retrievedPageSize; - System.out.println("Page size: " + retrievedPageSize); - } - System.out.println("Total objects in the bucket: " + totalObjects); - } - - public void listBuckets() { - // List all buckets - ListBucketsResponse listBucketsResponse = s3Client.listBuckets(); - - // Display the bucket names - List buckets = listBucketsResponse.buckets(); - System.out.println("Buckets:"); - for (Bucket bucket : buckets) { - System.out.println(bucket.name()); - } - } - - public void putObject(String bucketName, List files) { - try { - files.stream().forEach(file -> { - s3Client.putObject(PutObjectRequest.builder().bucket(bucketName).key(file.getName()).build(), - RequestBody.fromByteBuffer(file.getContent())); - System.out.println("Uploaded file: " + file.getName()); - }); - } catch (S3Exception e) { - System.err.println("Upload failed"); - e.printStackTrace(); - } - } - - public void cleanup() { - this.s3Client.close(); - } -} \ No newline at end of file diff --git a/aws-modules/aws-s3/README.md b/aws-modules/aws-s3/README.md index 109a898405..3389fdf454 100644 --- a/aws-modules/aws-s3/README.md +++ b/aws-modules/aws-s3/README.md @@ -8,3 +8,4 @@ This module contains articles about Simple Storage Service (S3) on AWS - [Multipart Uploads in Amazon S3 with Java](https://www.baeldung.com/aws-s3-multipart-upload) - [Using the JetS3t Java Client With Amazon S3](https://www.baeldung.com/jets3t-amazon-s3) - [Check if a Specified Key Exists in a Given S3 Bucket Using Java](https://www.baeldung.com/java-aws-s3-check-specified-key-exists) +- [Listing All AWS S3 Objects in a Bucket Using Java](https://www.baeldung.com/java-aws-s3-list-bucket-objects) \ No newline at end of file diff --git a/aws-modules/aws-s3/pom.xml b/aws-modules/aws-s3/pom.xml index 0ea99588d8..157aeb671d 100644 --- a/aws-modules/aws-s3/pom.xml +++ b/aws-modules/aws-s3/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 aws-s3 0.1.0-SNAPSHOT @@ -16,10 +16,11 @@ - com.amazonaws - aws-java-sdk - ${aws-java-sdk.version} + software.amazon.awssdk + s3 + ${aws.java.sdk.version} + commons-io commons-io @@ -60,6 +61,7 @@ + 2.20.52 1.10.L001 0.9.4.0006L diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/AWSS3ObjectUtils.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/AWSS3ObjectUtils.java deleted file mode 100644 index 1c31218ff9..0000000000 --- a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/AWSS3ObjectUtils.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.s3; - -import org.apache.http.HttpStatus; - -import com.amazonaws.AmazonServiceException; -import com.amazonaws.services.s3.AmazonS3; - -public class AWSS3ObjectUtils { - - private AmazonS3 s3Client; - - public AWSS3ObjectUtils(AmazonS3 s3client) { - this.s3Client = s3client; - } - - public boolean doesObjectExistByDefaultMethod(String bucket, String key) { - return s3Client.doesObjectExist(bucket, key); - } - - public boolean doesObjectExistByListObjects(String bucket, String key) { - return s3Client.listObjects(bucket) - .getObjectSummaries() - .stream() - .filter(s3ObjectSummary -> s3ObjectSummary.getKey() - .equals(key)) - .findFirst() - .isPresent(); - } - - public boolean doesObjectExistByMetaData(String bucket, String key) { - try { - s3Client.getObjectMetadata(bucket, key); - return true; - } catch (AmazonServiceException e) { - if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) { - return false; - } else { - throw e; - } - } - } -} \ No newline at end of file diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/AWSS3Service.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/AWSS3Service.java deleted file mode 100644 index 64ed043f98..0000000000 --- a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/AWSS3Service.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.baeldung.s3; - -import java.io.File; -import java.net.URL; -import java.util.List; - -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3Client; -import com.amazonaws.services.s3.model.Bucket; -import com.amazonaws.services.s3.model.CopyObjectResult; -import com.amazonaws.services.s3.model.DeleteObjectsRequest; -import com.amazonaws.services.s3.model.DeleteObjectsResult; -import com.amazonaws.services.s3.model.ObjectListing; -import com.amazonaws.services.s3.model.PutObjectResult; -import com.amazonaws.services.s3.model.S3Object; - -public class AWSS3Service { - private final AmazonS3 s3client; - - public AWSS3Service() { - this(new AmazonS3Client() { - }); - } - - public AWSS3Service(AmazonS3 s3client) { - this.s3client = s3client; - } - - //is bucket exist? - public boolean doesBucketExist(String bucketName) { - return s3client.doesBucketExist(bucketName); - } - - //create a bucket - public Bucket createBucket(String bucketName) { - return s3client.createBucket(bucketName); - } - - //list all buckets - public List listBuckets() { - return s3client.listBuckets(); - } - - //delete a bucket - public void deleteBucket(String bucketName) { - s3client.deleteBucket(bucketName); - } - - //uploading object - public PutObjectResult putObject(String bucketName, String key, File file) { - return s3client.putObject(bucketName, key, file); - } - //uploading object and getting url - public URL getObjectURL(String bucketName, String key, File file) { - s3client.putObject(bucketName, key, file); - return s3client.getUrl(bucketName, key); - } - - //listing objects - public ObjectListing listObjects(String bucketName) { - return s3client.listObjects(bucketName); - } - - //get an object - public S3Object getObject(String bucketName, String objectKey) { - return s3client.getObject(bucketName, objectKey); - } - - //copying an object - public CopyObjectResult copyObject( - String sourceBucketName, - String sourceKey, - String destinationBucketName, - String destinationKey - ) { - return s3client.copyObject( - sourceBucketName, - sourceKey, - destinationBucketName, - destinationKey - ); - } - - //deleting an object - public void deleteObject(String bucketName, String objectKey) { - s3client.deleteObject(bucketName, objectKey); - } - - //deleting multiple Objects - public DeleteObjectsResult deleteObjects(DeleteObjectsRequest delObjReq) { - return s3client.deleteObjects(delObjReq); - } -} diff --git a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/File.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/File.java similarity index 85% rename from aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/File.java rename to aws-modules/aws-s3/src/main/java/com/baeldung/s3/File.java index f9fe7f6fb3..9ab817f7fb 100644 --- a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/File.java +++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/File.java @@ -1,21 +1,21 @@ -package com.baeldung.s3.listobjects; - -import java.nio.ByteBuffer; - -public class File { - private String name; - private ByteBuffer content; - - public File(String name, ByteBuffer content) { - this.name = name; - this.content = content; - } - - public String getName() { - return name; - } - - public ByteBuffer getContent() { - return content; - } -} +package com.baeldung.s3; + +import java.nio.ByteBuffer; + +public class File { + private String name; + private ByteBuffer content; + + public File(String name, ByteBuffer content) { + this.name = name; + this.content = content; + } + + public String getName() { + return name; + } + + public ByteBuffer getContent() { + return content; + } +} diff --git a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/FileGenerator.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/FileGenerator.java similarity index 91% rename from aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/FileGenerator.java rename to aws-modules/aws-s3/src/main/java/com/baeldung/s3/FileGenerator.java index 7c640591d7..7c35192d22 100644 --- a/aws-modules/aws-s3-v2/src/main/java/com/baeldung/s3/listobjects/FileGenerator.java +++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/FileGenerator.java @@ -1,27 +1,27 @@ -package com.baeldung.s3.listobjects; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -public class FileGenerator { - - public static List generateFiles(int fileCount, int fileSize) { - List files = new ArrayList<>(); - for (int i = 0; i < fileCount; i++) { - String fileName = "file_" + i + ".txt"; - ByteBuffer fileContent = generateRandomBytes(fileSize); - files.add(new File(fileName, fileContent)); - } - return files; - } - - private static ByteBuffer generateRandomBytes(int size) { - byte[] array = new byte[size]; - new Random().nextBytes(array); - return ByteBuffer.wrap(array); - } - - -} +package com.baeldung.s3; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class FileGenerator { + + public static List generateFiles(int fileCount, int fileSize) { + List files = new ArrayList<>(); + for (int i = 0; i < fileCount; i++) { + String fileName = "file_" + i + ".txt"; + ByteBuffer fileContent = generateRandomBytes(fileSize); + files.add(new File(fileName, fileContent)); + } + return files; + } + + private static ByteBuffer generateRandomBytes(int size) { + byte[] array = new byte[size]; + new Random().nextBytes(array); + return ByteBuffer.wrap(array); + } + + +} diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/MultipartUpload.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/MultipartUpload.java index 711046c112..de45238994 100644 --- a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/MultipartUpload.java +++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/MultipartUpload.java @@ -1,56 +1,101 @@ package com.baeldung.s3; -import com.amazonaws.AmazonClientException; -import com.amazonaws.auth.DefaultAWSCredentialsProviderChain; -import com.amazonaws.event.ProgressListener; -import com.amazonaws.regions.Regions; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; -import com.amazonaws.services.s3.model.PutObjectRequest; -import com.amazonaws.services.s3.transfer.TransferManager; -import com.amazonaws.services.s3.transfer.TransferManagerBuilder; -import com.amazonaws.services.s3.transfer.Upload; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; + +import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.services.s3.model.*; -import java.io.File; -import java.util.concurrent.Executors; public class MultipartUpload { - public static void main(String[] args) throws Exception { + public static void main(String[] args) { String existingBucketName = "baeldung-bucket"; String keyName = "my-picture.jpg"; String filePath = "documents/my-picture.jpg"; - AmazonS3 amazonS3 = AmazonS3ClientBuilder - .standard() - .withCredentials(new DefaultAWSCredentialsProviderChain()) - .withRegion(Regions.DEFAULT_REGION) - .build(); + ProfileCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create(); + Region region = Region.US_EAST_1; + S3Client s3 = S3Client.builder() + .region(region) + .credentialsProvider(credentialsProvider) + .build(); - int maxUploadThreads = 5; + // Initiate a multipart upload + CreateMultipartUploadRequest createRequest = CreateMultipartUploadRequest.builder() + .bucket(existingBucketName) + .key(keyName) + .build(); - TransferManager tm = TransferManagerBuilder - .standard() - .withS3Client(amazonS3) - .withMultipartUploadThreshold((long) (5 * 1024 * 1024)) - .withExecutorFactory(() -> Executors.newFixedThreadPool(maxUploadThreads)) - .build(); + CreateMultipartUploadResponse createResponse = s3.createMultipartUpload(createRequest); - ProgressListener progressListener = - progressEvent -> System.out.println("Transferred bytes: " + progressEvent.getBytesTransferred()); + String uploadId = createResponse.uploadId(); - PutObjectRequest request = new PutObjectRequest(existingBucketName, keyName, new File(filePath)); + // Prepare the parts to be uploaded + List completedParts = new ArrayList<>(); + int partNumber = 1; + ByteBuffer buffer = ByteBuffer.allocate(5 * 1024 * 1024); // Set your preferred part size (5 MB in this example) - request.setGeneralProgressListener(progressListener); + // Read the file and upload each part + try (RandomAccessFile file = new RandomAccessFile(filePath, "r")) { + long fileSize = file.length(); + long position = 0; - Upload upload = tm.upload(request); + while (position < fileSize) { + file.seek(position); + int bytesRead = file.getChannel().read(buffer); - try { - upload.waitForCompletion(); - System.out.println("Upload complete."); - } catch (AmazonClientException e) { - System.out.println("Error occurred while uploading file"); + buffer.flip(); + UploadPartRequest uploadPartRequest = UploadPartRequest.builder() + .bucket(existingBucketName) + .key(keyName) + .uploadId(uploadId) + .partNumber(partNumber) + .contentLength((long) bytesRead) + .build(); + + UploadPartResponse response = s3.uploadPart(uploadPartRequest, RequestBody.fromByteBuffer(buffer)); + + completedParts.add(CompletedPart.builder() + .partNumber(partNumber) + .eTag(response.eTag()) + .build()); + + buffer.clear(); + position += bytesRead; + partNumber++; + } + } catch (IOException e) { e.printStackTrace(); } + + // Complete the multipart upload + CompletedMultipartUpload completedUpload = CompletedMultipartUpload.builder() + .parts(completedParts) + .build(); + + CompleteMultipartUploadRequest completeRequest = CompleteMultipartUploadRequest.builder() + .bucket(existingBucketName) + .key(keyName) + .uploadId(uploadId) + .multipartUpload(completedUpload) + .build(); + + CompleteMultipartUploadResponse completeResponse = s3.completeMultipartUpload(completeRequest); + + // Print the object's URL + String objectUrl = s3.utilities().getUrl(GetUrlRequest.builder() + .bucket(existingBucketName) + .key(keyName) + .build()) + .toExternalForm(); + + System.out.println("Uploaded object URL: " + objectUrl); } } \ No newline at end of file diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java index 39a9b0050f..abf570f0d0 100644 --- a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java +++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Application.java @@ -1,104 +1,69 @@ package com.baeldung.s3; import java.io.File; -import java.io.IOException; +import java.util.List; -import org.apache.commons.io.FileUtils; - -import com.amazonaws.auth.AWSCredentials; -import com.amazonaws.auth.AWSStaticCredentialsProvider; -import com.amazonaws.auth.BasicAWSCredentials; -import com.amazonaws.regions.Regions; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; -import com.amazonaws.services.s3.model.Bucket; -import com.amazonaws.services.s3.model.DeleteObjectsRequest; -import com.amazonaws.services.s3.model.ObjectListing; -import com.amazonaws.services.s3.model.S3Object; -import com.amazonaws.services.s3.model.S3ObjectInputStream; -import com.amazonaws.services.s3.model.S3ObjectSummary; +import software.amazon.awssdk.regions.Region; public class S3Application { - private static final AWSCredentials credentials; - private static String bucketName; + private static String AWS_BUCKET = "baeldung-tutorial-s3"; + public static Region AWS_REGION = Region.EU_CENTRAL_1; - static { - //put your accesskey and secretkey here - credentials = new BasicAWSCredentials( - "", - "" - ); - } - - public static void main(String[] args) throws IOException { - //set-up the client - AmazonS3 s3client = AmazonS3ClientBuilder - .standard() - .withCredentials(new AWSStaticCredentialsProvider(credentials)) - .withRegion(Regions.US_EAST_2) - .build(); - - AWSS3Service awsService = new AWSS3Service(s3client); - - bucketName = "baeldung-bucket"; + public static void main(String[] args) { + S3Service s3Service = new S3Service(AWS_REGION); //creating a bucket - if(awsService.doesBucketExist(bucketName)) { + s3Service.createBucket(AWS_BUCKET); + + //check if a bucket exists + if(s3Service.doesBucketExist(AWS_BUCKET)) { System.out.println("Bucket name is not available." - + " Try again with a different Bucket name."); + + " Try again with a different Bucket name."); return; } - awsService.createBucket(bucketName); - - //list all the buckets - for(Bucket s : awsService.listBuckets() ) { - System.out.println(s.getName()); - } - - //deleting bucket - awsService.deleteBucket("baeldung-bucket-test2"); - - //uploading object - awsService.putObject( - bucketName, - "Document/hello.txt", - new File("/Users/user/Document/hello.txt") - ); - //uploading object and getting url - awsService.getObjectURL(bucketName, "Document/hello.txt", new File("/Users/user/Document/hello.txt")); + + s3Service.putObjects(AWS_BUCKET, FileGenerator.generateFiles(1000, 1)); + + //list all the buckets + s3Service.listBuckets(); + s3Service.listObjectsInBucket(AWS_BUCKET); + s3Service.listAllObjectsInBucket(AWS_BUCKET); + s3Service.listAllObjectsInBucketPaginated(AWS_BUCKET, 500); + s3Service.listAllObjectsInBucketPaginatedWithPrefix(AWS_BUCKET, 500, "backup/"); + + + + //deleting bucket + s3Service.deleteBucket("baeldung-bucket-test2"); + + //uploading object + s3Service.putObject( + AWS_BUCKET, + "Document/hello.txt", + new File("/Users/user/Document/hello.txt") + ); //listing objects - ObjectListing objectListing = awsService.listObjects(bucketName); - for(S3ObjectSummary os : objectListing.getObjectSummaries()) { - System.out.println(os.getKey()); - } + s3Service.listObjects(AWS_BUCKET); //downloading an object - S3Object s3object = awsService.getObject(bucketName, "Document/hello.txt"); - S3ObjectInputStream inputStream = s3object.getObjectContent(); - FileUtils.copyInputStreamToFile(inputStream, new File("/Users/user/Desktop/hello.txt")); - + s3Service.getObject(AWS_BUCKET, "Document/hello.txt"); + //copying an object - awsService.copyObject( - "baeldung-bucket", - "picture/pic.png", - "baeldung-bucket2", - "Document/picture.png" + s3Service.copyObject( + "baeldung-bucket", + "picture/pic.png", + "baeldung-bucket2", + "Document/picture.png" ); - + //deleting an object - awsService.deleteObject(bucketName, "Document/hello.txt"); + s3Service.deleteObject(AWS_BUCKET, "Document/hello.txt"); //deleting multiple objects - String objkeyArr[] = { - "Document/hello2.txt", - "Document/picture.png" - }; - - DeleteObjectsRequest delObjReq = new DeleteObjectsRequest("baeldung-bucket") - .withKeys(objkeyArr); - awsService.deleteObjects(delObjReq); + List objKeyList = List.of("Document/hello2.txt", "Document/picture.png"); + s3Service.deleteObjects(AWS_BUCKET, objKeyList); } } diff --git a/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java new file mode 100644 index 0000000000..f4f768d1b4 --- /dev/null +++ b/aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java @@ -0,0 +1,323 @@ +package com.baeldung.s3; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider; +import software.amazon.awssdk.core.ResponseBytes; +import software.amazon.awssdk.core.sync.RequestBody; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.Bucket; +import software.amazon.awssdk.services.s3.model.CopyObjectRequest; +import software.amazon.awssdk.services.s3.model.CopyObjectResponse; +import software.amazon.awssdk.services.s3.model.CreateBucketRequest; +import software.amazon.awssdk.services.s3.model.Delete; +import software.amazon.awssdk.services.s3.model.DeleteBucketRequest; +import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; +import software.amazon.awssdk.services.s3.model.DeleteObjectsRequest; +import software.amazon.awssdk.services.s3.model.GetObjectRequest; +import software.amazon.awssdk.services.s3.model.GetObjectResponse; +import software.amazon.awssdk.services.s3.model.HeadBucketRequest; +import software.amazon.awssdk.services.s3.model.HeadObjectRequest; +import software.amazon.awssdk.services.s3.model.ListBucketsResponse; +import software.amazon.awssdk.services.s3.model.ListObjectsV2Request; +import software.amazon.awssdk.services.s3.model.ListObjectsV2Response; +import software.amazon.awssdk.services.s3.model.NoSuchBucketException; +import software.amazon.awssdk.services.s3.model.ObjectIdentifier; +import software.amazon.awssdk.services.s3.model.PutObjectRequest; +import software.amazon.awssdk.services.s3.model.PutObjectResponse; +import software.amazon.awssdk.services.s3.model.S3Exception; +import software.amazon.awssdk.services.s3.model.S3Object; +import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable; + +class S3Service { + + private S3Client s3Client; + + public S3Service(Region awsRegion) { + init(awsRegion); + } + + public S3Service(S3Client s3Client) { + this.s3Client = s3Client; + } + + public void init(Region awsRegion) { + this.s3Client = S3Client.builder() + .region(awsRegion) + .credentialsProvider(ProfileCredentialsProvider.create("default")) + .build(); + } + + //is bucket exist? + public boolean doesBucketExist(String bucketName) { + HeadBucketRequest headBucketRequest = HeadBucketRequest.builder() + .bucket(bucketName) + .build(); + + try { + s3Client.headBucket(headBucketRequest); + return true; + } catch (NoSuchBucketException e) { + return false; + } + } + + //create a bucket + public void createBucket(String bucketName) { + CreateBucketRequest bucketRequest = CreateBucketRequest.builder() + .bucket(bucketName) + .build(); + + s3Client.createBucket(bucketRequest); + } + + //delete a bucket + public void deleteBucket(String bucketName) { + try { + DeleteBucketRequest deleteBucketRequest = DeleteBucketRequest.builder() + .bucket(bucketName) + .build(); + + s3Client.deleteBucket(deleteBucketRequest); + System.out.println("Successfully deleted bucket : " + bucketName); + } catch (S3Exception e) { + System.err.println(e.getMessage()); + System.exit(1); + } + } + + //uploading object + public PutObjectResponse putObject(String bucketName, String key, java.io.File file) { + PutObjectRequest request = PutObjectRequest.builder() + .bucket(bucketName) + .key(key) + .build(); + + return s3Client.putObject(request, Path.of(file.toURI()) ); + } + + //listing objects + public void listObjects(String bucketName) { + ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() + .bucket(bucketName) + .build(); + ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request); + + for(S3Object os : listObjectsV2Response.contents()) { + System.out.println(os.key()); + } + } + + //get an object + public void getObject(String bucketName, String objectKey) { + try { + GetObjectRequest objectRequest = GetObjectRequest.builder() + .bucket(bucketName) + .key(objectKey) + .build(); + + ResponseBytes responseResponseBytes = s3Client.getObjectAsBytes(objectRequest); + + byte[] data = responseResponseBytes.asByteArray(); + + // Write the data to a local file. + java.io.File myFile = new java.io.File("/Users/user/Desktop/hello.txt" ); + OutputStream os = new FileOutputStream(myFile); + os.write(data); + System.out.println("Successfully obtained bytes from an S3 object"); + os.close(); + } catch (IOException ex) { + ex.printStackTrace(); + } catch (S3Exception e) { + System.err.println(e.awsErrorDetails().errorMessage()); + System.exit(1); + } + } + + //copying an object + public CopyObjectResponse copyObject( + String sourceBucketName, + String sourceKey, + String destinationBucketName, + String destinationKey + ) { + CopyObjectRequest copyObjectRequest = CopyObjectRequest.builder() + .sourceBucket(sourceBucketName) + .sourceKey(sourceKey) + .destinationBucket(destinationBucketName) + .destinationKey(destinationKey) + .build(); + + return s3Client.copyObject(copyObjectRequest); + } + + //deleting an object + public void deleteObject(String bucketName, String objectKey) { + DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder() + .bucket(bucketName) + .key(objectKey) + .build(); + + s3Client.deleteObject(deleteObjectRequest); + } + + //deleting multiple Objects + public void deleteObjects(String bucketName, List keys ) { + + ArrayList toDelete = new ArrayList<>(); + for(String objKey : keys) { + toDelete.add(ObjectIdentifier.builder() + .key(objKey) + .build()); + } + + DeleteObjectsRequest deleteObjectRequest = DeleteObjectsRequest.builder() + .bucket(bucketName) + .delete(Delete.builder() + .objects(toDelete).build()) + .build(); + + s3Client.deleteObjects(deleteObjectRequest); + } + + public boolean doesObjectExistByListObjects(String bucketName, String key) { + + ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() + .bucket(bucketName) + .build(); + ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request); + + return listObjectsV2Response.contents() + .stream() + .filter(s3ObjectSummary -> s3ObjectSummary.getValueForField("key", String.class) + .equals(key)) + .findFirst() + .isPresent(); + } + + public boolean doesObjectExistByDefaultMethod(String bucket, String key) { + try { + HeadObjectRequest headObjectRequest = HeadObjectRequest.builder() + .bucket(bucket) + .key(key) + .build(); + + s3Client.headObject(headObjectRequest); + + System.out.println("Object exists"); + return true; + } catch (S3Exception e) { + if (e.statusCode() == 404) { + System.out.println("Object does not exist"); + return false; + } else { + throw e; + } + } + } + + public void listBuckets() { + // List all buckets + ListBucketsResponse listBucketsResponse = s3Client.listBuckets(); + + // Display the bucket names + List buckets = listBucketsResponse.buckets(); + System.out.println("Buckets:"); + for (Bucket bucket : buckets) { + System.out.println(bucket.name()); + } + } + + public void listObjectsInBucket(String bucketName) { + ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() + .bucket(bucketName) + .build(); + ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request); + + List contents = listObjectsV2Response.contents(); + + System.out.println("Number of objects in the bucket: " + contents.stream().count()); + contents.stream().forEach(System.out::println); + } + + public void listAllObjectsInBucket(String bucketName) { + String nextContinuationToken = null; + long totalObjects = 0; + + do { + ListObjectsV2Request.Builder requestBuilder = ListObjectsV2Request.builder() + .bucket(bucketName) + .continuationToken(nextContinuationToken); + + ListObjectsV2Response response = s3Client.listObjectsV2(requestBuilder.build()); + nextContinuationToken = response.nextContinuationToken(); + + totalObjects += response.contents().stream() + .peek(System.out::println) + .reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum); + } while (nextContinuationToken != null); + System.out.println("Number of objects in the bucket: " + totalObjects); + } + + public void listAllObjectsInBucketPaginated(String bucketName, int pageSize) { + ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() + .bucket(bucketName) + .maxKeys(pageSize) // Set the maxKeys parameter to control the page size + .build(); + + ListObjectsV2Iterable listObjectsV2Iterable = s3Client.listObjectsV2Paginator(listObjectsV2Request); + long totalObjects = 0; + + for (ListObjectsV2Response page : listObjectsV2Iterable) { + long retrievedPageSize = page.contents().stream() + .peek(System.out::println) + .reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum); + totalObjects += retrievedPageSize; + System.out.println("Page size: " + retrievedPageSize); + } + System.out.println("Total objects in the bucket: " + totalObjects); + } + + public void listAllObjectsInBucketPaginatedWithPrefix(String bucketName, int pageSize, String prefix) { + ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder() + .bucket(bucketName) + .maxKeys(pageSize) // Set the maxKeys parameter to control the page size + .prefix(prefix) + .build(); + + ListObjectsV2Iterable listObjectsV2Iterable = s3Client.listObjectsV2Paginator(listObjectsV2Request); + long totalObjects = 0; + + for (ListObjectsV2Response page : listObjectsV2Iterable) { + long retrievedPageSize = page.contents().stream() + .peek(System.out::println) + .reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum); + totalObjects += retrievedPageSize; + System.out.println("Page size: " + retrievedPageSize); + } + System.out.println("Total objects in the bucket: " + totalObjects); + } + + public void putObjects(String bucketName, List files) { + try { + files.stream().forEach(file -> { + s3Client.putObject(PutObjectRequest.builder().bucket(bucketName).key(file.getName()).build(), + RequestBody.fromByteBuffer(file.getContent())); + System.out.println("Uploaded file: " + file.getName()); + }); + } catch (S3Exception e) { + System.err.println("Upload failed"); + e.printStackTrace(); + } + } + public void cleanup() { + this.s3Client.close(); + } + +} \ No newline at end of file diff --git a/aws-modules/aws-s3/src/main/resources/logback.xml b/aws-modules/aws-s3/src/main/resources/logback.xml index 7d900d8ea8..88eee7b977 100644 --- a/aws-modules/aws-s3/src/main/resources/logback.xml +++ b/aws-modules/aws-s3/src/main/resources/logback.xml @@ -10,4 +10,7 @@ + + + \ No newline at end of file diff --git a/aws-modules/aws-s3/src/test/java/com/baeldung/jets3t/JetS3tLiveTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/jets3t/JetS3tLiveTest.java index cf0b203e10..cad7da6cc9 100644 --- a/aws-modules/aws-s3/src/test/java/com/baeldung/jets3t/JetS3tLiveTest.java +++ b/aws-modules/aws-s3/src/test/java/com/baeldung/jets3t/JetS3tLiveTest.java @@ -1,5 +1,13 @@ package com.baeldung.jets3t; +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -10,8 +18,8 @@ import org.jets3t.service.model.S3Bucket; import org.jets3t.service.model.S3Object; import org.jets3t.service.model.StorageObject; import org.jets3t.service.security.AWSCredentials; -import org.junit.BeforeClass; -import org.junit.Test; + + import java.io.*; import java.nio.file.Files; @@ -19,14 +27,13 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.stream.Collectors; -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; -import static junit.framework.TestCase.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; + + + public class JetS3tLiveTest { - private Log log = LogFactory.getLog(JetS3tLiveTest.class); + private final Log log = LogFactory.getLog(JetS3tLiveTest.class); private static final String BucketName = "baeldung-barfoo"; private static final String TestString = "test string"; @@ -35,7 +42,7 @@ public class JetS3tLiveTest { private static S3Service s3Service; - @BeforeClass + @BeforeAll public static void connectS3() throws Exception { // Replace with your keys @@ -50,7 +57,7 @@ public class JetS3tLiveTest { } @Test - public void givenCreate_AndDeleteBucket_CountGoesUpThenDown() throws Exception { + void givenCreate_AndDeleteBucket_CountGoesUpThenDown() throws Exception { // List buckets, get a count S3Bucket[] myBuckets = s3Service.listAllBuckets(); @@ -89,7 +96,7 @@ public class JetS3tLiveTest { } @Test - public void givenString_Uploaded_StringInfoIsAvailable() throws Exception { + void givenString_Uploaded_StringInfoIsAvailable() throws Exception { // Create a bucket S3Bucket bucket = createBucket(); @@ -120,7 +127,7 @@ public class JetS3tLiveTest { } @Test - public void givenStringUploaded_StringIsDownloaded() throws Exception { + void givenStringUploaded_StringIsDownloaded() throws Exception { // Get a bucket S3Bucket bucket = createBucket(); @@ -135,7 +142,7 @@ public class JetS3tLiveTest { String downloadedString = new BufferedReader(new InputStreamReader(stringObject.getDataInputStream())).lines().collect(Collectors.joining("\n")); // Verify - assertTrue(TestString.equals(downloadedString)); + assertEquals(TestString, downloadedString); // Clean up for next test @@ -144,7 +151,7 @@ public class JetS3tLiveTest { } @Test - public void givenBinaryFileUploaded_FileIsDownloaded() throws Exception { + void givenBinaryFileUploaded_FileIsDownloaded() throws Exception { // get a bucket S3Bucket bucket = createBucket(); @@ -169,7 +176,7 @@ public class JetS3tLiveTest { // Get hashes and compare String origMD5 = getFileMD5("src/test/resources/test.jpg"); String newMD5 = getFileMD5("src/test/resources/newtest.jpg"); - assertTrue(origMD5.equals(newMD5)); + assertEquals(origMD5, newMD5); // Clean up deleteObject("test.jpg"); @@ -186,7 +193,7 @@ public class JetS3tLiveTest { @Test - public void givenStreamDataUploaded_StreamDataIsDownloaded() throws Exception { + void givenStreamDataUploaded_StreamDataIsDownloaded() throws Exception { // get a bucket S3Bucket bucket = createBucket(); @@ -233,7 +240,7 @@ public class JetS3tLiveTest { } @Test - public void whenFileCopied_CopyIsSame() throws Exception { + void whenFileCopied_CopyIsSame() throws Exception { // get a bucket S3Bucket bucket = createBucket(); @@ -260,7 +267,7 @@ public class JetS3tLiveTest { // Get hashes and compare String origMD5 = getFileMD5("src/test/resources/test.jpg"); String newMD5 = getFileMD5("src/test/resources/testcopy.jpg"); - assertTrue(origMD5.equals(newMD5)); + assertEquals(origMD5, newMD5); // Clean up deleteObject("test.jpg"); @@ -271,7 +278,7 @@ public class JetS3tLiveTest { @Test - public void whenFileRenamed_NewNameIsSame() throws Exception { + void whenFileRenamed_NewNameIsSame() throws Exception { // get a bucket S3Bucket bucket = createBucket(); @@ -297,7 +304,7 @@ public class JetS3tLiveTest { // Get hashes and compare String origMD5 = getFileMD5("src/test/resources/test.jpg"); String newMD5 = getFileMD5("src/test/resources/spidey.jpg"); - assertTrue(origMD5.equals(newMD5)); + assertEquals(origMD5, newMD5); // Clean up deleteObject("test.jpg"); @@ -307,7 +314,7 @@ public class JetS3tLiveTest { } @Test - public void whenFileMoved_NewInstanceIsSame() throws Exception { + void whenFileMoved_NewInstanceIsSame() throws Exception { // get a bucket S3Bucket bucket = createBucket(); @@ -338,7 +345,7 @@ public class JetS3tLiveTest { // Get hashes and compare String origMD5 = getFileMD5("src/test/resources/test.jpg"); String newMD5 = getFileMD5("src/test/resources/spidey.jpg"); - assertTrue(origMD5.equals(newMD5)); + assertEquals(origMD5, newMD5); // Clean up deleteBucket(); diff --git a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/AWSS3ObjectManualTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/AWSS3ObjectManualTest.java deleted file mode 100644 index 02cc22367a..0000000000 --- a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/AWSS3ObjectManualTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.baeldung.s3; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.Before; -import org.junit.Test; - -import com.amazonaws.auth.EnvironmentVariableCredentialsProvider; -import com.amazonaws.regions.Regions; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.AmazonS3ClientBuilder; - -/** - * Required defined environment variables AWS_ACCESS_KEY_ID & AWS_ACCESS_KEY to access S3. - * Required S3 bucket and key that exist. - */ - -public class AWSS3ObjectManualTest { - - private static final String BUCKET = "your-bucket"; - private static final String KEY_THAT_EXIST = "your-key-that-exist"; - private AWSS3ObjectUtils s3ObjectUtils; - - @Before - public void setUp() { - AmazonS3 client = AmazonS3ClientBuilder.standard() - .withRegion(Regions.DEFAULT_REGION) - .withCredentials(new EnvironmentVariableCredentialsProvider()) - .build(); - - s3ObjectUtils = new AWSS3ObjectUtils(client); - } - - @Test - public void whenVerifyIfObjectExistByDefaultMethod_thenCorrect() { - assertTrue(s3ObjectUtils.doesObjectExistByDefaultMethod(BUCKET, KEY_THAT_EXIST), "Key: " + KEY_THAT_EXIST + " doesn't exist"); - - } - - @Test - public void whenVerifyIfObjectExistByListObjects_thenCorrect() { - assertTrue(s3ObjectUtils.doesObjectExistByListObjects(BUCKET, KEY_THAT_EXIST), "Key: " + KEY_THAT_EXIST + " doesn't exist"); - } - - @Test - public void whenVerifyIfObjectExistByMetaData_thenCorrect() { - assertTrue(s3ObjectUtils.doesObjectExistByMetaData(BUCKET, KEY_THAT_EXIST), "Key: " + KEY_THAT_EXIST + " doesn't exist"); - } -} diff --git a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/AWSS3ServiceIntegrationTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/AWSS3ServiceIntegrationTest.java deleted file mode 100644 index d386704513..0000000000 --- a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/AWSS3ServiceIntegrationTest.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.baeldung.s3; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.File; - -import org.junit.Before; -import org.junit.Test; - -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.CopyObjectResult; -import com.amazonaws.services.s3.model.DeleteObjectsRequest; -import com.amazonaws.services.s3.model.DeleteObjectsResult; -import com.amazonaws.services.s3.model.PutObjectResult; - -public class AWSS3ServiceIntegrationTest { - - private static final String BUCKET_NAME = "bucket_name"; - private static final String KEY_NAME = "key_name"; - private static final String BUCKET_NAME2 = "bucket_name2"; - private static final String KEY_NAME2 = "key_name2"; - - private AmazonS3 s3; - private AWSS3Service service; - - @Before - public void setUp() { - s3 = mock(AmazonS3.class); - service = new AWSS3Service(s3); - } - - @Test - public void whenInitializingAWSS3Service_thenNotNull() { - assertThat(new AWSS3Service()).isNotNull(); - } - - @Test - public void whenVerifyingIfS3BucketExist_thenCorrect() { - service.doesBucketExist(BUCKET_NAME); - verify(s3).doesBucketExist(BUCKET_NAME); - } - - @Test - public void whenVerifyingCreationOfS3Bucket_thenCorrect() { - service.createBucket(BUCKET_NAME); - verify(s3).createBucket(BUCKET_NAME); - } - - @Test - public void whenVerifyingListBuckets_thenCorrect() { - service.listBuckets(); - verify(s3).listBuckets(); - } - - @Test - public void whenDeletingBucket_thenCorrect() { - service.deleteBucket(BUCKET_NAME); - verify(s3).deleteBucket(BUCKET_NAME); - } - - @Test - public void whenVerifyingPutObject_thenCorrect() { - File file = mock(File.class); - PutObjectResult result = mock(PutObjectResult.class); - when(s3.putObject(anyString(), anyString(), (File) any())).thenReturn(result); - - assertThat(service.putObject(BUCKET_NAME, KEY_NAME, file)).isEqualTo(result); - verify(s3).putObject(BUCKET_NAME, KEY_NAME, file); - } - - @Test - public void whenVerifyingListObjects_thenCorrect() { - service.listObjects(BUCKET_NAME); - verify(s3).listObjects(BUCKET_NAME); - } - - @Test - public void whenVerifyingGetObject_thenCorrect() { - service.getObject(BUCKET_NAME, KEY_NAME); - verify(s3).getObject(BUCKET_NAME, KEY_NAME); - } - - @Test - public void whenVerifyingCopyObject_thenCorrect() { - CopyObjectResult result = mock(CopyObjectResult.class); - when(s3.copyObject(anyString(), anyString(), anyString(), anyString())).thenReturn(result); - - assertThat(service.copyObject(BUCKET_NAME, KEY_NAME, BUCKET_NAME2, KEY_NAME2)).isEqualTo(result); - verify(s3).copyObject(BUCKET_NAME, KEY_NAME, BUCKET_NAME2, KEY_NAME2); - } - - @Test - public void whenVerifyingDeleteObject_thenCorrect() { - service.deleteObject(BUCKET_NAME, KEY_NAME); - verify(s3).deleteObject(BUCKET_NAME, KEY_NAME); - } - - @Test - public void whenVerifyingDeleteObjects_thenCorrect() { - DeleteObjectsRequest request = mock(DeleteObjectsRequest.class); - DeleteObjectsResult result = mock(DeleteObjectsResult.class); - when(s3.deleteObjects((DeleteObjectsRequest)any())).thenReturn(result); - - assertThat(service.deleteObjects(request)).isEqualTo(result); - verify(s3).deleteObjects(request); - } - -} diff --git a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/MultipartUploadLiveTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/MultipartUploadLiveTest.java deleted file mode 100644 index e2a34b1c39..0000000000 --- a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/MultipartUploadLiveTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.baeldung.s3; - -import com.amazonaws.event.ProgressListener; -import com.amazonaws.services.s3.AmazonS3; -import com.amazonaws.services.s3.model.PutObjectRequest; -import com.amazonaws.services.s3.model.PutObjectResult; -import com.amazonaws.services.s3.transfer.TransferManager; -import com.amazonaws.services.s3.transfer.TransferManagerBuilder; -import com.amazonaws.services.s3.transfer.Upload; -import org.junit.Before; -import org.junit.Test; - -import java.io.File; -import java.util.concurrent.Executors; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -public class MultipartUploadLiveTest { - - private static final String BUCKET_NAME = "bucket_name"; - private static final String KEY_NAME = "picture.jpg"; - - private AmazonS3 amazonS3; - private TransferManager tm; - private ProgressListener progressListener; - - @Before - public void setup() { - amazonS3 = mock(AmazonS3.class); - tm = TransferManagerBuilder - .standard() - .withS3Client(amazonS3) - .withMultipartUploadThreshold((long) (5 * 1024 * 1025)) - .withExecutorFactory(() -> Executors.newFixedThreadPool(5)) - .build(); - progressListener = - progressEvent -> System.out.println("Transferred bytes: " + progressEvent.getBytesTransferred()); - } - - @Test - public void whenUploadingFileWithTransferManager_thenVerifyUploadRequested() { - File file = mock(File.class); - PutObjectResult s3Result = mock(PutObjectResult.class); - - when(amazonS3.putObject(anyString(), anyString(), (File) any())).thenReturn(s3Result); - when(file.getName()).thenReturn(KEY_NAME); - - PutObjectRequest request = new PutObjectRequest(BUCKET_NAME, KEY_NAME, file); - request.setGeneralProgressListener(progressListener); - - Upload upload = tm.upload(request); - - assertThat(upload).isNotNull(); - verify(amazonS3).putObject(request); - } -} diff --git a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java new file mode 100644 index 0000000000..bf24bcaa43 --- /dev/null +++ b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceIntegrationTest.java @@ -0,0 +1,137 @@ +package com.baeldung.s3; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import java.util.Collections; + +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.CopyObjectRequest; +import software.amazon.awssdk.services.s3.model.CopyObjectResponse; +import software.amazon.awssdk.services.s3.model.CreateBucketRequest; +import software.amazon.awssdk.services.s3.model.DeleteBucketRequest; +import software.amazon.awssdk.services.s3.model.DeleteObjectRequest; +import software.amazon.awssdk.services.s3.model.HeadBucketRequest; +import software.amazon.awssdk.services.s3.model.ListBucketsResponse; +import software.amazon.awssdk.services.s3.model.ListObjectsV2Request; +import software.amazon.awssdk.services.s3.model.ListObjectsV2Response; + +class S3ServiceIntegrationTest { + + private static final String BUCKET_NAME = "bucket_name"; + private static final String KEY_NAME = "key_name"; + private static final String BUCKET_NAME2 = "bucket_name2"; + private static final String KEY_NAME2 = "key_name2"; + + @Mock + private S3Client s3Client; + + private S3Service s3Service; + + private final String AWS_BUCKET = "baeldung-tutorial-s3"; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + s3Service = new S3Service(s3Client); + } + + @AfterEach + public void cleanup() { + s3Service.cleanup(); + Mockito.verify(s3Client).close(); + } + + @Test + void whenInitializingAWSS3Service_thenNotNull() { + assertThat(new S3Service(s3Client)).isNotNull(); + } + + @Test + void whenVerifyingIfS3BucketExist_thenCorrect() { + HeadBucketRequest headBucketRequest = HeadBucketRequest.builder() + .bucket(BUCKET_NAME) + .build(); + + s3Service.doesBucketExist(BUCKET_NAME); + verify(s3Client).headBucket(headBucketRequest); + } + + @Test + void whenVerifyingCreationOfS3Bucket_thenCorrect() { + CreateBucketRequest bucketRequest = CreateBucketRequest.builder() + .bucket(BUCKET_NAME) + .build(); + + s3Service.createBucket(BUCKET_NAME); + verify(s3Client).createBucket(bucketRequest); + } + + @Test + void whenVerifyingListBuckets_thenCorrect() { + when(s3Client.listBuckets()).thenReturn(ListBucketsResponse.builder().buckets(Collections.emptyList()).build()); + + s3Service.listBuckets(); + Mockito.verify(s3Client).listBuckets(); + } + + @Test + void whenDeletingBucket_thenCorrect() { + DeleteBucketRequest deleteBucketRequest = DeleteBucketRequest.builder() + .bucket(BUCKET_NAME) + .build(); + + s3Service.deleteBucket(BUCKET_NAME); + verify(s3Client).deleteBucket(deleteBucketRequest); + } + + + + @Test + void whenVerifyingListObjects_thenCorrect() { + ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build(); + ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build(); + + when(s3Client.listObjectsV2(request)).thenReturn(response); + + s3Service.listObjects(AWS_BUCKET); + verify(s3Client).listObjectsV2(request); + } + + + @Test + void whenVerifyingCopyObject_thenCorrect() { + CopyObjectRequest request = CopyObjectRequest.builder() + .sourceBucket(BUCKET_NAME) + .sourceKey(KEY_NAME) + .destinationBucket(BUCKET_NAME2) + .destinationKey(KEY_NAME2) + .build(); + + CopyObjectResponse result = CopyObjectResponse.builder().build(); + + when(s3Client.copyObject(request)).thenReturn(result); + + assertThat(s3Service.copyObject(BUCKET_NAME, KEY_NAME, BUCKET_NAME2, KEY_NAME2)).isEqualTo(result); + verify(s3Client).copyObject(request); + } + + @Test + void whenVerifyingDeleteObject_thenCorrect() { + DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder() + .bucket(BUCKET_NAME) + .key(KEY_NAME) + .build(); + + s3Service.deleteObject(BUCKET_NAME, KEY_NAME); + verify(s3Client).deleteObject(deleteObjectRequest); + } +} diff --git a/aws-modules/aws-s3-v2/src/test/java/com/baeldung/s3/listobjects/S3ServiceLiveTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceLiveTest.java similarity index 85% rename from aws-modules/aws-s3-v2/src/test/java/com/baeldung/s3/listobjects/S3ServiceLiveTest.java rename to aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceLiveTest.java index 40b30f8669..c46af81564 100644 --- a/aws-modules/aws-s3-v2/src/test/java/com/baeldung/s3/listobjects/S3ServiceLiveTest.java +++ b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceLiveTest.java @@ -1,109 +1,109 @@ -package com.baeldung.s3.listobjects; - -import com.baeldung.s3.listobjects.S3Service; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import software.amazon.awssdk.services.s3.S3Client; -import software.amazon.awssdk.services.s3.model.ListBucketsResponse; -import software.amazon.awssdk.services.s3.model.ListObjectsV2Request; -import software.amazon.awssdk.services.s3.model.ListObjectsV2Response; -import software.amazon.awssdk.services.s3.model.S3Object; -import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable; - -import java.util.Arrays; -import java.util.Collections; - -import static org.mockito.Mockito.when; - -class S3ServiceLiveTest { - - @Mock - private S3Client s3Client; - - private S3Service s3Service; - - private String AWS_BUCKET = "baeldung-tutorial-s3"; - - @BeforeEach - public void setup() { - MockitoAnnotations.openMocks(this); - s3Service = new S3Service(s3Client); - } - - @AfterEach - public void cleanup() { - s3Service.cleanup(); - Mockito.verify(s3Client).close(); - } - - @Test - public void givenBucketName_whenListObjectsInBucket_thenReturnList() { - ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build(); - ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build(); - - when(s3Client.listObjectsV2(request)).thenReturn(response); - - s3Service.listObjectsInBucket(AWS_BUCKET); - Mockito.verify(s3Client).listObjectsV2(request); - } - - @Test - public void givenBucketName_whenListAllObjectsInBucket_thenReturnList() { - ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build(); - ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build(); - - when(s3Client.listObjectsV2(request)).thenReturn(response); - - s3Service.listAllObjectsInBucket(AWS_BUCKET); - Mockito.verify(s3Client).listObjectsV2(request); - } - - @Test - public void givenBucketNameAndPageSize_whenListAllObjectsInBucketPaginated_thenReturnPaginatedList() { - int pageSize = 10; - ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).maxKeys(pageSize).build(); - - ListObjectsV2Iterable mockIterable = Mockito.mock(ListObjectsV2Iterable.class); - - S3Object s3Object1 = S3Object.builder().key("object1").build(); - S3Object s3Object2 = S3Object.builder().key("object2").build(); - ListObjectsV2Response response = ListObjectsV2Response.builder().contents(s3Object1, s3Object2).build(); - - when(s3Client.listObjectsV2Paginator(request)).thenReturn(mockIterable); - when(mockIterable.iterator()).thenReturn(Arrays.asList(response).iterator()); - - s3Service.listAllObjectsInBucketPaginated(AWS_BUCKET, pageSize); - Mockito.verify(s3Client).listObjectsV2Paginator(request); - } - - @Test - public void givenBucketNamePageSizeAndPrefix_whenListAllObjectsInBucketPaginatedWithPrefix_thenReturnPaginatedList() { - int pageSize = 1; - String prefix = "folder/"; - ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).maxKeys(pageSize).prefix(prefix).build(); - - ListObjectsV2Iterable mockIterable = Mockito.mock(ListObjectsV2Iterable.class); - - S3Object s3Object1 = S3Object.builder().key("folder/object1").build(); - S3Object s3Object2 = S3Object.builder().key("folder/object2").build(); - ListObjectsV2Response response = ListObjectsV2Response.builder().contents(s3Object1, s3Object2).build(); - - when(s3Client.listObjectsV2Paginator(request)).thenReturn(mockIterable); - when(mockIterable.iterator()).thenReturn(Arrays.asList(response).iterator()); - - s3Service.listAllObjectsInBucketPaginatedWithPrefix(AWS_BUCKET, pageSize, prefix); - Mockito.verify(s3Client).listObjectsV2Paginator(request); - } - - @Test - public void whenListBuckets_thenReturnBucketList() { - when(s3Client.listBuckets()).thenReturn(ListBucketsResponse.builder().buckets(Collections.emptyList()).build()); - - s3Service.listBuckets(); - Mockito.verify(s3Client).listBuckets(); - } -} +package com.baeldung.s3; + +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.ListBucketsResponse; +import software.amazon.awssdk.services.s3.model.ListObjectsV2Request; +import software.amazon.awssdk.services.s3.model.ListObjectsV2Response; +import software.amazon.awssdk.services.s3.model.S3Object; +import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable; + +import java.util.Arrays; +import java.util.Collections; + +class S3ServiceLiveTest { + + @Mock + private S3Client s3Client; + + private S3Service s3Service; + + private String AWS_BUCKET = "baeldung-tutorial-s3"; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + s3Service = new S3Service(s3Client); + } + + @AfterEach + public void cleanup() { + s3Service.cleanup(); + Mockito.verify(s3Client).close(); + } + + @Test + void givenBucketName_whenListObjectsInBucket_thenReturnList() { + ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build(); + ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build(); + + when(s3Client.listObjectsV2(request)).thenReturn(response); + + s3Service.listObjectsInBucket(AWS_BUCKET); + Mockito.verify(s3Client).listObjectsV2(request); + } + + @Test + void givenBucketName_whenListAllObjectsInBucket_thenReturnList() { + ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build(); + ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build(); + + when(s3Client.listObjectsV2(request)).thenReturn(response); + + s3Service.listAllObjectsInBucket(AWS_BUCKET); + Mockito.verify(s3Client).listObjectsV2(request); + } + + @Test + void givenBucketNameAndPageSize_whenListAllObjectsInBucketPaginated_thenReturnPaginatedList() { + int pageSize = 10; + ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).maxKeys(pageSize).build(); + + ListObjectsV2Iterable mockIterable = Mockito.mock(ListObjectsV2Iterable.class); + + S3Object s3Object1 = S3Object.builder().key("object1").build(); + S3Object s3Object2 = S3Object.builder().key("object2").build(); + ListObjectsV2Response response = ListObjectsV2Response.builder().contents(s3Object1, s3Object2).build(); + + when(s3Client.listObjectsV2Paginator(request)).thenReturn(mockIterable); + when(mockIterable.iterator()).thenReturn(Arrays.asList(response).iterator()); + + s3Service.listAllObjectsInBucketPaginated(AWS_BUCKET, pageSize); + Mockito.verify(s3Client).listObjectsV2Paginator(request); + } + + @Test + void givenBucketNamePageSizeAndPrefix_whenListAllObjectsInBucketPaginatedWithPrefix_thenReturnPaginatedList() { + int pageSize = 1; + String prefix = "folder/"; + ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).maxKeys(pageSize).prefix(prefix).build(); + + ListObjectsV2Iterable mockIterable = Mockito.mock(ListObjectsV2Iterable.class); + + S3Object s3Object1 = S3Object.builder().key("folder/object1").build(); + S3Object s3Object2 = S3Object.builder().key("folder/object2").build(); + ListObjectsV2Response response = ListObjectsV2Response.builder().contents(s3Object1, s3Object2).build(); + + when(s3Client.listObjectsV2Paginator(request)).thenReturn(mockIterable); + when(mockIterable.iterator()).thenReturn(Arrays.asList(response).iterator()); + + s3Service.listAllObjectsInBucketPaginatedWithPrefix(AWS_BUCKET, pageSize, prefix); + Mockito.verify(s3Client).listObjectsV2Paginator(request); + } + + @Test + void whenListBuckets_thenReturnBucketList() { + when(s3Client.listBuckets()).thenReturn(ListBucketsResponse.builder().buckets(Collections.emptyList()).build()); + + s3Service.listBuckets(); + Mockito.verify(s3Client).listBuckets(); + } +} diff --git a/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceManualTest.java b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceManualTest.java new file mode 100644 index 0000000000..defe75e346 --- /dev/null +++ b/aws-modules/aws-s3/src/test/java/com/baeldung/s3/S3ServiceManualTest.java @@ -0,0 +1,51 @@ +package com.baeldung.s3; + + +import static org.junit.jupiter.api.Assertions.assertTrue; + + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; + +import software.amazon.awssdk.services.s3.S3Client; + +/** + * Required defined environment variables AWS_ACCESS_KEY_ID & AWS_ACCESS_KEY to access S3. + * Required S3 bucket and key that exist. + */ + +class S3ServiceManualTest { + + private static final String BUCKET_NAME = "bucket_name"; + private static final String KEY_NAME = "key_name"; + @Mock + private S3Client s3Client; + + private S3Service s3Service; + + @BeforeEach + public void setup() { + MockitoAnnotations.openMocks(this); + s3Service = new S3Service(s3Client); + } + + @AfterEach + public void cleanup() { + s3Service.cleanup(); + Mockito.verify(s3Client).close(); + } + + @Test + void whenVerifyIfObjectExistByDefaultMethod_thenCorrect() { + assertTrue(s3Service.doesObjectExistByDefaultMethod(BUCKET_NAME, KEY_NAME), "Key: " + KEY_NAME + " doesn't exist"); + } + + @Test + void whenVerifyIfObjectExistByListObjects_thenCorrect() { + assertTrue(s3Service.doesObjectExistByListObjects(BUCKET_NAME, KEY_NAME), "Key: " + KEY_NAME + " doesn't exist"); + } +} diff --git a/aws-modules/pom.xml b/aws-modules/pom.xml index 77872e3f8f..b94faafa86 100644 --- a/aws-modules/pom.xml +++ b/aws-modules/pom.xml @@ -19,7 +19,7 @@ aws-miscellaneous aws-reactive aws-s3 - aws-s3-v2 + aws-s3-update-object diff --git a/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ConstraintsBuilder.java b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ConstraintsBuilder.java new file mode 100644 index 0000000000..ce437fac6d --- /dev/null +++ b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ConstraintsBuilder.java @@ -0,0 +1,15 @@ +package reminderapplication; + +import java.awt.GridBagConstraints; +import java.awt.Insets; + +public class ConstraintsBuilder { + + static GridBagConstraints constraint(int x, int y) { + final GridBagConstraints gridBagConstraints = new GridBagConstraints(); + gridBagConstraints.gridx = x; + gridBagConstraints.gridy = y; + gridBagConstraints.insets = new Insets(5, 5, 5, 5); + return gridBagConstraints; + } +} diff --git a/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/EditReminderFrame.java b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/EditReminderFrame.java new file mode 100644 index 0000000000..818cea403e --- /dev/null +++ b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/EditReminderFrame.java @@ -0,0 +1,194 @@ +package reminderapplication; + +import static reminderapplication.ConstraintsBuilder.*; + +import java.awt.GridBagLayout; +import java.awt.HeadlessException; +import java.lang.reflect.InvocationTargetException; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; +import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.SwingUtilities; + +public class EditReminderFrame extends JFrame { + + private static Timer TIMER = new Timer(); + + private final TimeReminderApplication reminderApplication; + private final JLabel reminderTextLabel; + private final JLabel repeatPeriodLabel; + private final JLabel setDelayLabel; + private final JComboBox delay; + private final JComboBox period; + private final JButton cancelButton; + private final JButton okButton; + private final JTextField textField; + private final JLabel delaysLabel; + private final JLabel periodLabel; + + private final int reminderIndex; + + public EditReminderFrame(TimeReminderApplication reminderApp, String reminderText, int delayInSeconds, int periodInSeconds, int index) throws HeadlessException { + this.reminderApplication = reminderApp; + reminderIndex = index; + textField = createTextField(reminderText); + delay = createDelayComboBox(delayInSeconds); + period = createPeriodComboBox(periodInSeconds); + cancelButton = createCancelButton(); + okButton = createOkButton(); + reminderTextLabel = createReminderTextLabel(); + repeatPeriodLabel = createRepeatPeriodLabel(); + setDelayLabel = createSetDelayLabel(); + delaysLabel = createDelaysLabel(); + periodLabel = createPeriodLabel(); + configureVisualRepresentation(); + configureActions(); + } + + private void configureActions() { + updateReminder(); + } + + private void configureVisualRepresentation() { + configureFrame(); + setLocationRelativeTo(null); + setLayout(new GridBagLayout()); + add(reminderTextLabel, constraint(0,0)); + add(repeatPeriodLabel, constraint(1,0)); + add(setDelayLabel, constraint(2,0)); + add(textField, constraint(0, 1)); + add(delay, constraint(1, 1)); + add(period, constraint(2, 1)); + add(delaysLabel, constraint(1,3)); + add(periodLabel, constraint(2,3)); + add(okButton, constraint(1, 4)); + add(cancelButton, constraint(2, 4)); + pack(); + setVisible(true); + } + + private void configureFrame() { + setTitle("Set Reminder"); + setName("Set Reminder"); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + } + + private static JLabel createSetDelayLabel() { + return createLabel("Set Delay", "Set Delay Label"); + } + + private static JLabel createRepeatPeriodLabel() { + return createLabel("Set Period", "Set Repeat Period Label"); + } + + private static JLabel createReminderTextLabel() { + return createLabel("Reminder Text", "Reminder Text Label"); + } + + private JLabel createPeriodLabel() { + return createLabel("0", "Period label"); + } + + private JLabel createDelaysLabel() { + return createLabel("30", "Delays Label"); + } + + private JComboBox createPeriodComboBox(final int periodInSeconds) { + final JComboBox comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20})); + comboBox.setSelectedItem(periodInSeconds); + comboBox.setName("set Period"); + comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString())); + return comboBox; + } + + private JComboBox createDelayComboBox(final int delayInSeconds) { + final JComboBox comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5})); + comboBox.setSelectedItem(delayInSeconds); + comboBox.setName("set Delay"); + comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString())); + return comboBox; + } + + private JTextField createTextField(final String reminderText) { + final JTextField textField = new JTextField(20); + textField.setName("Field"); + textField.setText(reminderText); + return textField; + } + + private JButton createOkButton() { + final JButton button = new JButton("ok"); + button.setName("OK"); + return button; + } + + private void updateReminder() { + okButton.addActionListener(e -> this.dispose()); + okButton.addActionListener(e -> { + final int periodInSeconds = getTimeInSeconds(period); + final int delayInSeconds = getTimeInSeconds(delay); + final Reminder reminder = new Reminder(textField.getText(), delayInSeconds, periodInSeconds); + ((DefaultListModel) reminderApplication.getReminders()).set(reminderIndex, reminder); + }); + okButton.addActionListener(e -> scheduleReminder(textField, delay, period)); + } + + private void scheduleReminder(final JTextField textField, final JComboBox delay, final JComboBox period) { + final int periodInSeconds = getTimeInSeconds(period); + if (periodInSeconds == 0) + scheduleNonRepeatedReminder(textField, delay); + else + scheduleRepeatedReminder(textField, delay, period); + } + + private void scheduleRepeatedReminder(final JTextField textField, final JComboBox delay, final JComboBox period) { + final int delayInSeconds = getTimeInSeconds(delay); + final int periodInSeconds = getTimeInSeconds(period); + final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds); + TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds), TimeUnit.SECONDS.toMillis(periodInSeconds)); + } + + private void scheduleNonRepeatedReminder(final JTextField textField, final JComboBox delay) { + final int delayInSeconds = getTimeInSeconds(delay); + final int periodInSeconds = 0; + final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds); + TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds)); + + } + + private int getTimeInSeconds(final JComboBox comboBox) { + if (comboBox != null && comboBox.getSelectedItem() != null) + return ((Integer) comboBox.getSelectedItem()); + else + return 0; + } + + private TimerTask getTimerTask(final String reminderText, final Integer delayInSeconds, final Integer periodInSeconds) { + return new TimerTask() { + @Override + public void run() { + new ReminderPopupFrame(reminderApplication, reminderText, delayInSeconds, periodInSeconds); + } + }; + } + + private JButton createCancelButton() { + final JButton button = new JButton("cancel"); + button.setName("Cancel"); + button.addActionListener(e -> this.dispose()); + return button; + } + + private static JLabel createLabel(final String text, final String name) { + JLabel label = new JLabel(text); + label.setName(name); + return label; + } +} diff --git a/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/Reminder.java b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/Reminder.java new file mode 100644 index 0000000000..8f6ff336ed --- /dev/null +++ b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/Reminder.java @@ -0,0 +1,33 @@ +package reminderapplication; + +public class Reminder { + + private static String REMINDER_FORMAT = "Reminder Text: %s; Delay: %d; Period: %d;"; + + private final String name; + private final int delay; + private final int period; + + public Reminder(final String name, final int delay, final int period) { + this.name = name; + this.delay = delay; + this.period = period; + } + + public String getName() { + return name; + } + + public int getDelay() { + return delay; + } + + public int getPeriod() { + return period; + } + + @Override + public String toString() { + return REMINDER_FORMAT.formatted(name, delay, period); + } +} diff --git a/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ReminderFrame.java b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ReminderFrame.java new file mode 100644 index 0000000000..3a1623219c --- /dev/null +++ b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ReminderFrame.java @@ -0,0 +1,186 @@ +package reminderapplication; + +import static reminderapplication.ConstraintsBuilder.*; + +import java.awt.GridBagLayout; +import java.awt.HeadlessException; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; +import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; + +public class ReminderFrame extends JFrame { + + private static Timer TIMER = new Timer(); + private final TimeReminderApplication reminderApplication; + private final JLabel reminderTextLabel; + private final JLabel repeatPeriodLabel; + private final JLabel setDelayLabel; + private final JComboBox delay; + private final JComboBox period; + private final JButton cancelButton; + private final JButton okButton; + private final JTextField textField; + private final JLabel delaysLabel; + private final JLabel periodLabel; + + public ReminderFrame(TimeReminderApplication reminderApp) throws HeadlessException { + this.reminderApplication = reminderApp; + textField = createTextField(); + delay = createDelayComboBox(); + period = createPeriodComboBox(); + cancelButton = createCancelButton(); + okButton = createOkButton(); + reminderTextLabel = createReminderTextLabel(); + repeatPeriodLabel = createRepeatPeriodLabel(); + setDelayLabel = createSetDelayLabel(); + delaysLabel = createDelaysLabel(); + periodLabel = createPeriodLabel(); + configureVisualRepresentation(); + configureActions(); + } + + private void configureActions() { + createNewReminder(); + } + + private void configureVisualRepresentation() { + configureFrame(); + setLocationRelativeTo(null); + setLayout(new GridBagLayout()); + add(reminderTextLabel, constraint(0,0)); + add(repeatPeriodLabel, constraint(1,0)); + add(setDelayLabel, constraint(2,0)); + add(textField, constraint(0, 1)); + add(delay, constraint(1, 1)); + add(period, constraint(2, 1)); + add(delaysLabel, constraint(1,3)); + add(periodLabel, constraint(2,3)); + add(okButton, constraint(1, 4)); + add(cancelButton, constraint(2, 4)); + pack(); + setVisible(true); + } + + private void configureFrame() { + setTitle("Set Reminder"); + setName("Set Reminder"); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + } + + private static JLabel createSetDelayLabel() { + return createLabel("Set Delay", "Set Delay Label"); + } + + private static JLabel createRepeatPeriodLabel() { + return createLabel("Set Period", "Set Repeat Period Label"); + } + + private static JLabel createReminderTextLabel() { + return createLabel("Reminder Text", "Reminder Text Label"); + } + + private JLabel createPeriodLabel() { + return createLabel("0", "Period label"); + } + + private JLabel createDelaysLabel() { + return createLabel("30", "Delays Label"); + } + + private JComboBox createPeriodComboBox() { + final JComboBox comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20})); + comboBox.setName("set Period"); + comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString())); + return comboBox; + } + + private JComboBox createDelayComboBox() { + final JComboBox comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5})); + comboBox.setName("set Delay"); + comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString())); + return comboBox; + } + + private JTextField createTextField() { + final JTextField textField = new JTextField(20); + textField.setName("Field"); + return textField; + } + + private JButton createOkButton() { + final JButton button = new JButton("ok"); + button.setName("OK"); + return button; + } + + private void createNewReminder() { + + okButton.addActionListener(e -> this.dispose()); + okButton.addActionListener(e -> { + final int periodInSeconds = getTimeInSeconds(period); + final int delayInSeconds = getTimeInSeconds(delay); + final Reminder reminder = new Reminder(textField.getText(), delayInSeconds, periodInSeconds); + ((DefaultListModel) reminderApplication.getReminders()).addElement(reminder); + }); + okButton.addActionListener(e -> scheduleReminder(textField, delay, period)); + } + + private void scheduleReminder(final JTextField textField, final JComboBox delay, final JComboBox period) { + final int periodInSeconds = getTimeInSeconds(period); + if (periodInSeconds == 0) + scheduleNonRepeatedReminder(textField, delay); + else + scheduleRepeatedReminder(textField, delay, period); + } + + private void scheduleRepeatedReminder(final JTextField textField, final JComboBox delay, final JComboBox period) { + final int delayInSeconds = getTimeInSeconds(delay) + 200; + final int periodInSeconds = getTimeInSeconds(period); + final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds); + TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds), TimeUnit.SECONDS.toMillis(periodInSeconds)); + } + + private void scheduleNonRepeatedReminder(final JTextField textField, final JComboBox delay) { + final int delayInSeconds = getTimeInSeconds(delay); + final int periodInSeconds = 0; + final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds); + TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds)); + + } + + private int getTimeInSeconds(final JComboBox comboBox) { + if (comboBox != null && comboBox.getSelectedItem() != null) + return ((Integer) comboBox.getSelectedItem()); + else + return 0; + } + + private TimerTask getTimerTask(final String reminderText, final Integer delayInSeconds, final Integer periodInSeconds) { + return new TimerTask() { + @Override + public void run() { + new ReminderPopupFrame(reminderApplication, reminderText, delayInSeconds, periodInSeconds); + } + }; + } + + private JButton createCancelButton() { + final JButton button = new JButton("cancel"); + button.setName("Cancel"); + button.addActionListener(e -> this.dispose()); + return button; + } + + private static JLabel createLabel(final String text, final String name) { + JLabel label = new JLabel(text); + label.setName(name); + return label; + } +} diff --git a/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ReminderPopupFrame.java b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ReminderPopupFrame.java new file mode 100644 index 0000000000..d41343cb6d --- /dev/null +++ b/core-java-modules/Reminder Application/Reminder Application/task/src/reminderapplication/ReminderPopupFrame.java @@ -0,0 +1,151 @@ +package reminderapplication; + +import static reminderapplication.ConstraintsBuilder.*; + +import java.awt.GridBagLayout; +import java.awt.HeadlessException; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; +import javax.swing.DefaultComboBoxModel; +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; + +public class ReminderPopupFrame extends JFrame { + + private static final Timer TIMER = new Timer(); + private final int AUTOMATIC_CLOSE_TIME_IN_SECONDS = 10; + private final TimeReminderApplication reminderApplication; + private final JLabel reminderTextLabel; + private final JLabel repeatPeriodLabel; + private final JLabel setDelayLabel; + private final JComboBox delay; + private final JComboBox period; + private final JButton cancelButton; + private final JButton okButton; + private final JTextField textField; + private final JLabel delaysLabel; + private final JLabel periodLabel; + + public ReminderPopupFrame(TimeReminderApplication reminderApp, final String text, final Integer delayInSeconds, final Integer periodInSeconds) throws HeadlessException { + this.reminderApplication = reminderApp; + textField = createTextField(text); + delay = createDelayComboBox(delayInSeconds); + period = createPeriodComboBox(periodInSeconds); + cancelButton = createCancelButton(); + okButton = createDisabledOkButton(); + reminderTextLabel = createReminderTextLabel(); + repeatPeriodLabel = createRepeatPeriodLabel(); + setDelayLabel = createSetDelayLabel(); + delaysLabel = createDelaysLabel(); + periodLabel = createPeriodLabel(); + configureVisualRepresentation(); + configureActions(); + } + + private void configureActions() { + scheduleClosing(); + } + + private void scheduleClosing() { + final TimerTask timerTask = new TimerTask() { + @Override + public void run() { + ReminderPopupFrame.this.dispose(); + } + }; + TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(AUTOMATIC_CLOSE_TIME_IN_SECONDS)); + } + + private void configureVisualRepresentation() { + configureFrame(); + setLocationRelativeTo(null); + setLayout(new GridBagLayout()); + add(reminderTextLabel, constraint(0,0)); + add(repeatPeriodLabel, constraint(1,0)); + add(setDelayLabel, constraint(2,0)); + add(textField, constraint(0, 1)); + add(delay, constraint(1, 1)); + add(period, constraint(2, 1)); + add(delaysLabel, constraint(1,3)); + add(periodLabel, constraint(2,3)); + add(okButton, constraint(1, 4)); + add(cancelButton, constraint(2, 4)); + pack(); + setVisible(true); + } + + private void configureFrame() { + setTitle("Set Reminder"); + setName("Set Reminder"); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + } + + private static JLabel createSetDelayLabel() { + return createLabel("Set Delay", "Set Delay Label"); + } + + private static JLabel createRepeatPeriodLabel() { + return createLabel("Set Period", "Set Repeat Period Label"); + } + + private static JLabel createReminderTextLabel() { + return createLabel("Reminder Text", "Reminder Text Label"); + } + + private JLabel createPeriodLabel() { + return createLabel("0", "Period label"); + } + + private JLabel createDelaysLabel() { + return createLabel("30", "Delays Label"); + } + + private JComboBox createPeriodComboBox(final Integer periodInSeconds) { + final JComboBox comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20})); + comboBox.setName("set Period"); + comboBox.setSelectedItem(periodInSeconds); + comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString())); + return comboBox; + } + + private JComboBox createDelayComboBox(Integer delay) { + final JComboBox comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5})); + comboBox.setSelectedItem(delay); + comboBox.setName("set Delay"); + comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString())); + return comboBox; + } + + private JTextField createTextField(final String text) { + final JTextField textField = new JTextField(20); + textField.setName("Field"); + textField.setText(text); + return textField; + } + + private JButton createDisabledOkButton() { + final JButton button = new JButton("ok"); + button.setName("OK"); + button.setEnabled(false); + return button; + } + + private JButton createCancelButton() { + final JButton button = new JButton("cancel"); + button.setName("Cancel"); + button.addActionListener(e -> this.dispose()); + return button; + } + + private static JLabel createLabel(final String text, final String name) { + JLabel label = new JLabel(text); + label.setName(name); + return label; + } + +} diff --git a/core-java-modules/core-java-9/README.md b/core-java-modules/core-java-9/README.md index bd7df0c8a6..43f8bf8ca8 100644 --- a/core-java-modules/core-java-9/README.md +++ b/core-java-modules/core-java-9/README.md @@ -12,3 +12,4 @@ This module contains articles about Java 9 core features - [Private Methods in Java Interfaces](https://www.baeldung.com/java-interface-private-methods) - [Java Scanner useDelimiter with Examples](https://www.baeldung.com/java-scanner-usedelimiter) - [Is There a Destructor in Java?](https://www.baeldung.com/java-destructor) +- [Java 9 Migration Issues and Resolutions](https://www.baeldung.com/java-9-migration-issue) \ No newline at end of file diff --git a/core-java-modules/core-java-9/pom.xml b/core-java-modules/core-java-9/pom.xml index bcfdacdf1d..616dceb2bf 100644 --- a/core-java-modules/core-java-9/pom.xml +++ b/core-java-modules/core-java-9/pom.xml @@ -46,6 +46,11 @@ commons-io ${commons-io.version} + + javax.xml.bind + jaxb-api + ${javax.xml.bind.version} + @@ -58,6 +63,9 @@ ${maven.compiler.source} ${maven.compiler.target} + + --add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED + @@ -74,6 +82,7 @@ 1.7.0 1.9 1.9 + 2.4.0-b180725.0427 \ No newline at end of file diff --git a/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/App.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/prejpms/App.java similarity index 98% rename from core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/App.java rename to core-java-modules/core-java-9/src/main/java/com/baeldung/java9/prejpms/App.java index a69e0555c6..d97ff4b743 100644 --- a/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/App.java +++ b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/prejpms/App.java @@ -1,15 +1,16 @@ -package com.baeldung.prejpms; +package com.baeldung.java9.prejpms; import java.io.StringWriter; import java.lang.StackWalker.Option; import java.lang.StackWalker.StackFrame; -import com.sun.crypto.provider.SunJCE; import java.util.Base64; import java.util.concurrent.atomic.AtomicInteger; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; +import com.sun.crypto.provider.SunJCE; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/Book.java b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/prejpms/Book.java similarity index 94% rename from core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/Book.java rename to core-java-modules/core-java-9/src/main/java/com/baeldung/java9/prejpms/Book.java index 6780c73738..f94096b722 100644 --- a/core-java-modules/pre-jpms/src/main/java/com/baeldung/prejpms/Book.java +++ b/core-java-modules/core-java-9/src/main/java/com/baeldung/java9/prejpms/Book.java @@ -1,4 +1,4 @@ -package com.baeldung.prejpms; +package com.baeldung.java9.prejpms; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; diff --git a/core-java-modules/core-java-arrays-convert/README.md b/core-java-modules/core-java-arrays-convert/README.md index fecbcfb698..dcaaaac12e 100644 --- a/core-java-modules/core-java-arrays-convert/README.md +++ b/core-java-modules/core-java-arrays-convert/README.md @@ -8,3 +8,5 @@ This module contains articles about arrays conversion in Java - [Convert a Byte Array to a Numeric Representation in Java](https://www.baeldung.com/java-byte-array-to-number) - [Converting a String Array Into an int Array in Java](https://www.baeldung.com/java-convert-string-array-to-int-array) - [Convert Java Array to Iterable](https://www.baeldung.com/java-array-convert-to-iterable) +- [Converting an int[] to HashSet in Java](https://www.baeldung.com/java-converting-int-array-to-hashset) +- [Convert an ArrayList of String to a String Array in Java](https://www.baeldung.com/java-convert-string-arraylist-array) diff --git a/core-java-modules/core-java-arrays-convert/pom.xml b/core-java-modules/core-java-arrays-convert/pom.xml index c90b60e09a..480e1b3f07 100644 --- a/core-java-modules/core-java-arrays-convert/pom.xml +++ b/core-java-modules/core-java-arrays-convert/pom.xml @@ -20,5 +20,4 @@ ${commons-lang3.version} - \ No newline at end of file diff --git a/core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/PrimitiveIntArrayToHashSetUnitTest.java b/core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/PrimitiveIntArrayToHashSetUnitTest.java new file mode 100644 index 0000000000..ca658d3e97 --- /dev/null +++ b/core-java-modules/core-java-arrays-convert/src/test/java/com/baeldung/array/conversions/PrimitiveIntArrayToHashSetUnitTest.java @@ -0,0 +1,53 @@ +package com.baeldung.array.conversions; + +import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.stream.Collectors; + +import org.apache.commons.lang3.ArrayUtils; +import org.junit.Test; + +import com.google.common.primitives.Ints; + +public class PrimitiveIntArrayToHashSetUnitTest { + int[] arr = { 1, 2, 3, 4, 5 }; + HashSet expected = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5)); + + @Test + public void givenPrimitiveIntArray_whenConvertingByDirectConstructor_thenGiveWrongResult() { + HashSet result = new HashSet<>(Arrays.asList(arr)); + assertEquals(1, result.size()); + assertNotEquals(expected, result); + } + + @Test + public void givenPrimitiveIntArray_whenConvertingByLoop_thenSuccess() { + HashSet result = new HashSet<>(); + for (int num : arr) { + result.add(num); + } + assertEquals(expected, result); + } + + @Test + public void givenPrimitiveIntArray_whenConvertingByStreams_thenSuccess() { + HashSet result = Arrays.stream(arr).boxed().collect(Collectors.toCollection(HashSet::new)); + assertEquals(expected, result); + } + + @Test + public void givenPrimitiveIntArray_whenConvertingByArrayUtils_thenSuccess() { + HashSet result = new HashSet<>(Arrays.asList(ArrayUtils.toObject(arr))); + assertEquals(expected, result); + } + + @Test + public void givenPrimitiveIntArray_whenConvertingByGuava_thenSuccess() { + HashSet result = new HashSet<>(Ints.asList(arr)); + assertEquals(expected, result); + } + +} diff --git a/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraysums/SumArraysUsingForEach.java b/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraysums/SumArraysUsingForEach.java new file mode 100644 index 0000000000..3c2a75a409 --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraysums/SumArraysUsingForEach.java @@ -0,0 +1,14 @@ +package com.baeldung.arraysums; + +public class SumArraysUsingForEach { + + public static int[] sumOfTwoArrays(int[] arr1, int[] arr2) { + int[] arr3 = new int[arr1.length]; + int counter = 0; + for (int num1 : arr1) { + arr3[counter] = num1 + arr2[counter]; + counter++; + } + return arr3; + } +} diff --git a/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraysums/SumArraysUsingForLoop.java b/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraysums/SumArraysUsingForLoop.java new file mode 100644 index 0000000000..32e2e939d4 --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraysums/SumArraysUsingForLoop.java @@ -0,0 +1,12 @@ +package com.baeldung.arraysums; + +public class SumArraysUsingForLoop { + + public static int[] sumOfTwoArrays(int[] arr1, int[] arr2) { + int[] arr3 = new int[arr1.length]; + for (int i = 0; i < arr1.length; i++) { + arr3[i] = arr1[i] + arr2[i]; + } + return arr3; + } +} diff --git a/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraysums/SumArraysUsingStreams.java b/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraysums/SumArraysUsingStreams.java new file mode 100644 index 0000000000..40bfda4b74 --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-advanced/src/main/java/com/baeldung/arraysums/SumArraysUsingStreams.java @@ -0,0 +1,14 @@ +package com.baeldung.arraysums; + +import java.util.Arrays; +import java.util.stream.IntStream; + +public class SumArraysUsingStreams { + + public static int[] sumOfTwoArrays(int[] arr1, int[] arr2) { + IntStream range = IntStream.range(0, Math.min(arr1.length, arr2.length)); + IntStream stream3 = range.map(i -> arr1[i] + arr2[i]); + int[] arr3 = stream3.toArray(); + return arr3; + } +} diff --git a/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arraysums/SumArraysUsingForEachUnitTest.java b/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arraysums/SumArraysUsingForEachUnitTest.java new file mode 100644 index 0000000000..883b35b223 --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arraysums/SumArraysUsingForEachUnitTest.java @@ -0,0 +1,16 @@ +package com.baeldung.arraysums; + +import com.baeldung.arraysums.SumArraysUsingForEach; +import org.junit.Test; +import static org.junit.Assert.*; + +public class SumArraysUsingForEachUnitTest { + + @Test + public void sumOfTwoArraysUsingForEach_GivenTwoEqualSizedIntArrays_ReturnsCorrectSumArray() { + int[] arr1 = { 4, 5, 1, 6, 4, 15 }; + int[] arr2 = { 3, 5, 6, 1, 9, 6 }; + int[] expected = { 7, 10, 7, 7, 13, 21 }; + assertArrayEquals(expected, SumArraysUsingForEach.sumOfTwoArrays(arr1, arr2)); + } +} diff --git a/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arraysums/SumArraysUsingForLoopUnitTest.java b/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arraysums/SumArraysUsingForLoopUnitTest.java new file mode 100644 index 0000000000..7cffd5f4ff --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arraysums/SumArraysUsingForLoopUnitTest.java @@ -0,0 +1,16 @@ +package com.baeldung.arraysums; + +import com.baeldung.arraysums.SumArraysUsingForLoop; +import org.junit.Test; +import static org.junit.Assert.*; + +public class SumArraysUsingForLoopUnitTest { + + @Test + public void sumOfTwoArrays_GivenTwoEqualSizedIntArrays_ReturnsCorrectSumArray() { + int[] arr1 = {4, 5, 1, 6, 4, 15}; + int[] arr2 = {3, 5, 6, 1, 9, 6}; + int[] expected = {7, 10, 7, 7, 13, 21}; + assertArrayEquals(expected, SumArraysUsingForLoop.sumOfTwoArrays(arr1, arr2)); + } +} diff --git a/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arraysums/SumArraysUsingStreamsUnitTest.java b/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arraysums/SumArraysUsingStreamsUnitTest.java new file mode 100644 index 0000000000..62ea465ab0 --- /dev/null +++ b/core-java-modules/core-java-arrays-operations-advanced/src/test/java/com/baeldung/arraysums/SumArraysUsingStreamsUnitTest.java @@ -0,0 +1,16 @@ +package com.baeldung.arraysums; + +import com.baeldung.arraysums.SumArraysUsingStreams; +import org.junit.Test; +import static org.junit.Assert.*; + +public class SumArraysUsingStreamsUnitTest { + + @Test + public void sumOfTwoArraysUsingStreams_GivenTwoEqualSizedIntArrays_ReturnsCorrectSumArray() { + int[] arr1 = {4, 5, 1, 6, 4, 15}; + int[] arr2 = {3, 5, 6, 1, 9, 6}; + int[] expected = {7, 10, 7, 7, 13, 21}; + assertArrayEquals(expected, SumArraysUsingStreams.sumOfTwoArrays(arr1, arr2)); + } +} diff --git a/core-java-modules/core-java-collections-conversions-2/README.md b/core-java-modules/core-java-collections-conversions-2/README.md index fe17af0a7a..efd01c46ee 100644 --- a/core-java-modules/core-java-collections-conversions-2/README.md +++ b/core-java-modules/core-java-collections-conversions-2/README.md @@ -12,4 +12,5 @@ This module contains articles about conversions among Collection types and array - [Convert a List of Integers to a List of Strings](https://www.baeldung.com/java-convert-list-integers-to-list-strings) - [Combining Two Lists Into a Map in Java](https://www.baeldung.com/java-combine-two-lists-into-map) - [Convert a List of Strings to a List of Integers](https://www.baeldung.com/java-convert-list-strings-to-integers) +- [Convert List to Long[] Array in Java](https://www.baeldung.com/java-convert-list-object-to-long-array) - More articles: [[<-- prev]](../core-java-collections-conversions) diff --git a/core-java-modules/core-java-collections-conversions-2/pom.xml b/core-java-modules/core-java-collections-conversions-2/pom.xml index 8cd0a6932b..7b7533fc39 100644 --- a/core-java-modules/core-java-collections-conversions-2/pom.xml +++ b/core-java-modules/core-java-collections-conversions-2/pom.xml @@ -43,6 +43,7 @@ 0.10.3 + 11 + 3.1.1 - \ No newline at end of file diff --git a/core-java-modules/core-java-collections-conversions-2/src/test/java/com/baeldung/arrayconversion/ArrayListToArrayUnitTest.java b/core-java-modules/core-java-collections-conversions-2/src/test/java/com/baeldung/arrayconversion/ArrayListToArrayUnitTest.java new file mode 100644 index 0000000000..63cdf22f3a --- /dev/null +++ b/core-java-modules/core-java-collections-conversions-2/src/test/java/com/baeldung/arrayconversion/ArrayListToArrayUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.arrayconversion; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.google.common.collect.Lists; + +public class ArrayListToArrayUnitTest { + private static final List INPUT_LIST = Lists.newArrayList("Michael Bolton", "Michael Jackson", "Guns and Roses", "Bryan Adams", "Air Supply"); + private static final String[] EXPECTED_ARRAY = new String[] { "Michael Bolton", "Michael Jackson", "Guns and Roses", "Bryan Adams", "Air Supply" }; + + @Test + void whenUsingForLoop_thenGetExpectedResult() { + String[] result = new String[INPUT_LIST.size()]; + for (int i = 0; i < INPUT_LIST.size(); i++) { + result[i] = INPUT_LIST.get(i); + } + assertArrayEquals(EXPECTED_ARRAY, result); + } + + @Test + void whenUsingListToArray_thenGetExpectedResult() { + String[] result = new String[INPUT_LIST.size()]; + INPUT_LIST.toArray(result); + assertArrayEquals(EXPECTED_ARRAY, result); + + String[] result2 = INPUT_LIST.toArray(new String[0]); + assertArrayEquals(EXPECTED_ARRAY, result2); + } + + @Test + void whenUsingStreamApi_thenGetExpectedResult() { + String[] result = INPUT_LIST.stream() + .toArray(String[]::new); + assertArrayEquals(EXPECTED_ARRAY, result); + } + + @Test + void whenUsingListToArrayInJava11_thenGetExpectedResult() { + String[] result = INPUT_LIST.toArray(String[]::new); + assertArrayEquals(EXPECTED_ARRAY, result); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-conversions-2/src/test/java/com/baeldung/arrayconversion/ListToArrayFirstNElementsUnitTest.java b/core-java-modules/core-java-collections-conversions-2/src/test/java/com/baeldung/arrayconversion/ListToArrayFirstNElementsUnitTest.java new file mode 100644 index 0000000000..c9818613fe --- /dev/null +++ b/core-java-modules/core-java-collections-conversions-2/src/test/java/com/baeldung/arrayconversion/ListToArrayFirstNElementsUnitTest.java @@ -0,0 +1,56 @@ +package com.baeldung.arrayconversion; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; + +import java.util.Iterator; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import com.google.common.collect.Lists; + +public class ListToArrayFirstNElementsUnitTest { + private static final List INPUT_LIST = Lists.newArrayList("one", "two", "three", "four", "five", "six", "seven"); + private static final int n = 5; + + @Test + void whenUsingForLoop_thenGetExpectedArray() { + String[] result = new String[n]; + for (int i = 0; i < n; i++) { + result[i] = INPUT_LIST.get(i); + } + assertArrayEquals(new String[] { "one", "two", "three", "four", "five" }, result); + + String[] result2 = new String[n]; + Iterator iterator = INPUT_LIST.iterator(); + for (int i = 0; i < n && iterator.hasNext(); i++) { + result2[i] = iterator.next(); + } + assertArrayEquals(new String[] { "one", "two", "three", "four", "five" }, result2); + } + + @Test + void whenUsingSubList_thenGetExpectedArray() { + String[] result = new String[n]; + INPUT_LIST.subList(0, n) + .toArray(result); + assertArrayEquals(new String[] { "one", "two", "three", "four", "five" }, result); + + String[] result2 = INPUT_LIST.subList(0, n) + .toArray(new String[0]); + assertArrayEquals(new String[] { "one", "two", "three", "four", "five" }, result2); + + // available only for java 11+ + String[] result3 = INPUT_LIST.subList(0, n) + .toArray(String[]::new); + assertArrayEquals(new String[] { "one", "two", "three", "four", "five" }, result3); + } + + @Test + void whenUsingStream_thenGetExpectedArray() { + String[] result = INPUT_LIST.stream() + .limit(n) + .toArray(String[]::new); + assertArrayEquals(new String[] { "one", "two", "three", "four", "five" }, result); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-list-5/README.md b/core-java-modules/core-java-collections-list-5/README.md index 18ff0c687d..d734cf7364 100644 --- a/core-java-modules/core-java-collections-list-5/README.md +++ b/core-java-modules/core-java-collections-list-5/README.md @@ -11,3 +11,4 @@ This module contains articles about the Java List collection - [Set Default Value for Elements in List](https://www.baeldung.com/java-list-set-default-values) - [Get Unique Values From an ArrayList in Java](https://www.baeldung.com/java-unique-values-arraylist) - [Converting a Java List to a Json Array](https://www.baeldung.com/java-converting-list-to-json-array) +- [What’s the Difference Between Iterator and ListIterator?](https://www.baeldung.com/java-iterator-vs-listiterator) diff --git a/core-java-modules/core-java-collections-list-5/pom.xml b/core-java-modules/core-java-collections-list-5/pom.xml index 144fd12c45..bcdb6824ed 100644 --- a/core-java-modules/core-java-collections-list-5/pom.xml +++ b/core-java-modules/core-java-collections-list-5/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 core-java-collections-list-5 core-java-collections-list-5 @@ -42,11 +42,33 @@ 1.18.26 provided + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + test + + + com.google.code.gson + gson + ${gson.version} + test + + + org.json + json + ${org.json.version} + test + + 1.21 2.2 3.12.0 + 2.10.1 + 2.15.2 + 20230618 \ No newline at end of file diff --git a/core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/java/iteratorandlistiterator/IteratorVsListIteratorUnitTest.java b/core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/java/iteratorandlistiterator/IteratorVsListIteratorUnitTest.java new file mode 100644 index 0000000000..8efe88c24a --- /dev/null +++ b/core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/java/iteratorandlistiterator/IteratorVsListIteratorUnitTest.java @@ -0,0 +1,108 @@ +package com.baeldung.java.iteratorandlistiterator; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; + +import org.junit.jupiter.api.Test; + +import com.google.common.collect.Lists; + +public class IteratorVsListIteratorUnitTest { + + @Test + void whenUsingIterator_thenWeCanTraverseForwardsAndRemoveElements() { + List inputList = Lists.newArrayList("1", "2", "3", "4", "5"); + Iterator it = inputList.iterator(); + while (it.hasNext()) { + String e = it.next(); + if ("3".equals(e) || "5".equals(e)) { + it.remove(); + } + } + + assertEquals(Lists.newArrayList("1", "2", "4"), inputList); + + } + + @Test + void whenUsingListIteratorAlternatingNextAndPrevious_thenAlwaysGetTheSameElement() { + List inputList = Lists.newArrayList("1", "2", "3", "4", "5"); + ListIterator lit = inputList.listIterator(); // ^ 1 2 3 4 5 + lit.next(); // 1 ^ 2 3 4 5 + lit.next(); // 1 2 ^ 3 4 5 + + for (int i = 1; i <= 100; i++) { + assertEquals("2", lit.previous()); + assertEquals("2", lit.next()); + } + + } + + @Test + void whenUsingListIterator_thenRetrieveElementInForwardAndBackwardDirection() { + List inputList = Lists.newArrayList("1", "2", "3", "4", "5"); + ListIterator lit = inputList.listIterator(); // ^ 1 2 3 4 5 + + assertFalse(lit.hasPrevious()); // lit is at the beginning of the list + assertEquals(-1, lit.previousIndex()); + + assertEquals("1", lit.next()); // after next(): 1 ^ 2 3 4 5 + assertEquals("2", lit.next()); // after next(): 1 2 ^ 3 4 5 + assertEquals("3", lit.next()); // after next(): 1 2 3 ^ 4 5 + + assertTrue(lit.hasPrevious()); + assertEquals(2, lit.previousIndex()); + assertEquals("3", lit.previous()); // after previous(): 1 2 ^ 3 4 5 + + assertTrue(lit.hasPrevious()); + assertEquals(1, lit.previousIndex()); + assertEquals("2", lit.previous()); // after previous(): 1 ^ 2 3 4 5 + + assertTrue(lit.hasPrevious()); + assertEquals(0, lit.previousIndex()); + assertEquals("1", lit.previous()); // after previous(): ^ 1 2 3 4 5 + } + + @Test + void whenUsingSetElement_thenGetExpectedResult() { + List inputList = Lists.newArrayList("1", "2", "3", "4", "5"); + ListIterator lit = inputList.listIterator(1); // ^ 1 2 3 4 5 + lit.next(); // 1 ^ 2 3 4 5 + + assertEquals("3", lit.next()); // 1 2 ^ 3 4 5 + lit.set("X"); + assertEquals(Lists.newArrayList("1", "2", "X", "4", "5"), inputList); + + assertEquals("X", lit.previous()); // 1 2 ^ X 4 5 + + assertEquals("2", lit.previous()); // 1 ^ 2 X 4 5 + lit.set("Y"); + assertEquals(Lists.newArrayList("1", "Y", "X", "4", "5"), inputList); + } + + @Test + void whenUsingAddElement_thenGetExpectedResult() { + List inputList = Lists.newArrayList("1", "2", "3", "4", "5"); + ListIterator lit = inputList.listIterator(); // ^ 1 2 3 4 5 + lit.next(); // 1 ^ 2 3 4 5 + lit.next(); // 1 2 ^ 3 4 5 + lit.next(); // 1 2 3 ^ 4 5 + + lit.add("X"); // 1 2 3 X ^ 4 5 + assertEquals("4", lit.next()); // 1 2 3 X 4 ^ 5 + + lit.previous(); // 1 2 3 X ^ 4 5 + lit.previous(); // 1 2 3 ^ X 4 5 + lit.previous(); // 1 2 ^ 3 X 4 5 + lit.add("Y"); // 1 2 Y ^ 3 X 4 5 + + assertEquals("Y", lit.previous()); + + assertEquals(Lists.newArrayList("1", "2", "Y", "3", "X", "4", "5"), inputList); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/java/list/ListContainsElementFromOtherListTest.java b/core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/java/list/ListContainsElementFromOtherListUnitTest.java similarity index 97% rename from core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/java/list/ListContainsElementFromOtherListTest.java rename to core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/java/list/ListContainsElementFromOtherListUnitTest.java index 4ce7c44282..8d981f2746 100644 --- a/core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/java/list/ListContainsElementFromOtherListTest.java +++ b/core-java-modules/core-java-collections-list-5/src/test/java/com/baeldung/java/list/ListContainsElementFromOtherListUnitTest.java @@ -13,7 +13,7 @@ import org.junit.Test; import com.baeldung.list.Country; -public class ListContainsElementFromOtherListTest { +public class ListContainsElementFromOtherListUnitTest { final private List listOfLetters = Arrays.asList("a", "b", "c", "d"); final private List listOfLettersWithOverlap = Arrays.asList("d", "e", "f", "g"); @@ -65,4 +65,4 @@ public class ListContainsElementFromOtherListTest { assertTrue(shouldBeTrue); } -} +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/hashmap/kvtolist/MapKeysValuesToListUnitTest.java b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/hashmap/kvtolist/MapKeysValuesToListUnitTest.java new file mode 100644 index 0000000000..39c537bac2 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-3/src/test/java/com/baeldung/map/hashmap/kvtolist/MapKeysValuesToListUnitTest.java @@ -0,0 +1,72 @@ +package com.baeldung.map.hashmap.kvtolist; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +public class MapKeysValuesToListUnitTest { + private static final HashMap DEV_MAP; + + static { + DEV_MAP = new HashMap<>(); + DEV_MAP.put("Kent", "Linux"); + DEV_MAP.put("Eric", "MacOS"); + DEV_MAP.put("Kevin", "Windows"); + DEV_MAP.put("Michal", "MacOS"); + DEV_MAP.put("Saajan", "Linux"); + } + + @Test + void whenUsingKeySet_thenGetExpectedResult() { + List keyList = new ArrayList<>(DEV_MAP.keySet()); + // this assertion may fail, since hashMap doesn't preserve the insertion order + // assertEquals(Lists.newArrayList("Kent", "Eric", "Kevin", "Michal", "Saajan"), keyList); + + assertThat(keyList).containsExactlyInAnyOrder("Kent", "Eric", "Kevin", "Michal", "Saajan"); + + } + + @Test + void whenUsingValues_thenGetExpectedResult() { + List valueList = new ArrayList<>(DEV_MAP.values()); + assertThat(valueList).containsExactlyInAnyOrder("Linux", "MacOS", "Windows", "MacOS", "Linux"); + } + + @Test + void whenLoopingEntries_thenGetExpectedResult() { + List keyList = new ArrayList<>(); + List valueList = new ArrayList<>(); + for (Map.Entry entry : DEV_MAP.entrySet()) { + keyList.add(entry.getKey()); + valueList.add(entry.getValue()); + } + + assertKeyAndValueList(keyList, valueList); + + } + + @Test + void whenUsingForEach_thenGetExpectedResult() { + List keyList = new ArrayList<>(); + List valueList = new ArrayList<>(); + DEV_MAP.forEach((k, v) -> { + keyList.add(k); + valueList.add(v); + }); + + assertKeyAndValueList(keyList, valueList); + } + + private void assertKeyAndValueList(List keyList, List valueList) { + assertThat(keyList).containsExactlyInAnyOrder("Kent", "Eric", "Kevin", "Michal", "Saajan"); + assertThat(valueList).containsExactlyInAnyOrder("Linux", "MacOS", "Windows", "MacOS", "Linux"); + for (int i = 0; i < keyList.size(); i++) { + assertThat(DEV_MAP).containsEntry(keyList.get(i), valueList.get(i)); + } + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps-6/README.md b/core-java-modules/core-java-collections-maps-6/README.md index 7bd1d5ea11..d4f432bdcb 100644 --- a/core-java-modules/core-java-collections-maps-6/README.md +++ b/core-java-modules/core-java-collections-maps-6/README.md @@ -5,3 +5,7 @@ - [Converting Object To Map in Java](https://www.baeldung.com/java-convert-object-to-map) - [Difference Between Map.clear() and Instantiating a New Map](https://www.baeldung.com/java-map-clear-vs-new-map) - [Converting JsonNode Object to Map](https://www.baeldung.com/jackson-jsonnode-map) +- [How to Modify a Key in a HashMap?](https://www.baeldung.com/java-hashmap-modify-key) +- [Converting String or String Array to Map in Java](https://www.baeldung.com/java-convert-string-to-map) +- [Remove Duplicate Values From HashMap in Java](https://www.baeldung.com/java-hashmap-delete-duplicates) +- [Sorting Java Map in Descending Order](https://www.baeldung.com/java-sort-map-descending) diff --git a/core-java-modules/core-java-collections-maps-6/src/test/java/com/baeldung/map/removeduplicate/RemoveDuplicateValuesUnitTest.java b/core-java-modules/core-java-collections-maps-6/src/test/java/com/baeldung/map/removeduplicate/RemoveDuplicateValuesUnitTest.java new file mode 100644 index 0000000000..080bc46289 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-6/src/test/java/com/baeldung/map/removeduplicate/RemoveDuplicateValuesUnitTest.java @@ -0,0 +1,83 @@ +package com.baeldung.map.removeuplicate; + +import static java.util.stream.Collectors.toMap; +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.HashMap; +import java.util.Map; + +import org.junit.jupiter.api.Test; + +import com.google.common.collect.ImmutableMap; + +public class RemoveDuplicateValuesUnitTest { + private Map initDevMap() { + Map devMap = new HashMap<>(); + devMap.put("Tom", "Linux"); + devMap.put("Kent", "Linux"); + + devMap.put("Bob", "MacOS"); + devMap.put("Eric", "MacOS"); + + devMap.put("Peter", "Windows"); + devMap.put("Saajan", "Windows"); + devMap.put("Jan", "Windows"); + + devMap.put("Kevin", "FreeBSD"); + return devMap; + } + + @Test + void whenUsingReverseMap_thenDuplicateValuesAreRemoved() { + Map devMap = initDevMap(); + Map tmpReverseMap = new HashMap<>(); + Map result = new HashMap<>(); + for (String name : devMap.keySet()) { + tmpReverseMap.put(devMap.get(name), name); + } + + for (String os : tmpReverseMap.keySet()) { + result.put(tmpReverseMap.get(os), os); + } + + assertThat(result.values()).hasSize(4) + .containsExactlyInAnyOrder("Windows", "MacOS", "Linux", "FreeBSD"); + } + + @Test + void whenUsingStream_thenDuplicateValuesAreRemoved() { + Map devMap = initDevMap(); + Map result = devMap.entrySet() + .stream() + .collect(toMap(Map.Entry::getValue, Map.Entry::getKey, (keyInMap, keyNew) -> keyInMap)) + .entrySet() + .stream() + .collect(toMap(Map.Entry::getValue, Map.Entry::getKey)); + + assertThat(result.values()).hasSize(4) + .containsExactlyInAnyOrder("Windows", "MacOS", "Linux", "FreeBSD"); + } + + @Test + void whenUsingStream_thenDuplicateValuesAreRemovedAndOnlyLongestNamesExist() { + Map devMap = initDevMap(); + + //@formatter:off + Map expected = ImmutableMap.of( + "Eric", "MacOS", + "Kent", "Linux", + "Saajan", "Windows", + "Kevin", "FreeBSD"); + //@formatter:on + + Map result = devMap.entrySet() + .stream() + .collect(toMap(Map.Entry::getValue, Map.Entry::getKey, (k1, k2) -> k1.length() > k2.length() ? k1 : k2)) + .entrySet() + .stream() + .collect(toMap(Map.Entry::getValue, Map.Entry::getKey)); + + assertThat(result).hasSize(4) + .isEqualTo(expected); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-collections-maps-6/src/test/java/com/baeldung/strringtomap/StringToMapUnitTest.java b/core-java-modules/core-java-collections-maps-6/src/test/java/com/baeldung/strringtomap/StringToMapUnitTest.java new file mode 100644 index 0000000000..bab4d7dfa7 --- /dev/null +++ b/core-java-modules/core-java-collections-maps-6/src/test/java/com/baeldung/strringtomap/StringToMapUnitTest.java @@ -0,0 +1,89 @@ +package com.baeldung.stringtomap; + +import org.junit.Test; + +import java.util.*; + +import static org.junit.Assert.assertEquals; + +public class StringToMapUnitTest { + + public Map convertStringToMap(String data) { + Map map = new HashMap<>(); + StringTokenizer tokenizer = new StringTokenizer(data, " "); + + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + String[] keyValue = token.split("="); + map.put(keyValue[0], keyValue[1]); + } + + return map; + } + + @Test + public void given_StringWithKeyValuePairs_whenUsing_convertStringToMap_thenMapCreated() { + String data = "name=John age=30 city=NewYork"; + Map expectedMap = new HashMap<>(); + expectedMap.put("name", "John"); + expectedMap.put("age", "30"); + expectedMap.put("city", "NewYork"); + Map resultMap = convertStringToMap(data); + assertEquals(expectedMap, resultMap); + } + + public Map convertStringArrayToMap(String[] data) { + Map map = new HashMap<>(); + + for (String keyValue : data) { + String[] parts = keyValue.split("="); + map.put(parts[0], parts[1]); + } + + return map; + } + + @Test + public void given_StringArrayWithKeyValuePairs_whenUsing_convertStringArrayToMap_thenMapCreated() { + String[] data = {"name=John", "age=30", "city=NewYork"}; + Map expectedMap = new HashMap<>(); + expectedMap.put("name", "John"); + expectedMap.put("age", "30"); + expectedMap.put("city", "NewYork"); + Map resultMap = convertStringArrayToMap(data); + assertEquals(expectedMap, resultMap); + } + + public Map> convertStringArrayToMapWithDuplicates(String[] data) { + Map> map = new HashMap<>(); + + for (String keyValue : data) { + String[] parts = keyValue.split("="); + String key = parts[0]; + String value = parts[1]; + + if (map.containsKey(key)) { + List valuesList = map.get(key); + valuesList.add(value); + } else { + List valuesList = new ArrayList<>(); + valuesList.add(value); + map.put(key, valuesList); + } + } + + return map; + + } + + @Test + public void given_StringArrayWithKeyValuePairsWithDuplicates_whenUsing_convertStringArrayToMapWithDuplicates_thenMapCreatedWithLists() { + String[] data = {"name=John", "age=30", "city=NewYork", "age=31"}; + Map> expectedMap = new HashMap<>(); + expectedMap.put("name", Collections.singletonList("John")); + expectedMap.put("age", Arrays.asList("30", "31")); + expectedMap.put("city", Collections.singletonList("NewYork")); + Map> resultMap = convertStringArrayToMapWithDuplicates(data); + assertEquals(expectedMap, resultMap); + } +} diff --git a/core-java-modules/core-java-collections-set-2/README.md b/core-java-modules/core-java-collections-set-2/README.md index a11329365a..33f20d60af 100644 --- a/core-java-modules/core-java-collections-set-2/README.md +++ b/core-java-modules/core-java-collections-set-2/README.md @@ -3,4 +3,5 @@ - [Using Streams to Collect Into a TreeSet](https://www.baeldung.com/java-stream-collect-into-treeset) - [A Guide to LinkedHashSet in Java](https://www.baeldung.com/java-linkedhashset) - [Sorting a HashSet in Java](https://www.baeldung.com/java-sort-hashset) -- More articles: [[<-- prev]](/core-java-modules/core-java-collections-set) \ No newline at end of file +- [How to Get First Item From a Java Set](https://www.baeldung.com/first-item-set) +- More articles: [[<-- prev]](/core-java-modules/core-java-collections-set) diff --git a/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/firstitemfromset/GetFirstItemFromSetUnitTest.java b/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/firstitemfromset/GetFirstItemFromSetUnitTest.java new file mode 100644 index 0000000000..ec81c17f93 --- /dev/null +++ b/core-java-modules/core-java-collections-set-2/src/test/java/com/baeldung/firstitemfromset/GetFirstItemFromSetUnitTest.java @@ -0,0 +1,35 @@ +package com.baeldung.firstitemfromset; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Optional; +import java.util.Set; + +import org.junit.Test; + +public class GetFirstItemFromSetUnitTest { + + @Test + public void givenASet_whenUsingIterator_thenRetrieveAnItem(){ + Set set = new LinkedHashSet<>(Arrays.asList(1, 2, 3, 4, 5)); + Iterator iterator = set.iterator(); + if(iterator.hasNext()){ + int retrieved = (int) iterator.next(); + assertEquals(retrieved, 1); + } + } + + @Test + public void givenASet_whenUsingStreams_thenRetrieveAnItem(){ + Set set = new LinkedHashSet<>(Arrays.asList(1, 2, 3, 4, 5)); + Optional optional = set.stream().findFirst(); + if(optional.isPresent()){ + int retrieved = optional.get(); + assertEquals(retrieved, 1); + } + } + +} diff --git a/core-java-modules/core-java-conditionals/README.md b/core-java-modules/core-java-conditionals/README.md new file mode 100644 index 0000000000..828f3484f1 --- /dev/null +++ b/core-java-modules/core-java-conditionals/README.md @@ -0,0 +1,6 @@ +## Core Java Conditionals + +This module contains articles about Java Conditionals. + +### Relevant articles: +- [Guide to the yield Keyword in Java](https://www.baeldung.com/java-yield-switch) diff --git a/core-java-modules/core-java-conditionals/pom.xml b/core-java-modules/core-java-conditionals/pom.xml new file mode 100644 index 0000000000..2a1290c98e --- /dev/null +++ b/core-java-modules/core-java-conditionals/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + core-java-conditionals + 0.1.0-SNAPSHOT + core-java-compiler + jar + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.projectlombok + lombok + 1.18.24 + provided + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven-compiler-plugin.version} + + --enable-preview + ${maven.compiler.source.version} + ${maven.compiler.target.version} + 14 + --enable-preview + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.plugin.version} + + --enable-preview + + + + + + + 14 + 3.8.1 + 14 + 3.0.0-M3 + + + \ No newline at end of file diff --git a/core-java-modules/core-java-conditionals/src/test/java/com/baeldung/conditionals/YieldTest.java b/core-java-modules/core-java-conditionals/src/test/java/com/baeldung/conditionals/YieldTest.java new file mode 100644 index 0000000000..4ea9126cde --- /dev/null +++ b/core-java-modules/core-java-conditionals/src/test/java/com/baeldung/conditionals/YieldTest.java @@ -0,0 +1,83 @@ +package com.baeldung.conditionals; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + + +class YieldTest { + + enum Number { + ONE, TWO, THREE, FOUR + } + + @Test + void whenSwitchingOnNumberOne_thenWillReturnString() { + Number number = Number.ONE; + String message; + switch (number) { + case ONE: + message = "Got a 1"; + break; + case TWO: + message = "Got a 2"; + break; + default: + message = "More than 2"; + } + + assertEquals("Got a 1", message); + } + + @Test + void whenSwitchingWithArrowOnNumberTwo_thenWillReturnString() { + Number number = Number.TWO; + String message = switch (number) { + case ONE -> { + yield "Got a 1"; + } + case TWO -> { + yield "Got a 2"; + } + default -> { + yield "More than 2"; + } + }; + + assertEquals("Got a 2", message); + } + + @Test + void whenSwitchingWithArrowNoDefaultOnNumberTwo_thenWillReturnString() { + Number number = Number.TWO; + String message = switch (number) { + case ONE -> { + yield "Got a 1"; + } + case TWO -> { + yield "Got a 2"; + } + case THREE, FOUR -> { + yield "More than 2"; + } + }; + + assertEquals("Got a 2", message); + } + + @Test + void whenSwitchingWithColonOnNumberTwo_thenWillReturnString() { + Number number = Number.TWO; + String message = switch (number) { + case ONE: + yield "Got a 1"; + case TWO: + yield "Got a 2"; + default: + yield "More than 2"; + }; + + assertEquals("Got a 2", message); + } + +} diff --git a/core-java-modules/core-java-date-operations-3/README.md b/core-java-modules/core-java-date-operations-3/README.md index 97855814e5..e3f0cfa3dc 100644 --- a/core-java-modules/core-java-date-operations-3/README.md +++ b/core-java-modules/core-java-date-operations-3/README.md @@ -9,4 +9,5 @@ This module contains articles about date operations in Java. - [Adding One Month to Current Date in Java](https://www.baeldung.com/java-adding-one-month-to-current-date) - [How to Get Last Day of a Month in Java](https://www.baeldung.com/java-last-day-month) - [Getting Yesterday’s Date in Java](https://www.baeldung.com/java-find-yesterdays-date) +- [How to Get the Start and End Dates of a Year Using Java](https://www.baeldung.com/java-date-year-start-end) - [[<-- Prev]](/core-java-modules/core-java-date-operations-2) diff --git a/core-java-modules/core-java-datetime-conversion/README.md b/core-java-modules/core-java-datetime-conversion/README.md index 11e4348838..98c2d6694b 100644 --- a/core-java-modules/core-java-datetime-conversion/README.md +++ b/core-java-modules/core-java-datetime-conversion/README.md @@ -8,3 +8,4 @@ This module contains articles about converting between Java date and time object - [Convert Date to LocalDate or LocalDateTime and Back](http://www.baeldung.com/java-date-to-localdate-and-localdatetime) - [Convert Between java.time.Instant and java.sql.Timestamp](https://www.baeldung.com/java-time-instant-to-java-sql-timestamp) - [Convert Between LocalDateTime and ZonedDateTime](https://www.baeldung.com/java-localdatetime-zoneddatetime) +- [Conversion From 12-Hour Time to 24-Hour Time in Java](https://www.baeldung.com/java-convert-time-format) diff --git a/core-java-modules/core-java-datetime-conversion/src/main/java/com/baeldung/epochtolocaldate/EpochTimeToLocalDateConverter.java b/core-java-modules/core-java-datetime-conversion/src/main/java/com/baeldung/epochtolocaldate/EpochTimeToLocalDateConverter.java new file mode 100644 index 0000000000..8dd7c8d602 --- /dev/null +++ b/core-java-modules/core-java-datetime-conversion/src/main/java/com/baeldung/epochtolocaldate/EpochTimeToLocalDateConverter.java @@ -0,0 +1,29 @@ +package com.baeldung.epochtolocaldate; + +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; + +/** + * Class which shows a way to convert Epoch time in milliseconds to java.time.LocalDate. + * + * @author quincy + * + */ + +public class EpochTimeToLocalDateConverter { + public static String main(String[] args) { + long epochTimeinMillisToConvert = 1624962431000L; + + Instant instant = Instant.ofEpochMilli(epochTimeinMillisToConvert); + + ZoneId zoneId = ZoneId.systemDefault(); // Use the system default time zone + LocalDate localDate = instant.atZone(zoneId).toLocalDate(); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + String formattedDate = localDate.format(formatter); + + return formattedDate; + } +} diff --git a/core-java-modules/core-java-datetime-conversion/src/main/java/com/baeldung/epochtolocaldate/EpochTimeToLocalDateTimeConverter.java b/core-java-modules/core-java-datetime-conversion/src/main/java/com/baeldung/epochtolocaldate/EpochTimeToLocalDateTimeConverter.java new file mode 100644 index 0000000000..ffac6e50e9 --- /dev/null +++ b/core-java-modules/core-java-datetime-conversion/src/main/java/com/baeldung/epochtolocaldate/EpochTimeToLocalDateTimeConverter.java @@ -0,0 +1,29 @@ +package com.baeldung.epochtolocaldate; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; + +/** + * Class which shows a way to convert Epoch time in milliseconds to java.time.LocalDateTime. + * + * @author quincy + * + */ + +public class EpochTimeToLocalDateTimeConverter { + public static String main(String[] args) { + long epochTimeinMillisToConvert = 1624962431000L; + + Instant instant = Instant.ofEpochMilli(epochTimeinMillisToConvert); + + ZoneId zoneId = ZoneId.systemDefault(); // Use the system default time zone + LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime(); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + String formattedDate = localDateTime.format(formatter); + + return formattedDate; + } +} diff --git a/core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/epochtolocaldate/EpochTimeToLocalDateConverterUnitTest.java b/core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/epochtolocaldate/EpochTimeToLocalDateConverterUnitTest.java new file mode 100644 index 0000000000..9b8135de51 --- /dev/null +++ b/core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/epochtolocaldate/EpochTimeToLocalDateConverterUnitTest.java @@ -0,0 +1,21 @@ +package com.baeldung.epochtolocaldate; + +import org.junit.jupiter.api.Test; +import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class EpochTimeToLocalDateConverterUnitTest { + @Test + public void testConvertEpochTimeToLocalDate() { + long epochTimeMillis = 1624962431000L; // Example epoch time in millisecond + LocalDate expectedDate = LocalDate.of(2021, 6, 29); + + Instant instant = Instant.ofEpochMilli(epochTimeMillis); + ZoneId zoneId = ZoneId.systemDefault(); + LocalDate actualDate = instant.atZone(zoneId).toLocalDate(); + + assertEquals(expectedDate, actualDate); + } +} diff --git a/core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/epochtolocaldate/EpochTimeToLocalDateTimeConverterUnitTest.java b/core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/epochtolocaldate/EpochTimeToLocalDateTimeConverterUnitTest.java new file mode 100644 index 0000000000..6e3b250938 --- /dev/null +++ b/core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/epochtolocaldate/EpochTimeToLocalDateTimeConverterUnitTest.java @@ -0,0 +1,24 @@ +package com.baeldung.epochtolocaldate; + +import org.junit.jupiter.api.Test; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class EpochTimeToLocalDateTimeConverterUnitTest { + + @Test + public void testConvertEpochTimeToLocalDateTime() { + long epochTimeMillis = 1624962431000L; // Example epoch time in milliseconds + LocalDateTime expectedDateTime = LocalDateTime.of(2021, 6, 29, 12, 13, 51); + + Instant instant = Instant.ofEpochMilli(epochTimeMillis); + ZoneId zoneId = ZoneId.systemDefault(); + LocalDateTime actualDateTime = instant.atZone(zoneId).toLocalDateTime(); + + assertEquals(expectedDateTime, actualDateTime); + } + +} diff --git a/core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/twelvehourstotwentyhours/TimeConversionUnitTest.java b/core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/twelvehourstotwentyhours/TimeConversionUnitTest.java new file mode 100644 index 0000000000..e82af6dd19 --- /dev/null +++ b/core-java-modules/core-java-datetime-conversion/src/test/java/com/baeldung/twelvehourstotwentyhours/TimeConversionUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.twelvehourstotwentyhours; + +import static org.junit.jupiter.api.Assertions.*; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.Locale; +import org.junit.jupiter.api.Test; + +public class TimeConversionUnitTest { + + @Test + public void givenTimeInTwelveHours_whenConvertingToTwentyHours_thenConverted() throws ParseException { + SimpleDateFormat displayFormat = new SimpleDateFormat("HH:mm"); + SimpleDateFormat parseFormat = new SimpleDateFormat("hh:mm a"); + Date date = parseFormat.parse("06:00 PM"); + assertEquals("18:00", displayFormat.format(date)); + } + + @Test + public void givenTimeInTwelveHours_whenConvertingToTwentyHoursWithDateTimeFormatter_thenConverted() throws ParseException { + String time = LocalTime.parse("06:00 PM", DateTimeFormatter.ofPattern("hh:mm a", Locale.US)) + .format(DateTimeFormatter.ofPattern("HH:mm")); + assertEquals("18:00", time); + } + +} diff --git a/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/socketexception/SslServer.java b/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/socketexception/SslServer.java new file mode 100644 index 0000000000..ae783fa8bd --- /dev/null +++ b/core-java-modules/core-java-exceptions-2/src/main/java/com/baeldung/socketexception/SslServer.java @@ -0,0 +1,32 @@ +package com.baeldung.socketexception; + +import java.io.IOException; + +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; + +public class SslServer { + + public static void createSSLSocketWithEnabledProtocols(SSLServerSocketFactory socketFactory, int port, String[] enabledProtocols) { + SSLServerSocket serverSocket = null; + + try { + serverSocket = (SSLServerSocket) socketFactory.createServerSocket(port); + // Set the enabled protocols + serverSocket.setEnabledProtocols(enabledProtocols); + System.out.println("Server is running on port " + port); + + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (serverSocket != null) { + try { + serverSocket.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + +} diff --git a/core-java-modules/core-java-exceptions-2/src/test/java/com/baeldung/socketexception/SocketExceptionHandlingUnitTest.java b/core-java-modules/core-java-exceptions-2/src/test/java/com/baeldung/socketexception/SocketExceptionHandlingUnitTest.java index 08b21c6299..197046d273 100644 --- a/core-java-modules/core-java-exceptions-2/src/test/java/com/baeldung/socketexception/SocketExceptionHandlingUnitTest.java +++ b/core-java-modules/core-java-exceptions-2/src/test/java/com/baeldung/socketexception/SocketExceptionHandlingUnitTest.java @@ -1,25 +1,33 @@ package com.baeldung.socketexception; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + import java.io.IOException; import java.net.SocketException; import java.util.concurrent.Executors; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; + import org.junit.BeforeClass; import org.junit.Test; public class SocketExceptionHandlingUnitTest { + private static final int PORT = 6699; @BeforeClass public static void runServer() throws IOException, InterruptedException { Executors.newSingleThreadExecutor() - .submit(() -> new SocketServer().start(6699)); + .submit(() -> new SocketServer().start(PORT)); Thread.sleep(100); } @Test public void givenRunningServer_whenConnectToClosedSocket_thenHandleException() throws IOException { SocketClient client = new SocketClient(); - client.startConnection("127.0.0.1", 6699); + client.startConnection("127.0.0.1", PORT); try { client.sendMessage("hi"); client.sendMessage("hi again"); @@ -28,4 +36,22 @@ public class SocketExceptionHandlingUnitTest { } } + @Test + public void givenRunningServer_whenConnectToSocket_thenHandleConnectionResetException() throws IOException { + // Enable multiple SSL/TLS protocols + String[] enabledProtocols = { "TLSv1.2", "TLSv1.3", "TLSv1.1", "TLSv1", "SSLv3", "SSLv3" }; + SSLServerSocketFactory mockFactory = mock(SSLServerSocketFactory.class); + SSLServerSocket mockServerSocket = mock(SSLServerSocket.class); + + // Set up the mock factory to return the mock server socket + when(mockFactory.createServerSocket(PORT)).thenReturn(mockServerSocket); + + // Call the method being tested + SslServer.createSSLSocketWithEnabledProtocols(mockFactory, PORT, enabledProtocols); + + // Verify that setEnabledProtocols and close were called + verify(mockServerSocket).setEnabledProtocols(enabledProtocols); + verify(mockServerSocket).close(); + } + } diff --git a/core-java-modules/core-java-io-apis-2/README.md b/core-java-modules/core-java-io-apis-2/README.md index e86539c750..cc3c351afc 100644 --- a/core-java-modules/core-java-io-apis-2/README.md +++ b/core-java-modules/core-java-io-apis-2/README.md @@ -5,4 +5,5 @@ This module contains articles about core Java input/output(IO) APIs. ### Relevant Articles: - [Constructing a Relative Path From Two Absolute Paths in Java](https://www.baeldung.com/java-relative-path-absolute) - [Get the Desktop Path in Java](https://www.baeldung.com/java-desktop-path) -- [Check if a File Is Empty in Java](https://www.baeldung.com/java-check-file-empty) \ No newline at end of file +- [Check if a File Is Empty in Java](https://www.baeldung.com/java-check-file-empty) +- [Converting Relative to Absolute Paths in Java](https://www.baeldung.com/java-from-relative-to-absolute-paths) diff --git a/core-java-modules/core-java-20/src/main/java/com/baeldung/convertpaths/RelativePathConverter.java b/core-java-modules/core-java-io-apis-2/src/main/java/com/baeldung/convertpaths/RelativePathConverter.java similarity index 100% rename from core-java-modules/core-java-20/src/main/java/com/baeldung/convertpaths/RelativePathConverter.java rename to core-java-modules/core-java-io-apis-2/src/main/java/com/baeldung/convertpaths/RelativePathConverter.java diff --git a/core-java-modules/core-java-20/src/test/java/com/baeldung/convertpaths/RelativePathConverterUnitTest.java b/core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/convertpaths/RelativePathConverterUnitTest.java similarity index 100% rename from core-java-modules/core-java-20/src/test/java/com/baeldung/convertpaths/RelativePathConverterUnitTest.java rename to core-java-modules/core-java-io-apis-2/src/test/java/com/baeldung/convertpaths/RelativePathConverterUnitTest.java diff --git a/core-java-modules/core-java-io-apis/src/main/java/com/baeldung/outputtofile/DualPrintStream.java b/core-java-modules/core-java-io-apis/src/main/java/com/baeldung/outputtofile/DualPrintStream.java new file mode 100644 index 0000000000..17e057aba9 --- /dev/null +++ b/core-java-modules/core-java-io-apis/src/main/java/com/baeldung/outputtofile/DualPrintStream.java @@ -0,0 +1,49 @@ +package com.baeldung.outputtofile; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; + +class DualPrintStream extends PrintStream { + private final PrintStream second; + + public DualPrintStream(OutputStream main, PrintStream second) { + super(main); + this.second = second; + } + + @Override + public void close() { + super.close(); + second.close(); + } + + @Override + public void flush() { + super.flush(); + second.flush(); + } + + @Override + public void write(byte[] buf, int off, int len) { + super.write(buf, off, len); + second.write(buf, off, len); + } + + @Override + public void write(int b) { + super.write(b); + second.write(b); + } + + @Override + public void write(byte[] b) throws IOException { + super.write(b); + second.write(b); + } + + @Override + public boolean checkError() { + return super.checkError() && second.checkError(); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-io-apis/src/test/java/com/baeldung/outputtofile/ConsoleOutputToFileUnitTest.java b/core-java-modules/core-java-io-apis/src/test/java/com/baeldung/outputtofile/ConsoleOutputToFileUnitTest.java index c7f643b148..24157d4efa 100644 --- a/core-java-modules/core-java-io-apis/src/test/java/com/baeldung/outputtofile/ConsoleOutputToFileUnitTest.java +++ b/core-java-modules/core-java-io-apis/src/test/java/com/baeldung/outputtofile/ConsoleOutputToFileUnitTest.java @@ -4,7 +4,6 @@ import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; -import java.io.OutputStream; import java.io.PrintStream; import java.nio.file.Files; import java.nio.file.Path; @@ -15,45 +14,6 @@ import org.junit.jupiter.api.io.TempDir; import com.google.common.collect.Lists; -class DualPrintStream extends PrintStream { - private final PrintStream second; - - public DualPrintStream(OutputStream main, PrintStream second) { - super(main); - this.second = second; - } - - @Override - public void close() { - super.close(); - second.close(); - } - - @Override - public void flush() { - super.flush(); - second.flush(); - } - - @Override - public void write(byte[] buf, int off, int len) { - super.write(buf, off, len); - second.write(buf, off, len); - } - - @Override - public void write(int b) { - super.write(b); - second.write(b); - } - - @Override - public void write(byte[] b) throws IOException { - super.write(b); - second.write(b); - } -} - public class ConsoleOutputToFileUnitTest { // @formatter:off diff --git a/core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/JarAppUnitTest.java b/core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/JarAppUnitTest.java index 707ce79624..fc40aa01c5 100644 --- a/core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/JarAppUnitTest.java +++ b/core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/JarAppUnitTest.java @@ -3,10 +3,14 @@ package com.baeldung.jar; import org.junit.Assert; import org.junit.jupiter.api.Test; +import java.util.regex.Pattern; + public class JarAppUnitTest { @Test public void findClassTest(){ - Assert.assertTrue(JarApp.findObjectMapperClass().endsWith("jackson-databind-2.13.3.jar")); + Pattern databindPattern = Pattern.compile(".*jackson-databind-(\\d)+\\.(\\d)+\\.(\\d)\\.jar$"); + + Assert.assertTrue(databindPattern.matcher(JarApp.findObjectMapperClass()).matches()); } } diff --git a/core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/MySampleGUIAppnUnitTest.java b/core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/MySampleGUIAppManualTest.java similarity index 69% rename from core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/MySampleGUIAppnUnitTest.java rename to core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/MySampleGUIAppManualTest.java index 106531008c..240c5be58d 100644 --- a/core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/MySampleGUIAppnUnitTest.java +++ b/core-java-modules/core-java-jar/src/test/java/com/baeldung/jar/MySampleGUIAppManualTest.java @@ -1,15 +1,15 @@ package com.baeldung.jar; -import java.io.IOException; - import org.junit.jupiter.api.Test; -class MySampleGUIAppnUnitTest { +class MySampleGUIAppManualTest { + @Test - void testMain() throws IOException { + void testMain() { System.setProperty("java.awt.headless", "true"); String [] args = null; System.exit(0); MySampleGUIAppn.main(args); } + } \ No newline at end of file diff --git a/core-java-modules/core-java-lang-6/src/main/java/com/baeldung/randominset/RandomInSetUtil.java b/core-java-modules/core-java-lang-6/src/main/java/com/baeldung/randominset/RandomInSetUtil.java new file mode 100644 index 0000000000..5b203db515 --- /dev/null +++ b/core-java-modules/core-java-lang-6/src/main/java/com/baeldung/randominset/RandomInSetUtil.java @@ -0,0 +1,50 @@ +package com.baeldung.randominset; + +import java.util.HashSet; +import java.util.Random; +import java.util.Set; +import java.util.concurrent.ThreadLocalRandom; + +public class RandomInSetUtil { + + public static T getByRandomClass(Set set) { + if (set == null || set.isEmpty()) { + throw new IllegalArgumentException("The Set cannot be empty."); + } + int randomIndex = new Random().nextInt(set.size()); + int i = 0; + for (T element : set) { + if (i == randomIndex) { + return element; + } + i++; + } + throw new IllegalStateException("Something went wrong while picking a random element."); + } + + public static T getByThreadLocalRandom(Set set) { + if (set == null || set.isEmpty()) { + throw new IllegalArgumentException("The Set cannot be empty."); + } + int randomIndex = ThreadLocalRandom.current().nextInt(set.size()); + int i = 0; + for (T element : set) { + if (i == randomIndex) { + return element; + } + i++; + } + throw new IllegalStateException("Something went wrong while picking a random element."); + } + + public static void main(String[] args) { + Set animals = new HashSet<>(); + animals.add("Lion"); + animals.add("Elephant"); + animals.add("Giraffe"); + + String randomAnimal = getByThreadLocalRandom(animals); + System.out.println("Randomly picked animal: " + randomAnimal); + } + +} diff --git a/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/GenerationUnitTest.java b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/GenerationUnitTest.java new file mode 100644 index 0000000000..f02200462e --- /dev/null +++ b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/GenerationUnitTest.java @@ -0,0 +1,45 @@ +package com.baeldung.magicsquare; + +import org.junit.jupiter.api.Test; + +public class GenerationUnitTest { + @Test + public void testGenerate3x3() { + MagicSquare magicSquare = new MagicSquare(3); + System.out.println(magicSquare); + + magicSquare.validate(); + } + + @Test + public void testGenerate9x9() { + MagicSquare magicSquare = new MagicSquare(9); + System.out.println(magicSquare); + + magicSquare.validate(); + } + + @Test + public void testGenerate12x12() { + MagicSquare magicSquare = new MagicSquare(12); + System.out.println(magicSquare); + + magicSquare.validate(); + } + + @Test + public void testGenerate10x10() { + MagicSquare magicSquare = new MagicSquare(10); + System.out.println(magicSquare); + + magicSquare.validate(); + } + + @Test + public void testGenerate18x18() { + MagicSquare magicSquare = new MagicSquare(18); + System.out.println(magicSquare); + + magicSquare.validate(); + } +} diff --git a/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/MagicSquare.java b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/MagicSquare.java new file mode 100644 index 0000000000..b6e7ac24f5 --- /dev/null +++ b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/MagicSquare.java @@ -0,0 +1,188 @@ +package com.baeldung.magicsquare; + +import org.junit.platform.commons.util.StringUtils; + +import java.util.stream.IntStream; + +public class MagicSquare { + private int[][] cells; + + public MagicSquare(int n) { + this.cells = new int[n][]; + + for (int i = 0; i < n; ++i) { + this.cells[i] = new int[n]; + } + + if (n % 2 == 1) { + populateOdd(); + } else if (n % 4 == 0) { + populateDoubleEven(); + } else if (n >= 6) { + populateSingleEven(); + } + } + + private void populateOdd() { + int n = getN(); + + populateOddArea(0, 0, n, 0); + } + + private void populateOddArea(int xOffset, int yOffset, int n, int numberOffset) { + int y = 0; + int x = (n - 1) / 2; + setCell(xOffset + x, yOffset + y, numberOffset + 1); + + for (int number = 2; number <= n * n; ++number) { + int nextX = x + 1; + if (nextX == n) { + nextX = 0; + } + + int nextY = y - 1; + if (nextY == -1) { + nextY = n - 1; + } + + if (getCell(xOffset + nextX, yOffset + nextY) != 0) { + nextX = x; + + nextY = y + 1; + if (nextY == n) { + nextY = 0; + } + } + + setCell(xOffset + nextX, yOffset + nextY, numberOffset + number); + + x = nextX; + y = nextY; + } + } + + private void populateDoubleEven() { + int n = getN(); + int number = 1; + + for (int y = 0; y < n; ++y) { + for (int x = 0; x < n; ++x) { + boolean highlighted = false; + + if ((y < n/4 || y >= 3*n/4) && (x >= n/4 && x < 3*n/4)) { + highlighted = true; + } else if ((x < n/4 || x >= 3*n/4) && (y >= n/4 && y < 3*n/4)) { + highlighted = true; + } + + if (highlighted) { + setCell(x, y, (n * n) - number + 1); + } else { + setCell(x, y, number); + } + + number += 1; + } + } + } + + private void populateSingleEven() { + int n = getN(); + int halfN = n/2; + int swapSize = (int) n/4; + + populateOddArea(0, 0, halfN, 0); + populateOddArea(halfN, halfN, halfN, halfN * halfN); + populateOddArea(halfN, 0, halfN, (halfN * halfN) * 2); + populateOddArea(0, halfN, halfN, (halfN * halfN) * 3); + + for (int x = 0; x < swapSize; ++x) { + swapCells(x, 0, x, halfN); + swapCells(x, halfN - 1, x, n - 1); + + for (int y = 1; y < halfN - 1; ++y) { + swapCells(x + 1, y, x + 1, y + halfN); + } + } + + for (int x = 0; x < swapSize - 1; ++x) { + for (int y = 0; y < halfN; ++y) { + swapCells(n - x - 1, y, n - x - 1, y + halfN); + } + } + + } + + private void swapCells(int x1, int y1, int x2, int y2) { + int cell1 = getCell(x1, y1); + int cell2 = getCell(x2, y2); + + setCell(x1, y1, cell2); + setCell(x2, y2, cell1); + } + + public int getN() { + return cells.length; + } + + public int getCell(int x, int y) { + return cells[x][y]; + } + + public void setCell(int x, int y, int value) { + cells[x][y] = value; + } + + public void validate() { + int n = getN(); + int expectedValue = ((n * n * n) + n) / 2; + + // Diagonals + if (IntStream.range(0, n).map(i -> getCell(i, i)).sum() != expectedValue) { + throw new IllegalStateException("Leading diagonal is not the expected value"); + } + if (IntStream.range(0, n).map(i -> getCell(i, n - i - 1)).sum() != expectedValue) { + throw new IllegalStateException("Trailing diagonal is not the expected value"); + } + + // Rows + IntStream.range(0, n).forEach(y -> { + if (IntStream.range(0, n).map(x -> getCell(x, y)).sum() != expectedValue) { + throw new IllegalStateException("Row is not the expected value"); + } + }); + + // Cols + IntStream.range(0, n).forEach(x -> { + if (IntStream.range(0, n).map(y -> getCell(x, y)).sum() != expectedValue) { + throw new IllegalStateException("Column is not the expected value"); + } + }); + } + + public String toString() { + int n = getN(); + int largestNumberLength = Integer.toString(n * n).length(); + String formatString = " %0" + largestNumberLength + "d "; + + StringBuilder sb = new StringBuilder(); + + for (int y = 0; y < n; ++y) { + for (int x = 0; x < n; ++x) { + int value = getCell(x, y); + if (value == 0) { + sb.append(" "); + for (int i = 0; i < largestNumberLength; ++i) { + sb.append("."); + } + sb.append(" "); + } else { + sb.append(String.format(formatString, value)); + } + } + sb.append("\n"); + } + + return sb.toString(); + } +} diff --git a/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/README.md b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/README.md new file mode 100644 index 0000000000..b2f7ece88a --- /dev/null +++ b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/README.md @@ -0,0 +1,2 @@ +## Relevant Articles +- [Creating a Magic Square in Java](https://www.baeldung.com/java-magic-square) diff --git a/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/ValidationUnitTest.java b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/ValidationUnitTest.java new file mode 100644 index 0000000000..6b0ec600bb --- /dev/null +++ b/core-java-modules/core-java-lang-math-3/src/test/java/com/baeldung/magicsquare/ValidationUnitTest.java @@ -0,0 +1,21 @@ +package com.baeldung.magicsquare; + +import org.junit.jupiter.api.Test; + +public class ValidationUnitTest { + @Test + public void testValidate3x3() { + MagicSquare magicSquare = new MagicSquare(3); + magicSquare.setCell(0, 0, 8); + magicSquare.setCell(1, 0, 1); + magicSquare.setCell(2, 0, 6); + magicSquare.setCell(0, 1, 3); + magicSquare.setCell(1, 1, 5); + magicSquare.setCell(2, 1, 7); + magicSquare.setCell(0, 2, 4); + magicSquare.setCell(1, 2, 9); + magicSquare.setCell(2, 2, 2); + + magicSquare.validate(); + } +} diff --git a/core-java-modules/core-java-lang-oop-generics/README.md b/core-java-modules/core-java-lang-oop-generics/README.md index 720ba9dcfd..3e33ba5315 100644 --- a/core-java-modules/core-java-lang-oop-generics/README.md +++ b/core-java-modules/core-java-lang-oop-generics/README.md @@ -9,3 +9,4 @@ This module contains articles about generics in Java - [Super Type Tokens in Java Generics](https://www.baeldung.com/java-super-type-tokens) - [Java Warning “unchecked conversion”](https://www.baeldung.com/java-unchecked-conversion) - [Java Warning “Unchecked Cast”](https://www.baeldung.com/java-warning-unchecked-cast) +- [What Does the Holder Class Do in Java?](https://www.baeldung.com/java-holder-class) diff --git a/core-java-modules/core-java-lang-oop-generics/src/main/java/com/baeldung/holder/Holder.java b/core-java-modules/core-java-lang-oop-generics/src/main/java/com/baeldung/holder/Holder.java new file mode 100644 index 0000000000..da066ee5c6 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-generics/src/main/java/com/baeldung/holder/Holder.java @@ -0,0 +1,9 @@ +package com.baeldung.holder; + +public class Holder { + public T value; + + public Holder(T value) { + this.value = value; + } +} diff --git a/core-java-modules/core-java-lang-oop-generics/src/main/java/com/baeldung/holder/SupplierService.java b/core-java-modules/core-java-lang-oop-generics/src/main/java/com/baeldung/holder/SupplierService.java new file mode 100644 index 0000000000..473a4de423 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-generics/src/main/java/com/baeldung/holder/SupplierService.java @@ -0,0 +1,13 @@ +package com.baeldung.holder; + +public class SupplierService { + public void getSupplierByZipCode(String zip, Holder resultHolder) { + // Let's pretend we did some work here to get the supplier + // And let's say all zip codes starting with "9" are valid, just for this example + if (zip.startsWith("9")) { + resultHolder.value = true; + } else { + resultHolder.value = false; + } + } +} diff --git a/core-java-modules/core-java-lang-oop-generics/src/test/java/com/baeldung/holder/SupplierServiceUnitTest.java b/core-java-modules/core-java-lang-oop-generics/src/test/java/com/baeldung/holder/SupplierServiceUnitTest.java new file mode 100644 index 0000000000..e1446fc229 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-generics/src/test/java/com/baeldung/holder/SupplierServiceUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.holder; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +public class SupplierServiceUnitTest { + + @Test + public void givenValidZipCode_whenGetSupplierByZipCode_thenTrue() { + SupplierService service = new SupplierService(); + Holder resultHolder = new Holder<>(false); + String zipCode = "98682"; + + service.getSupplierByZipCode(zipCode, resultHolder); + + assertTrue(resultHolder.value); + } + + @Test + public void givenInvalidZipCode_whenGetSupplierByZipCode_thenFalse() { + SupplierService service = new SupplierService(); + Holder resultHolder = new Holder<>(true); + String zipCode = "12345"; + + service.getSupplierByZipCode(zipCode, resultHolder); + + assertFalse(resultHolder.value); + } +} diff --git a/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/EmailNotifier.java b/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/EmailNotifier.java new file mode 100644 index 0000000000..9f3e140926 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/EmailNotifier.java @@ -0,0 +1,22 @@ +package com.baeldung.subclassinnerclass; + +public class EmailNotifier extends Notifier { + @Override + void notify(Message e) { + // connect to the email connector + EmailConnector emailConnector = new EmailConnector(); + emailConnector.connect(); + // send email + } + + // Inner class for email connection + static class EmailConnector { + private String emailHost; + private int emailPort; + // Getter Setters + + private void connect() { + // connect to the smtp server + } + } +} diff --git a/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/Message.java b/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/Message.java new file mode 100644 index 0000000000..35d751b288 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/Message.java @@ -0,0 +1,6 @@ +package com.baeldung.subclassinnerclass; + +public class Message { + private int message; + // getter setter and other atteibutes +} diff --git a/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/NotificationService.java b/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/NotificationService.java new file mode 100644 index 0000000000..2ebbbde961 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/NotificationService.java @@ -0,0 +1,17 @@ +package com.baeldung.subclassinnerclass; + +public class NotificationService { + void notifyMessages() { + // Sending a Text Message + Message textMessage = new Message(); + Notifier textNotifier = new TextMessageNotifier(); + + textNotifier.notify(textMessage); + + // Sending an Email Message + Message emailMessage = new Message(); + Notifier emailNotifier = new EmailNotifier(); + + emailNotifier.notify(emailMessage); + } +} diff --git a/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/Notifier.java b/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/Notifier.java new file mode 100644 index 0000000000..aff0372af3 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/Notifier.java @@ -0,0 +1,5 @@ +package com.baeldung.subclassinnerclass; + +public abstract class Notifier { + abstract void notify(Message e); +} diff --git a/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/TextMessageNotifier.java b/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/TextMessageNotifier.java new file mode 100644 index 0000000000..8b64b4331d --- /dev/null +++ b/core-java-modules/core-java-lang-oop-inheritance/src/main/java/com/baeldung/subclassinnerclass/TextMessageNotifier.java @@ -0,0 +1,14 @@ +package com.baeldung.subclassinnerclass; + +public class TextMessageNotifier extends Notifier { + @Override + void notify(Message e) { + // Provide text message specific implementation here + } + + // Inner class for text message connection + private static class SMSConnector { + private String smsHost; + // Getter Setters + } +} diff --git a/core-java-modules/core-java-lang-oop-inheritance/src/test/java/com/baeldung/subclassinnerclass/InnerClassUnitTest.java b/core-java-modules/core-java-lang-oop-inheritance/src/test/java/com/baeldung/subclassinnerclass/InnerClassUnitTest.java new file mode 100644 index 0000000000..27577a546f --- /dev/null +++ b/core-java-modules/core-java-lang-oop-inheritance/src/test/java/com/baeldung/subclassinnerclass/InnerClassUnitTest.java @@ -0,0 +1,16 @@ +package com.baeldung.subclassinnerclass; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import org.junit.Test; + +public class InnerClassUnitTest { + @Test + public void givenInnerStaticClassWhenInstantiatedThenOuterClassIsInstantiated() { + Notifier emailNotifier = new EmailNotifier(); + EmailNotifier.EmailConnector emailConnector = new EmailNotifier.EmailConnector(); + + assertThat(emailNotifier).hasSameClassAs(new EmailNotifier()); + assertThat(emailConnector).isInstanceOf(EmailNotifier.EmailConnector.class); + } +} diff --git a/core-java-modules/core-java-lang-oop-inheritance/src/test/java/com/baeldung/subclassinnerclass/SubClassUnitTest.java b/core-java-modules/core-java-lang-oop-inheritance/src/test/java/com/baeldung/subclassinnerclass/SubClassUnitTest.java new file mode 100644 index 0000000000..25e6f5b8a4 --- /dev/null +++ b/core-java-modules/core-java-lang-oop-inheritance/src/test/java/com/baeldung/subclassinnerclass/SubClassUnitTest.java @@ -0,0 +1,18 @@ +package com.baeldung.subclassinnerclass; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +import org.junit.Test; + +public class SubClassUnitTest { + @Test + public void givenSubclassWhenInstantiatedThenSubclassObjectIsPossible() { + Notifier emailNotifier = new EmailNotifier(); + assertThat(emailNotifier).hasSameClassAs(new EmailNotifier()); + assertThat(emailNotifier).isExactlyInstanceOf(EmailNotifier.class); + + Notifier textMessageNotifier = new TextMessageNotifier(); + assertThat(textMessageNotifier).isInstanceOf(Notifier.class); + assertThat(textMessageNotifier).isExactlyInstanceOf(TextMessageNotifier.class); + } +} diff --git a/core-java-modules/core-java-lang-oop-others/README.md b/core-java-modules/core-java-lang-oop-others/README.md index b482669508..09c1dadb8b 100644 --- a/core-java-modules/core-java-lang-oop-others/README.md +++ b/core-java-modules/core-java-lang-oop-others/README.md @@ -7,3 +7,4 @@ This module contains articles about Object Oriented Programming (OOP) in Java - [Static and Dynamic Binding in Java](https://www.baeldung.com/java-static-dynamic-binding) - [Pass-By-Value as a Parameter Passing Mechanism in Java](https://www.baeldung.com/java-pass-by-value-or-pass-by-reference) - [Check If All the Variables of an Object Are Null](https://www.baeldung.com/java-check-all-variables-object-null) +- [Law of Demeter in Java](https://www.baeldung.com/java-demeter-law) diff --git a/core-java-modules/core-java-lang-oop-patterns/README.md b/core-java-modules/core-java-lang-oop-patterns/README.md index ba18c57ab0..4e171483e6 100644 --- a/core-java-modules/core-java-lang-oop-patterns/README.md +++ b/core-java-modules/core-java-lang-oop-patterns/README.md @@ -10,3 +10,4 @@ This module contains articles about Object-oriented programming (OOP) patterns i - [Using an Interface vs. Abstract Class in Java](https://www.baeldung.com/java-interface-vs-abstract-class) - [Should We Create an Interface for Only One Implementation?](https://www.baeldung.com/java-interface-single-implementation) - [How to Deep Copy an ArrayList in Java](https://www.baeldung.com/java-arraylist-deep-copy) +- [Stateless Object in Java](https://www.baeldung.com/java-stateless-object) diff --git a/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/deepcopyarraylist/Course.java b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/deepcopyarraylist/Course.java index f8367cfd50..75edca087f 100644 --- a/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/deepcopyarraylist/Course.java +++ b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/deepcopyarraylist/Course.java @@ -1,6 +1,7 @@ package com.baeldung.deepcopyarraylist; import java.io.Serializable; +import java.util.Objects; public class Course implements Serializable, Cloneable { @@ -39,4 +40,23 @@ public class Course implements Serializable, Cloneable { throw new IllegalStateException(e); } } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + Course that = (Course) o; + + return Objects.equals(courseId,that.courseId) + && Objects.equals(courseName,that.courseName); + } + + @Override + public int hashCode() { + return Objects.hash(courseId,courseName); + } } diff --git a/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/deepcopyarraylist/Student.java b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/deepcopyarraylist/Student.java index 0b3f1ba4a9..ce9f773bc7 100644 --- a/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/deepcopyarraylist/Student.java +++ b/core-java-modules/core-java-lang-oop-patterns/src/main/java/com/baeldung/deepcopyarraylist/Student.java @@ -2,6 +2,7 @@ package com.baeldung.deepcopyarraylist; import java.io.Serializable; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import org.apache.commons.lang3.SerializationUtils; @@ -100,4 +101,23 @@ public class Student implements Serializable, Cloneable { student.course = this.course.clone(); return student; } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + + Student that = (Student) o; + + return Objects.equals(studentId,that.studentId) && + Objects.equals(studentName, that.studentName) && + Objects.equals(course, that.course); + } + + @Override + public int hashCode() { + return Objects.hash(studentId,studentName,course); + } } diff --git a/core-java-modules/core-java-lang-oop-patterns/src/test/java/com/baeldung/deepcopyarraylist/DeepCopyArrayListUnitTest.java b/core-java-modules/core-java-lang-oop-patterns/src/test/java/com/baeldung/deepcopyarraylist/DeepCopyArrayListUnitTest.java index 625c7e8385..d7e4c0ff64 100644 --- a/core-java-modules/core-java-lang-oop-patterns/src/test/java/com/baeldung/deepcopyarraylist/DeepCopyArrayListUnitTest.java +++ b/core-java-modules/core-java-lang-oop-patterns/src/test/java/com/baeldung/deepcopyarraylist/DeepCopyArrayListUnitTest.java @@ -19,8 +19,10 @@ public class DeepCopyArrayListUnitTest { List deepCopy = Student.deepCopyUsingCloneable(students); - Assertions.assertNotEquals(students.get(0), deepCopy.get(0)); - Assertions.assertNotEquals(students.get(1), deepCopy.get(1)); + Assertions.assertEquals(students.get(0), deepCopy.get(0)); + Assertions.assertNotSame(students.get(0),deepCopy.get(0)); + Assertions.assertEquals(students.get(1), deepCopy.get(1)); + Assertions.assertNotSame(students.get(1),deepCopy.get(1)); } @@ -37,8 +39,10 @@ public class DeepCopyArrayListUnitTest { List deepCopy = Student.deepCopyUsingCopyConstructor(students); - Assertions.assertNotEquals(students.get(0), deepCopy.get(0)); - Assertions.assertNotEquals(students.get(1), deepCopy.get(1)); + Assertions.assertEquals(students.get(0), deepCopy.get(0)); + Assertions.assertNotSame(students.get(0),deepCopy.get(0)); + Assertions.assertEquals(students.get(1), deepCopy.get(1)); + Assertions.assertNotSame(students.get(1),deepCopy.get(1)); } @Test @@ -54,8 +58,10 @@ public class DeepCopyArrayListUnitTest { List deepCopy = Student.deepCopyUsingSerialization(students); - Assertions.assertNotEquals(students.get(0), deepCopy.get(0)); - Assertions.assertNotEquals(students.get(1), deepCopy.get(1)); + Assertions.assertEquals(students.get(0), deepCopy.get(0)); + Assertions.assertNotSame(students.get(0),deepCopy.get(0)); + Assertions.assertEquals(students.get(1), deepCopy.get(1)); + Assertions.assertNotSame(students.get(1),deepCopy.get(1)); } @Test @@ -71,7 +77,9 @@ public class DeepCopyArrayListUnitTest { List deepCopy = Student.deepCopyUsingJackson(students); - Assertions.assertNotEquals(students.get(0), deepCopy.get(0)); - Assertions.assertNotEquals(students.get(1), deepCopy.get(1)); + Assertions.assertEquals(students.get(0), deepCopy.get(0)); + Assertions.assertNotSame(students.get(0),deepCopy.get(0)); + Assertions.assertEquals(students.get(1), deepCopy.get(1)); + Assertions.assertNotSame(students.get(1),deepCopy.get(1)); } } diff --git a/core-java-modules/core-java-lang-oop-types/pom.xml b/core-java-modules/core-java-lang-oop-types/pom.xml index a5b492f5ca..a9909598eb 100644 --- a/core-java-modules/core-java-lang-oop-types/pom.xml +++ b/core-java-modules/core-java-lang-oop-types/pom.xml @@ -27,7 +27,7 @@ - 1.15 + 1.16.0 \ No newline at end of file diff --git a/core-java-modules/core-java-lang/src/test/java/com/baeldung/comparator/Java8ComparatorUnitTest.java b/core-java-modules/core-java-lang/src/test/java/com/baeldung/comparator/Java8ComparatorUnitTest.java index dac05a85b1..612fd7e097 100644 --- a/core-java-modules/core-java-lang/src/test/java/com/baeldung/comparator/Java8ComparatorUnitTest.java +++ b/core-java-modules/core-java-lang/src/test/java/com/baeldung/comparator/Java8ComparatorUnitTest.java @@ -30,13 +30,13 @@ public class Java8ComparatorUnitTest { System.out.println("************** Java 8 Comaparator **************"); Comparator byRanking = (Player player1, Player player2) -> Integer.compare(player1.getRanking(), player2.getRanking()); - System.out.println("Before Sorting : " + footballTeam); Collections.sort(footballTeam, byRanking); - System.out.println("After Sorting : " + footballTeam); - assertEquals(footballTeam.get(0) - .getName(), "Steven"); - assertEquals(footballTeam.get(2) - .getRanking(), 67); + assertEquals(footballTeam.get(0).getName(), "Steven"); + assertEquals(footballTeam.get(0).getRanking(), 45); + assertEquals(footballTeam.get(1).getName(), "John"); + assertEquals(footballTeam.get(1).getRanking(), 59); + assertEquals(footballTeam.get(2).getName(), "Roger"); + assertEquals(footballTeam.get(2).getRanking(), 67); } @Test @@ -45,24 +45,24 @@ public class Java8ComparatorUnitTest { System.out.println("********* byRanking *********"); Comparator byRanking = Comparator.comparing(Player::getRanking); - System.out.println("Before Sorting : " + footballTeam); Collections.sort(footballTeam, byRanking); - System.out.println("After Sorting : " + footballTeam); - assertEquals(footballTeam.get(0) - .getName(), "Steven"); - assertEquals(footballTeam.get(2) - .getRanking(), 67); - + assertEquals(footballTeam.get(0).getName(), "Steven"); + assertEquals(footballTeam.get(0).getRanking(), 45); + assertEquals(footballTeam.get(1).getName(), "John"); + assertEquals(footballTeam.get(1).getRanking(), 59); + assertEquals(footballTeam.get(2).getName(), "Roger"); + assertEquals(footballTeam.get(2).getRanking(), 67); + System.out.println("********* byAge *********"); Comparator byAge = Comparator.comparing(Player::getAge); - System.out.println("Before Sorting : " + footballTeam); Collections.sort(footballTeam, byAge); - System.out.println("After Sorting : " + footballTeam); - assertEquals(footballTeam.get(0) - .getName(), "Roger"); - assertEquals(footballTeam.get(2) - .getRanking(), 45); + assertEquals(footballTeam.get(0).getName(), "Roger"); + assertEquals(footballTeam.get(0).getAge(), 20); + assertEquals(footballTeam.get(1).getName(), "John"); + assertEquals(footballTeam.get(1).getAge(), 22); + assertEquals(footballTeam.get(2).getName(), "Steven"); + assertEquals(footballTeam.get(2).getAge(), 24); } } diff --git a/core-java-modules/core-java-networking-4/README.md b/core-java-modules/core-java-networking-4/README.md index 10ca7caf41..72c8e421f2 100644 --- a/core-java-modules/core-java-networking-4/README.md +++ b/core-java-modules/core-java-networking-4/README.md @@ -4,3 +4,4 @@ - [Validating IPv4 Address in Java](https://www.baeldung.com/java-validate-ipv4-address) - [Download a Webpage in Java](https://www.baeldung.com/java-download-webpage) - [URL Query Manipulation in Java](https://www.baeldung.com/java-url-query-manipulation) +- [Understanding the java.net.SocketException Broken Pipe Error](https://www.baeldung.com/java-socketexception-broken-pipe-error) diff --git a/core-java-modules/core-java-numbers-6/README.md b/core-java-modules/core-java-numbers-6/README.md index 560a84f851..67f574652c 100644 --- a/core-java-modules/core-java-numbers-6/README.md +++ b/core-java-modules/core-java-numbers-6/README.md @@ -1,6 +1,6 @@ ### Relevant Articles: - [Java Program to Estimate Pi](https://www.baeldung.com/java-monte-carlo-compute-pi) - [Convert Integer to Hexadecimal in Java](https://www.baeldung.com/java-convert-int-to-hex) -- [Integer.class Vs. Integer.TYPE Vs. int.class](https://www.baeldung.com/java-integer-class-vs-type-vs-int) +- [Integer.class vs Integer.TYPE vs int.class](https://www.baeldung.com/java-integer-class-vs-type-vs-int) - [Does Java Read Integers in Little Endian or Big Endian?](https://www.baeldung.com/java-integers-little-big-endian) - More articles: [[<-- prev]](../core-java-numbers-5) diff --git a/core-java-modules/core-java-scanner/README.md b/core-java-modules/core-java-scanner/README.md index 87bd9c41bc..6208dda964 100644 --- a/core-java-modules/core-java-scanner/README.md +++ b/core-java-modules/core-java-scanner/README.md @@ -11,5 +11,5 @@ This module contains articles about the Scanner. - [Integer.parseInt(scanner.nextLine()) and scanner.nextInt() in Java](https://www.baeldung.com/java-scanner-integer) - [Storing Java Scanner Input in an Array](https://www.baeldung.com/java-store-scanner-input-in-array) - [How to Take Input as String With Spaces in Java Using Scanner?](https://www.baeldung.com/java-scanner-input-with-spaces) -- [What’s the difference between Scanner next() and nextLine() methods?](https://www.baeldung.com/java-scanner-next-vs-nextline) +- [What’s the Difference between Scanner next() and nextLine() Methods?](https://www.baeldung.com/java-scanner-next-vs-nextline) - [Handle NoSuchElementException When Reading a File Through Scanner](https://www.baeldung.com/java-scanner-nosuchelementexception-reading-file) diff --git a/core-java-modules/core-java-security-algorithms/pom.xml b/core-java-modules/core-java-security-algorithms/pom.xml index 0dde9f861a..0204203fd7 100644 --- a/core-java-modules/core-java-security-algorithms/pom.xml +++ b/core-java-modules/core-java-security-algorithms/pom.xml @@ -13,28 +13,4 @@ 0.0.1-SNAPSHOT - - - commons-codec - commons-codec - ${commons-codec.version} - - - org.bouncycastle - bcprov-jdk15on - ${bouncycastle.version} - - - javax.xml.bind - jaxb-api - ${jaxb-api.version} - - - - - 1.60 - 1.11 - 2.3.1 - - \ No newline at end of file diff --git a/core-java-modules/core-java-string-conversions-3/README.md b/core-java-modules/core-java-string-conversions-3/README.md index 96799d1660..4b348dd555 100644 --- a/core-java-modules/core-java-string-conversions-3/README.md +++ b/core-java-modules/core-java-string-conversions-3/README.md @@ -1,3 +1,4 @@ ## Relevant Articles - [Object.toString() vs String.valueOf()](https://www.baeldung.com/java-object-tostring-vs-string-valueof) - [Convert String to Int Using Encapsulation](https://www.baeldung.com/java-encapsulation-convert-string-to-int) +- [HashMap with Multiple Values for the Same Key](https://www.baeldung.com/java-hashmap-multiple-values-per-key) diff --git a/core-java-modules/core-java-string-conversions-3/src/java.com.baeldung.multivluehashmap/MultiValueHashMapTest.java b/core-java-modules/core-java-string-conversions-3/src/java.com.baeldung.multivluehashmap/MultiValueHashMapTest.java new file mode 100644 index 0000000000..a3d0bc35de --- /dev/null +++ b/core-java-modules/core-java-string-conversions-3/src/java.com.baeldung.multivluehashmap/MultiValueHashMapTest.java @@ -0,0 +1,79 @@ +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +public class MultiValueHashMapTest { + @Test + public void given_MultiValueHashMap_whenPuttingAndGettingSingleValue_thenValueIsRetrieved() { + MultiValueHashMap map = new MultiValueHashMap<>(); + map.put("key1", 10); + assertEquals(List.of(10), map.get("key1")); + } + + @Test + public void given_MultiValueHashMap_whenPuttingAndGettingMultipleValues_thenAllValuesAreRetrieved() { + MultiValueHashMap map = new MultiValueHashMap<>(); + map.put("key2", "value1"); + map.put("key2", "value2"); + map.put("key2", "value3"); + + assertEquals(List.of("value1", "value2", "value3"), map.get("key2")); + } + + @Test + public void given_MultiValueHashMap_whenGettingNonExistentKey_thenEmptyListIsReturned() { + MultiValueHashMap map = new MultiValueHashMap<>(); + assertTrue(map.get("nonexistent").isEmpty()); + } + + @Test + public void given_MultiValueHashMap_whenRemovingValue_thenValueIsSuccessfullyRemoved() { + MultiValueHashMap map = new MultiValueHashMap<>(); + map.put(1, "one"); + map.put(1, "uno"); + map.put(1, "eins"); + + map.remove(1, "uno"); + assertEquals(List.of("one", "eins"), map.get(1)); + } + + @Test + public void testRemoveNonExistentValue() { + MultiValueHashMap map = new MultiValueHashMap<>(); + map.put(1, "one"); + map.remove(1, "nonexistent"); + assertEquals(List.of("one"), map.get(1)); + } + + public class MultiValueHashMap { + private HashMap> map; + + // Constructor + public MultiValueHashMap() { + map = new HashMap<>(); + } + + public void put(K key, V value) { + if (!map.containsKey(key)) { + map.put(key, new ArrayList<>()); + } + map.get(key).add(value); + } + + public List get(K key) { + return map.getOrDefault(key, new ArrayList<>()); + } + + public void remove(K key, V value) { + if (map.containsKey(key)) { + map.get(key).remove(value); + } + } + + + } +} diff --git a/core-java-modules/core-java-string-conversions-3/src/main/java/com/baeldung/hashmapmultivalues/MultiValueHashMap.java b/core-java-modules/core-java-string-conversions-3/src/main/java/com/baeldung/hashmapmultivalues/MultiValueHashMap.java new file mode 100644 index 0000000000..5e4faebb05 --- /dev/null +++ b/core-java-modules/core-java-string-conversions-3/src/main/java/com/baeldung/hashmapmultivalues/MultiValueHashMap.java @@ -0,0 +1,29 @@ +package com.baeldung.hashmapmultivalues; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class MultiValueHashMap { + private final HashMap> map; + + // Constructor + public MultiValueHashMap() { + map = new HashMap<>(); + } + + public void put(K key, V value) { + map.computeIfAbsent(key, k -> new ArrayList<>()).add(value); + } + + public List get(K key) { + return map.getOrDefault(key, new ArrayList<>()); + } + + public void remove(K key, V value) { + map.computeIfPresent(key, (k, v) -> { + v.remove(value); + return v; + }); + } +} \ No newline at end of file diff --git a/core-java-modules/core-java-string-conversions-3/src/test/java/com/baeldung/hashmapmultivalues/MultiValueHashMapUnitTest.java b/core-java-modules/core-java-string-conversions-3/src/test/java/com/baeldung/hashmapmultivalues/MultiValueHashMapUnitTest.java new file mode 100644 index 0000000000..b330df22df --- /dev/null +++ b/core-java-modules/core-java-string-conversions-3/src/test/java/com/baeldung/hashmapmultivalues/MultiValueHashMapUnitTest.java @@ -0,0 +1,53 @@ +package com.baeldung.hashmapmultivalues; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.*; + +public class MultiValueHashMapUnitTest { + @Test + public void given_MultiValueHashMap_whenPuttingAndGettingSingleValue_thenValueIsRetrieved() { + MultiValueHashMap map = new MultiValueHashMap<>(); + map.put("key1", 10); + assertEquals(List.of(10), map.get("key1")); + } + + @Test + public void given_MultiValueHashMap_whenPuttingAndGettingMultipleValues_thenAllValuesAreRetrieved() { + MultiValueHashMap map = new MultiValueHashMap<>(); + map.put("key2", "value1"); + map.put("key2", "value2"); + map.put("key2", "value3"); + + assertEquals(List.of("value1", "value2", "value3"), map.get("key2")); + } + + @Test + public void given_MultiValueHashMap_whenGettingNonExistentKey_thenEmptyListIsReturned() { + MultiValueHashMap map = new MultiValueHashMap<>(); + assertTrue(map.get("nonexistent").isEmpty()); + } + + @Test + public void given_MultiValueHashMap_whenRemovingValue_thenValueIsSuccessfullyRemoved() { + MultiValueHashMap map = new MultiValueHashMap<>(); + map.put(1, "one"); + map.put(1, "uno"); + map.put(1, "eins"); + + map.remove(1, "uno"); + assertEquals(List.of("one", "eins"), map.get(1)); + } + + @Test + public void testRemoveNonExistentValue() { + MultiValueHashMap map = new MultiValueHashMap<>(); + map.put(1, "one"); + map.remove(1, "nonexistent"); + assertEquals(List.of("one"), map.get(1)); + } + +} diff --git a/core-java-modules/core-java-string-operations-6/README.md b/core-java-modules/core-java-string-operations-6/README.md index 10f59a56e3..853d58287d 100644 --- a/core-java-modules/core-java-string-operations-6/README.md +++ b/core-java-modules/core-java-string-operations-6/README.md @@ -9,3 +9,4 @@ - [Split a String Into Digit and Non-Digit Substrings](https://www.baeldung.com/java-split-string-digits-letters) - [Check if a String Contains Non-Alphanumeric Characters](https://www.baeldung.com/java-string-test-special-characters) - [Check if a String Has All Unique Characters in Java](https://www.baeldung.com/java-check-string-all-unique-chars) +- [Performance Comparison Between Different Java String Concatenation Methods](https://www.baeldung.com/java-string-concatenation-methods) diff --git a/core-java-modules/pom.xml b/core-java-modules/pom.xml index ada8b68d1a..e9bb86e500 100644 --- a/core-java-modules/pom.xml +++ b/core-java-modules/pom.xml @@ -75,7 +75,7 @@ core-java-function core-java-functional core-java-hex - + core-java-io core-java-io-2 core-java-io-3 core-java-io-4 @@ -143,7 +143,6 @@ core-java-regex core-java-regex-2 core-java-uuid - pre-jpms core-java-collections-maps-6 core-java-records diff --git a/core-java-modules/pre-jpms/README.md b/core-java-modules/pre-jpms/README.md deleted file mode 100644 index 8c9af82ba5..0000000000 --- a/core-java-modules/pre-jpms/README.md +++ /dev/null @@ -1,3 +0,0 @@ -## Relevant Articles - -- [Java 9 Migration Issues and Resolutions](https://www.baeldung.com/java-9-migration-issue) diff --git a/core-java-modules/pre-jpms/pom.xml b/core-java-modules/pre-jpms/pom.xml deleted file mode 100644 index 67bc913767..0000000000 --- a/core-java-modules/pre-jpms/pom.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - 4.0.0 - pre-jpms - pre-jpms - jar - - - com.baeldung.core-java-modules - core-java-modules - 0.0.1-SNAPSHOT - - - - - javax.xml.bind - jaxb-api - 2.4.0-b180725.0427 - - - org.slf4j - slf4j-api - ${org.slf4j.version} - - - - - pre-jpms - - - org.apache.maven.plugins - maven-compiler-plugin - ${compiler.plugin.version} - - ${source.version} - ${target.version} - - --add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED - - - - - org.apache.maven.plugins - maven-dependency-plugin - ${dependency.plugin.version} - - - copy-dependencies - package - - copy-dependencies - - - - ${project.build.directory}/dependency-jars/ - - - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - com.baeldung.prejpms.App - true - dependency-jars/ - - - - - - - - - 3.1.1 - 3.8.0 - 11 - 11 - - - \ No newline at end of file diff --git a/di-modules/avaje/README.md b/di-modules/avaje/README.md new file mode 100644 index 0000000000..f0fa9f058e --- /dev/null +++ b/di-modules/avaje/README.md @@ -0,0 +1,7 @@ +# Introduction to Avaje Inject + +This module contains articles about Avaje + +### Relevant articles: + +- [Introduction to Avaje Inject](https://www.baeldung.com/avaje-inject) diff --git a/di-modules/avaje/pom.xml b/di-modules/avaje/pom.xml new file mode 100644 index 0000000000..7ffe14bd72 --- /dev/null +++ b/di-modules/avaje/pom.xml @@ -0,0 +1,37 @@ + + 4.0.0 + com.baeldung + inject-intro + 0.0.1-SNAPSHOT + avaje-inject-intro + + 11 + 11 + 9.5 + + + + io.avaje + avaje-inject + ${avaje.inject.version} + + + + io.avaje + avaje-inject-test + ${avaje.inject.version} + test + + + + + io.avaje + avaje-inject-generator + ${avaje.inject.version} + provided + true + + + \ No newline at end of file diff --git a/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/ArmsFactory.java b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/ArmsFactory.java new file mode 100644 index 0000000000..381b390ad0 --- /dev/null +++ b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/ArmsFactory.java @@ -0,0 +1,18 @@ +package com.baeldung.avaje.intro; + +import io.avaje.inject.Bean; +import io.avaje.inject.Factory; + +@Factory +public class ArmsFactory { + + @Bean + public Sword provideSword() { + return new Sword(); + } + + @Bean + public Shield provideShield() { + return new Shield(25); + } +} diff --git a/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Knight.java b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Knight.java new file mode 100644 index 0000000000..c78c60b858 --- /dev/null +++ b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Knight.java @@ -0,0 +1,34 @@ +package com.baeldung.avaje.intro; + +import jakarta.inject.Inject; +import jakarta.inject.Singleton; + +@Singleton +public class Knight { + + private Sword sword; + + private Shield shield; + + @Inject + public Knight(Sword sword, Shield shield) { + this.sword = sword; + this.shield = shield; + } + + public Sword sword() { + return sword; + } + + public void sword(Sword engine) { + this.sword = engine; + } + + public Shield shield() { + return shield; + } + + public void shield(Shield brand) { + this.shield = brand; + } +} diff --git a/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Ninja.java b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Ninja.java new file mode 100644 index 0000000000..e4d893ffef --- /dev/null +++ b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Ninja.java @@ -0,0 +1,30 @@ +package com.baeldung.avaje.intro; + +import io.avaje.inject.BeanScope; +import io.avaje.inject.PostConstruct; +import io.avaje.inject.PreDestroy; +import jakarta.inject.Singleton; + +@Singleton +public class Ninja { + + private Sword sword; + + @PostConstruct + void equip(BeanScope scope) { + sword = scope.get(Sword.class); + } + + @PreDestroy + void dequip() { + sword = null; + } + + public Sword sword() { + return sword; + } + + public void sword(Sword engine) { + this.sword = engine; + } +} diff --git a/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Shield.java b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Shield.java new file mode 100644 index 0000000000..c5d5a3e999 --- /dev/null +++ b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Shield.java @@ -0,0 +1,18 @@ +package com.baeldung.avaje.intro; + +public class Shield { + + private int defense; + + public Shield(int defense) { + this.defense = defense; + } + + public int defense() { + return defense; + } + + public void defense(int defense) { + this.defense = defense; + } +} diff --git a/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Sword.java b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Sword.java new file mode 100644 index 0000000000..6eceed082e --- /dev/null +++ b/di-modules/avaje/src/main/java/com/baeldung/avaje/intro/Sword.java @@ -0,0 +1,8 @@ +package com.baeldung.avaje.intro; + +public class Sword { + + public void attack() { + System.out.println("swing"); + } +} diff --git a/di-modules/avaje/src/test/java/com/baeldung/avaje/intro/AvajeUnitTest.java b/di-modules/avaje/src/test/java/com/baeldung/avaje/intro/AvajeUnitTest.java new file mode 100644 index 0000000000..a0b71a228a --- /dev/null +++ b/di-modules/avaje/src/test/java/com/baeldung/avaje/intro/AvajeUnitTest.java @@ -0,0 +1,21 @@ +package com.baeldung.avaje.intro; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; + +import io.avaje.inject.BeanScope; + +class AvajeUnitTest { + + @Test + void givenBeanScope_whenScopeGetsKnight_thenKnightShouldHaveDependencies() { + + final var scope = BeanScope.builder().build(); + final var knight = scope.get(Knight.class); + + assertNotNull(knight); + assertNotNull(knight.sword()); + assertNotNull(knight.shield()); + assertEquals(25, knight.shield().defense()); + } +} diff --git a/di-modules/avaje/src/test/java/com/baeldung/avaje/intro/ExampleInjectTest.java b/di-modules/avaje/src/test/java/com/baeldung/avaje/intro/ExampleInjectTest.java new file mode 100644 index 0000000000..6eada4cb6d --- /dev/null +++ b/di-modules/avaje/src/test/java/com/baeldung/avaje/intro/ExampleInjectTest.java @@ -0,0 +1,29 @@ +package com.baeldung.avaje.intro; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.Mockito; + +import io.avaje.inject.test.InjectTest; +import jakarta.inject.Inject; + +@InjectTest +class ExampleInjectTest { + + @Mock Shield shield; + + @Inject Knight knight; + + @Test + void givenMockedShield_whenGetShield_thenShieldShouldHaveMockedValue() { + + Mockito.when(shield.defense()).thenReturn(0); + assertNotNull(knight); + assertNotNull(knight.sword()); + assertNotNull(knight.shield()); + assertEquals(0, knight.shield().defense()); + } +} diff --git a/jackson-modules/jackson-jr/README.md b/jackson-modules/jackson-jr/README.md new file mode 100644 index 0000000000..f435469a90 --- /dev/null +++ b/jackson-modules/jackson-jr/README.md @@ -0,0 +1,2 @@ +## Relevant Articles +- [Guide to Java Jackson-jr Library](https://www.baeldung.com/java-jackson-jr-library) diff --git a/jackson-modules/jackson-polymorphic-deserialization/README.md b/jackson-modules/jackson-polymorphic-deserialization/README.md new file mode 100644 index 0000000000..feb40da5c4 --- /dev/null +++ b/jackson-modules/jackson-polymorphic-deserialization/README.md @@ -0,0 +1,2 @@ +## Relevant Articles +- [@JsonSubTypes Vs. Reflections for Polymorphic Deserialization in Jackson](https://www.baeldung.com/java-jackson-polymorphic-deserialization) diff --git a/java-native/README.md b/java-native/README.md index 2aa02c03d5..50c9feadc4 100644 --- a/java-native/README.md +++ b/java-native/README.md @@ -8,3 +8,4 @@ This module contains articles about the Java Native Interface (JNI). - [Using JNA to Access Native Dynamic Libraries](https://www.baeldung.com/java-jna-dynamic-libraries) - [Check if a Java Program Is Running in 64-Bit or 32-Bit JVM](https://www.baeldung.com/java-detect-jvm-64-or-32-bit) - [How to use JNI’s RegisterNatives() method?](https://www.baeldung.com/jni-registernatives) +- [Custom DLL Load – Fixing the “java.lang.UnsatisfiedLinkError” Error](https://www.baeldung.com/java-custom-dll-load-fixing-the-java-lang-unsatisfiedlinkerror-error) diff --git a/javaxval-2/README.md b/javaxval-2/README.md index b7603d9e84..3ae53ebd94 100644 --- a/javaxval-2/README.md +++ b/javaxval-2/README.md @@ -7,4 +7,5 @@ This module contains articles about Bean Validation. - [Guide to ParameterMessageInterpolator](https://www.baeldung.com/hibernate-parametermessageinterpolator) - [Hibernate Validator Annotation Processor in Depth](https://www.baeldung.com/hibernate-validator-annotation-processor) - [Object Validation After Deserialization](https://www.baeldung.com/java-object-validation-deserialization) +- [Java Validation List Annotations](https://www.baeldung.com/java-validation-list-annotations) - More articles: [[<-- prev]](../javaxval) diff --git a/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/AllLevels.java b/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/AllLevels.java new file mode 100644 index 0000000000..b6660c225a --- /dev/null +++ b/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/AllLevels.java @@ -0,0 +1,4 @@ +package com.baeldung.javaxval.listvalidation; + +public interface AllLevels { +} diff --git a/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/JobAspirant.java b/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/JobAspirant.java new file mode 100644 index 0000000000..31c8d69639 --- /dev/null +++ b/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/JobAspirant.java @@ -0,0 +1,95 @@ +package com.baeldung.javaxval.listvalidation; + +import jakarta.validation.constraints.*; + +import java.util.Date; + +public class JobAspirant { + @Size.List({ + @Size(min = 5, message = "Name should have at least 5 characters", groups = AllLevels.class), + @Size(max = 20, message = "Name should have at most 20 characters", groups = AllLevels.class) + }) + @Pattern.List({ + @Pattern(regexp = "^[\\p{Alpha} ]*$", message = "Name should contain only alphabets and space", groups = AllLevels.class), + @Pattern(regexp = "^[^\\s].*$", message = "Name should not start with space", groups = AllLevels.class), + @Pattern(regexp = "^.*[^\\s]$", message = "Name should not end with space", groups = AllLevels.class), + @Pattern(regexp = "^((?! ).)*$", message = "Name should not contain consecutive spaces", groups = AllLevels.class), + @Pattern(regexp = "^[^a-z].*$", message = "Name should not start with a lower case character", groups = AllLevels.class) + }) + private String name; + + @Min.List({ + @Min(value = 15, message = "Years of experience cannot be less than 15 Years", groups = Senior.class), + @Min(value = 10, message = "Years of experience cannot be less than 10 Years", groups = MidSenior.class), + @Min(value = 5, message = "Years of experience cannot be less than 5 Years", groups = Junior.class) + }) + @Max.List({ + @Max(value = 20, message = "Years of experience cannot be more than 20 Years", groups = Senior.class), + @Max(value = 15, message = "Years of experience cannot be more than 15 Years", groups = MidSenior.class), + @Max(value = 10, message = "Years of experience cannot be more than 10 Years", groups = Junior.class) + }) + private Integer experience; + + @AssertTrue.List({ + @AssertTrue(message = "Terms and Conditions consent missing for Senior Level Job", groups = Senior.class), + @AssertTrue(message = "Terms and Conditions consent missing for Mid-Senior Level Job", groups = MidSenior.class), + @AssertTrue(message = "Terms and Conditions consent missing for Junior Level Job", groups = Junior.class) + }) + private Boolean agreement; + + @Future.List({ + @Future(message = "Active passport is mandatory for Senior Level Job", groups = Senior.class), + @Future(message = "Active passport is mandatory for Mid-Senior Level Job", groups = MidSenior.class), + @Future(message = "Active passport is mandatory for Junior Level Job", groups = Junior.class) + }) + private Date passportExpiryDate; + + @Pattern.List({ + @Pattern(regexp = "^(Senior)$", message = "Job level should be Senior" + ,flags = Pattern.Flag.CASE_INSENSITIVE, groups = Senior.class), + @Pattern(regexp = "^(MidSenior)$", message = "Job level should be MidSenior" + ,flags = Pattern.Flag.CASE_INSENSITIVE, groups = MidSenior.class), + @Pattern(regexp = "^(Junior)$", message = "Job level should be Junior" + ,flags = Pattern.Flag.CASE_INSENSITIVE, groups = Junior.class) + }) + private String jobLevel; + + public String getJobLevel() { + return jobLevel; + } + + public String getName() { + return name; + } + + public Boolean getAgreement() { + return agreement; + } + public Date getPassportExpiryDate() { + return passportExpiryDate; + } + + public void setAgreement(Boolean agreement) { + this.agreement = agreement; + } + + public void setName(String name) { + this.name = name; + } + + public void setJobLevel(String jobLevel) { + this.jobLevel = jobLevel; + } + + public void setPassportExpiryDate(Date passportExpiryDate) { + this.passportExpiryDate = passportExpiryDate; + } + + public Integer getExperience() { + return experience; + } + + public void setExperience(Integer experience) { + this.experience = experience; + } +} diff --git a/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/Junior.java b/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/Junior.java new file mode 100644 index 0000000000..e881f4d6cd --- /dev/null +++ b/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/Junior.java @@ -0,0 +1,4 @@ +package com.baeldung.javaxval.listvalidation; + +public interface Junior { +} diff --git a/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/MidSenior.java b/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/MidSenior.java new file mode 100644 index 0000000000..f3a6bb67f8 --- /dev/null +++ b/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/MidSenior.java @@ -0,0 +1,4 @@ +package com.baeldung.javaxval.listvalidation; + +public interface MidSenior { +} diff --git a/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/Senior.java b/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/Senior.java new file mode 100644 index 0000000000..be3cf00d9c --- /dev/null +++ b/javaxval-2/src/main/java/com/baeldung/javaxval/listvalidation/Senior.java @@ -0,0 +1,4 @@ +package com.baeldung.javaxval.listvalidation; + +public interface Senior { +} diff --git a/javaxval-2/src/test/java/com/baeldung/javaxval/listvalidation/JobAspirantUnitTest.java b/javaxval-2/src/test/java/com/baeldung/javaxval/listvalidation/JobAspirantUnitTest.java new file mode 100644 index 0000000000..cee020c69f --- /dev/null +++ b/javaxval-2/src/test/java/com/baeldung/javaxval/listvalidation/JobAspirantUnitTest.java @@ -0,0 +1,209 @@ +package com.baeldung.javaxval.listvalidation; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validation; +import jakarta.validation.Validator; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +public class JobAspirantUnitTest { + private static Validator validator; + @BeforeClass + public static void setupValidatorInstance() { + validator = Validation.buildDefaultValidatorFactory().getValidator(); + } + @Test + public void givenJobLevelJunior_whenInValidMinExperience_thenExpectErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("Junior", "John Adam", "2025-12-31", 3, true); + Set> violations = validator.validate(jobAspirant, Junior.class); + assertThat(violations.size()).isEqualTo(1); + violations.forEach(action -> { + assertThat(action.getPropertyPath().toString()).isEqualTo("experience"); + assertThat(action.getMessage()).isEqualTo("Years of experience cannot be less than 5 Years"); + }); + } + @Test + public void givenJobLevelMidSenior_whenInvalidMinExperience_thenExpectErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("MidSenior", "John Adam", "2025-12-31", 8, true); + Set> violations = validator.validate(jobAspirant, MidSenior.class); + assertThat(violations.size()).isEqualTo(1); + violations.forEach(action -> { + assertThat(action.getPropertyPath().toString()).isEqualTo("experience"); + assertThat(action.getMessage()).isEqualTo("Years of experience cannot be less than 10 Years"); + }); + } + @Test + public void givenJobLevelSenior_whenInvalidMinExperience_thenExpectErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("Senior", "John Adam", "2025-12-31", 13, true); + Set> violations = validator.validate(jobAspirant, Senior.class); + assertThat(violations.size()).isEqualTo(1); + violations.forEach(action -> { + assertThat(action.getPropertyPath().toString()).isEqualTo("experience"); + assertThat(action.getMessage()).isEqualTo("Years of experience cannot be less than 15 Years"); + }); + } + @Test + public void givenJobLevelJunior_whenInValidMaxExperience_thenExpectErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("Junior", "John Adam", "2025-12-31", 11, true); + Set> violations = validator.validate(jobAspirant, Junior.class); + assertThat(violations.size()).isEqualTo(1); + violations.forEach(action -> { + assertThat(action.getPropertyPath().toString()).isEqualTo("experience"); + assertThat(action.getMessage()).isEqualTo("Years of experience cannot be more than 10 Years"); + }); + } + @Test + public void givenJobLevelMidSenior_whenInvalidMaxExperience_thenExpectErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("MidSenior", "John Adam", "2025-12-31", 16, true); + Set> violations = validator.validate(jobAspirant, MidSenior.class); + assertThat(violations.size()).isEqualTo(1); + violations.forEach(action -> { + assertThat(action.getPropertyPath().toString()).isEqualTo("experience"); + assertThat(action.getMessage()).isEqualTo("Years of experience cannot be more than 15 Years"); + }); + } + @Test + public void givenJobLevelSenior_whenInvalidMaxExperience_thenExpectErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("Senior", "John Adam", "2025-12-31", 23, true); + Set> violations = validator.validate(jobAspirant, Senior.class); + assertThat(violations.size()).isEqualTo(1); + violations.forEach(action -> { + assertThat(action.getPropertyPath().toString()).isEqualTo("experience"); + assertThat(action.getMessage()).isEqualTo("Years of experience cannot be more than 20 Years"); + }); + } + @Test + public void whenInvalidName_thenExpectErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("Senior", "John Adam", "2025-12-31", 17, true); + Set> violations = validator.validate(jobAspirant, Senior.class, AllLevels.class); + assertThat(violations.size()).isEqualTo(1); + violations.forEach(action -> { + assertThat(action.getPropertyPath().toString()).isEqualTo("name"); + assertThat(action.getMessage()).isEqualTo("Name should not contain consecutive spaces"); + }); + } + @Test + public void givenJuniorLevel_whenInvalidAgreement_thenExpectErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("Junior", "John Adam", "2025-12-31", 7, false); + Set> violations = validator.validate(jobAspirant, Junior.class); + assertThat(violations.size()).isEqualTo(1); + violations.forEach(action -> { + assertThat(action.getPropertyPath().toString()).isEqualTo("agreement"); + assertThat(action.getMessage()).isEqualTo("Terms and Conditions consent missing for Junior Level Job"); + }); + } + @Test + public void givenSeniorLevel_whenInvalidAgreement_thenExpectErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("Senior", "John Adam", "2025-12-31", 17, false); + Set> violations = validator.validate(jobAspirant, Senior.class); + assertThat(violations.size()).isEqualTo(1); + violations.forEach(action -> { + assertThat(action.getPropertyPath().toString()).isEqualTo("agreement"); + assertThat(action.getMessage()).isEqualTo("Terms and Conditions consent missing for Senior Level Job"); + }); + } + @Test + public void givenJobLevelMidSenior_whenInvalidPassport_thenExpectErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("MidSenior", "John Adam", "2021-12-31", 12, true); + Set> violations = validator.validate(jobAspirant, MidSenior.class); + assertThat(violations.size()).isEqualTo(1); + violations.forEach(action -> { + assertThat(action.getPropertyPath().toString()).isEqualTo("passportExpiryDate"); + assertThat(action.getMessage()).isEqualTo("Active passport is mandatory for Mid-Senior Level Job"); + }); + } + @Test + public void givenJobLevelSenior_whenInvalidPassport_thenExpectErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("Senior", "John Adam", "2021-12-31", 18, true); + Set> violations = validator.validate(jobAspirant, Senior.class); + assertThat(violations.size()).isEqualTo(1); + violations.forEach(action -> { + assertThat(action.getPropertyPath().toString()).isEqualTo("passportExpiryDate"); + assertThat(action.getMessage()).isEqualTo("Active passport is mandatory for Senior Level Job"); + }); + } + @Test + public void givenJobLevelSenior_whenAllFieldsValid_thenNoErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("Senior", "John Adam", "2025-12-31", 17, true); + Set> violations = validator.validate(jobAspirant, Senior.class, AllLevels.class); + assertThat(violations.size()).isEqualTo(0); + } + @Test + public void givenJobLevelMidSenior_whenAllFieldsValid_thenNoErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("MidSenior", "John Adam", "2025-12-31", 12, true); + Set> violations = validator.validate(jobAspirant, MidSenior.class, AllLevels.class); + assertThat(violations.size()).isEqualTo(0); + } + @Test + public void givenJobLevelJunior_whenAllFieldsValid_thenNoErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("Junior", "John Adam", "2025-12-31", 7, true); + Set> violations = validator.validate(jobAspirant, Junior.class, AllLevels.class); + assertThat(violations.size()).isEqualTo(0); + } + @Test + public void givenJobLevelJunior_whenAllFieldsInValid_thenExpectErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("Junior", " John Adam", "2022-12-31", 3, false); + Set> violations = validator.validate(jobAspirant, Junior.class, AllLevels.class); + assertThat(violations.size()).isEqualTo(4); + violations.forEach(action -> { + String fieldName = action.getPropertyPath().toString(); + switch(fieldName) { + case "name": + assertThat(action.getMessage()).isEqualTo("Name should not start with space"); + break; + case "passportExpiryDate": + assertThat(action.getMessage()).isEqualTo("Active passport is mandatory for Junior Level Job"); + break; + case "experience": + assertThat(action.getMessage()).isEqualTo("Years of experience cannot be less than 5 Years"); + break; + case "agreement": + assertThat(action.getMessage()).isEqualTo("Terms and Conditions consent missing for Junior Level Job"); + break; + } + }); + } + @Test + public void givenJobLevelSenior_whenAllFieldsInValid_thenExpectErrors() throws ParseException { + JobAspirant jobAspirant = getJobAspirant("Senior", "John Adam ", "2022-12-31", 12, false); + Set> violations = validator.validate(jobAspirant, Senior.class, AllLevels.class); + assertThat(violations.size()).isEqualTo(4); + violations.forEach(action -> { + String fieldName = action.getPropertyPath().toString(); + switch(fieldName) { + case "name": + assertThat(action.getMessage()).isEqualTo("Name should not end with space"); + break; + case "passportExpiryDate": + assertThat(action.getMessage()).isEqualTo("Active passport is mandatory for Senior Level Job"); + break; + case "experience": + assertThat(action.getMessage()).isEqualTo("Years of experience cannot be less than 15 Years"); + break; + case "agreement": + assertThat(action.getMessage()).isEqualTo("Terms and Conditions consent missing for Senior Level Job"); + break; + } + }); + } + private JobAspirant getJobAspirant(String jobLevel, String name, String passportExpDate, int exp, boolean agmt) throws ParseException { + JobAspirant jobAspirant = new JobAspirant(); + jobAspirant.setName(name); + jobAspirant.setPassportExpiryDate(convertStringToDate(passportExpDate)); + jobAspirant.setJobLevel(jobLevel); + jobAspirant.setExperience(exp); + jobAspirant.setAgreement(agmt); + return jobAspirant; + } + private Date convertStringToDate(String date) throws ParseException { + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); + return formatter.parse(date); + } +} diff --git a/json-modules/json-2/README.md b/json-modules/json-2/README.md index adf55c3618..a29484d9fc 100644 --- a/json-modules/json-2/README.md +++ b/json-modules/json-2/README.md @@ -12,5 +12,6 @@ This module contains articles about JSON. - [Check Whether a String Is Valid JSON in Java](https://www.baeldung.com/java-validate-json-string) - [Getting a Value in JSONObject](https://www.baeldung.com/java-jsonobject-get-value) - [Pretty-Print a JSON in Java](https://www.baeldung.com/java-json-pretty-print) +- [Remove Whitespaces From a JSON in Java](https://www.baeldung.com/java-json-minify-remove-whitespaces) - More Articles: [[<-- prev]](/json-modules/json) diff --git a/json-modules/json-2/pom.xml b/json-modules/json-2/pom.xml index 82fe689ebf..7253088516 100644 --- a/json-modules/json-2/pom.xml +++ b/json-modules/json-2/pom.xml @@ -1,7 +1,7 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 json-2 0.0.1-SNAPSHOT @@ -123,6 +123,26 @@ javax.annotation-api 1.3.2 + + com.github.victools + jsonschema-generator + ${jsonschema-generator.version} + + + com.github.victools + jsonschema-module-jackson + ${jsonschema-generator.version} + + + jakarta.validation + jakarta.validation-api + ${jakarta.validation.version} + + + com.github.victools + jsonschema-module-jakarta-validation + ${jsonschema-generator.version} + @@ -162,6 +182,55 @@ + + + com.github.victools + jsonschema-maven-plugin + ${jsonschema-generator.version} + + + + generate + + + + + + com.baeldung.jsonschemageneration.plugin + + + com.baeldung.jsonschemageneration.plugin.Person + + DRAFT_2020_12 + src/main/resources/schemas + {1}/{0}.json + true + + PLAIN_JSON + + + + + SCHEMA_VERSION_INDICATOR + + + + Jackson + + + + + + JakartaValidation + + + + + + + + + @@ -173,6 +242,8 @@ 0.1.1 0.4.2 0.13.0 + 4.31.1 + 3.0.2 \ No newline at end of file diff --git a/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/configuration/AdvancedArticle.java b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/configuration/AdvancedArticle.java new file mode 100644 index 0000000000..07e00bba0f --- /dev/null +++ b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/configuration/AdvancedArticle.java @@ -0,0 +1,70 @@ +package com.baeldung.jsonschemageneration.configuration; + +import java.sql.Timestamp; +import java.util.Date; +import java.util.UUID; + +enum Area { + JAVA("JAVA"), KOTLIN("KOTLIN"), SCALA("SCALA"), LINUX("LINUX"); + + private final String area; + + Area(String area) { + this.area = area; + } + + public String getArea() { + return area; + } +} + +public class AdvancedArticle { + private UUID id; + private String title; + + private String content; + + @AllowedTypes({ Timestamp.class, Date.class }) + private Object createdAt; + private Area area; + + public Area getArea() { + return area; + } + + public void setArea(Area area) { + this.area = area; + } + + public Object getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Object createdAt) { + this.createdAt = createdAt; + } + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} diff --git a/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/configuration/AdvancedConfigurationSchemaGenerator.java b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/configuration/AdvancedConfigurationSchemaGenerator.java new file mode 100644 index 0000000000..3fbf6bac6e --- /dev/null +++ b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/configuration/AdvancedConfigurationSchemaGenerator.java @@ -0,0 +1,39 @@ +package com.baeldung.jsonschemageneration.configuration; + +import com.fasterxml.jackson.databind.JsonNode; +import com.github.victools.jsonschema.generator.Option; +import com.github.victools.jsonschema.generator.OptionPreset; +import com.github.victools.jsonschema.generator.SchemaGenerator; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfig; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder; +import com.github.victools.jsonschema.generator.SchemaVersion; + +import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class AdvancedConfigurationSchemaGenerator { + public static void main(String[] args) { + + SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2020_12, OptionPreset.PLAIN_JSON); + + configBuilder.forFields().withInstanceAttributeOverride((node, field, context) -> node.put("readOnly", field.getDeclaredType().isInstanceOf(UUID.class))); + + configBuilder.forFields() + .withTargetTypeOverridesResolver(field -> Optional.ofNullable(field.getAnnotationConsideringFieldAndGetterIfSupported(AllowedTypes.class)) + .map(AllowedTypes::value) + .map(Stream::of) + .map(stream -> stream.map(subtype -> field.getContext().resolve(subtype))) + .map(stream -> stream.collect(Collectors.toList())) + .orElse(null)); + + SchemaGeneratorConfig config = configBuilder.with(Option.EXTRA_OPEN_API_FORMAT_VALUES).build(); + + SchemaGenerator generator = new SchemaGenerator(config); + JsonNode jsonSchema = generator.generateSchema(AdvancedArticle.class); + + System.out.println(jsonSchema.toPrettyString()); + } + +} diff --git a/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/configuration/AllowedTypes.java b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/configuration/AllowedTypes.java new file mode 100644 index 0000000000..9c2ae2780d --- /dev/null +++ b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/configuration/AllowedTypes.java @@ -0,0 +1,13 @@ +package com.baeldung.jsonschemageneration.configuration; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface AllowedTypes { + Class[] value(); +} + diff --git a/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/configuration/IndividualConfigurationSchemaGenerator.java b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/configuration/IndividualConfigurationSchemaGenerator.java new file mode 100644 index 0000000000..3e1b556311 --- /dev/null +++ b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/configuration/IndividualConfigurationSchemaGenerator.java @@ -0,0 +1,44 @@ +package com.baeldung.jsonschemageneration.configuration; + +import com.baeldung.jsonschemageneration.recursive.Author; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.victools.jsonschema.generator.Option; +import com.github.victools.jsonschema.generator.OptionPreset; +import com.github.victools.jsonschema.generator.SchemaGenerator; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfig; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder; +import com.github.victools.jsonschema.generator.SchemaVersion; + +import javax.annotation.Nullable; +import javax.validation.constraints.NotNull; +import java.time.Instant; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class IndividualConfigurationSchemaGenerator { + public static void main(String[] args) { + + SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2020_12, OptionPreset.PLAIN_JSON); + + configBuilder.forFields().withRequiredCheck(field -> field.getAnnotationConsideringFieldAndGetter(Nullable.class) == null).withArrayUniqueItemsResolver(scope -> scope.getType().getErasedType() == (List.class) ? true : null); + + configBuilder.forMethods().withRequiredCheck(method -> method.getAnnotationConsideringFieldAndGetter(NotNull.class) != null); + + configBuilder.forTypesInGeneral() + .withArrayUniqueItemsResolver(scope -> scope.getType().getErasedType() == (List.class) ? true : null) + .withDefaultResolver(scope -> scope.getType().getErasedType() == List.class ? Collections.EMPTY_LIST : null) + .withDefaultResolver(scope -> scope.getType().getErasedType() == Date.class ? Date.from(Instant.now()) : null) + .withEnumResolver(scope -> scope.getType().getErasedType().isEnum() ? Stream.of(scope.getType().getErasedType().getEnumConstants()).map(v -> ((Enum) v).name()).collect(Collectors.toList()) : null); + + SchemaGeneratorConfig config = configBuilder.with(Option.EXTRA_OPEN_API_FORMAT_VALUES).build(); + + SchemaGenerator generator = new SchemaGenerator(config); + JsonNode jsonSchema = generator.generateSchema(Author.class); + + System.out.println(jsonSchema.toPrettyString()); + } + +} diff --git a/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/modules/JacksonModuleSchemaGenerator.java b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/modules/JacksonModuleSchemaGenerator.java new file mode 100644 index 0000000000..eda5015400 --- /dev/null +++ b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/modules/JacksonModuleSchemaGenerator.java @@ -0,0 +1,68 @@ +package com.baeldung.jsonschemageneration.modules; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.JsonNode; +import com.github.victools.jsonschema.generator.SchemaGenerator; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder; +import com.github.victools.jsonschema.module.jackson.JacksonModule; + +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import static com.github.victools.jsonschema.generator.Option.EXTRA_OPEN_API_FORMAT_VALUES; +import static com.github.victools.jsonschema.generator.OptionPreset.PLAIN_JSON; +import static com.github.victools.jsonschema.generator.SchemaVersion.DRAFT_2020_12; +import static com.github.victools.jsonschema.module.jackson.JacksonOption.RESPECT_JSONPROPERTY_REQUIRED; + +public class JacksonModuleSchemaGenerator { + public static void main(String[] args) { + + JacksonModule module = new JacksonModule(RESPECT_JSONPROPERTY_REQUIRED); + SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(DRAFT_2020_12, PLAIN_JSON).with(module).with(EXTRA_OPEN_API_FORMAT_VALUES); + + SchemaGenerator generator = new SchemaGenerator(configBuilder.build()); + JsonNode jsonSchema = generator.generateSchema(Person.class); + + System.out.println(jsonSchema.toPrettyString()); + } + + static class Person { + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + UUID id; + + @JsonProperty(access = JsonProperty.Access.READ_WRITE, required = true) + String name; + + @JsonProperty(access = JsonProperty.Access.READ_WRITE, required = true) + String surname; + + @JsonProperty(access = JsonProperty.Access.READ_WRITE, required = true) + Address address; + + @JsonIgnore + String fullName; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + Date createdAt; + + @JsonProperty(access = JsonProperty.Access.READ_WRITE) + List friends; + + } + + static class Address { + + @JsonProperty() + String street; + + @JsonProperty(required = true) + String city; + + @JsonProperty(required = true) + String country; + } + +} diff --git a/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/modules/JakartaValidationModuleSchemaGenerator.java b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/modules/JakartaValidationModuleSchemaGenerator.java new file mode 100644 index 0000000000..ca19d35357 --- /dev/null +++ b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/modules/JakartaValidationModuleSchemaGenerator.java @@ -0,0 +1,63 @@ +package com.baeldung.jsonschemageneration.modules; + +import com.fasterxml.jackson.databind.JsonNode; +import com.github.victools.jsonschema.generator.SchemaGenerator; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder; +import com.github.victools.jsonschema.module.jakarta.validation.JakartaValidationModule; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Null; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; + +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import static com.github.victools.jsonschema.generator.OptionPreset.PLAIN_JSON; +import static com.github.victools.jsonschema.generator.SchemaVersion.DRAFT_2020_12; +import static com.github.victools.jsonschema.module.jakarta.validation.JakartaValidationOption.INCLUDE_PATTERN_EXPRESSIONS; +import static com.github.victools.jsonschema.module.jakarta.validation.JakartaValidationOption.NOT_NULLABLE_FIELD_IS_REQUIRED; + +public class JakartaValidationModuleSchemaGenerator { + public static void main(String[] args) { + + JakartaValidationModule module = new JakartaValidationModule(NOT_NULLABLE_FIELD_IS_REQUIRED, INCLUDE_PATTERN_EXPRESSIONS); + SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(DRAFT_2020_12, PLAIN_JSON).with(module); + + SchemaGenerator generator = new SchemaGenerator(configBuilder.build()); + JsonNode jsonSchema = generator.generateSchema(Person.class); + + System.out.println(jsonSchema.toPrettyString()); + } + + static class Person { + + @NotNull UUID id; + + @NotNull String name; + + @NotNull @Email @Pattern(regexp = "\\b[A-Za-z0-9._%+-]+@baeldung\\.com\\b") String email; + + @NotNull String surname; + + @NotNull Address address; + + @Null String fullName; + + @NotNull Date createdAt; + + @Size(max = 10) List friends; + + } + + static class Address { + + @Null String street; + + @NotNull String city; + + @NotNull String country; + } + +} diff --git a/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/plugin/Person.java b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/plugin/Person.java new file mode 100644 index 0000000000..f87dcd5981 --- /dev/null +++ b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/plugin/Person.java @@ -0,0 +1,61 @@ +package com.baeldung.jsonschemageneration.plugin; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Null; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; + +import java.util.Date; +import java.util.List; +import java.util.UUID; + +public class Person { + + @NotNull + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + UUID id; + + @NotNull + @JsonProperty(access = JsonProperty.Access.READ_WRITE, required = true) + String name; + + @NotNull + @JsonProperty(access = JsonProperty.Access.READ_WRITE, required = true) + @Email @Pattern(regexp = "\\b[A-Za-z0-9._%+-]+@baeldung\\.com\\b") String email; + + @NotNull + @JsonProperty(access = JsonProperty.Access.READ_WRITE, required = true) + + String surname; + + @NotNull + @JsonProperty(access = JsonProperty.Access.READ_WRITE, required = true) + Address address; + + @Null String fullName; + + @JsonProperty(access = JsonProperty.Access.READ_ONLY) + Date createdAt; + + @Size(max = 10) + @JsonProperty(access = JsonProperty.Access.READ_WRITE) + List friends; + +} + +class Address { + + @Null + @JsonProperty + String street; + + @NotNull + @JsonProperty(required = true) + String city; + + @NotNull + @JsonProperty(required = true) + String country; +} \ No newline at end of file diff --git a/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/recursive/Author.java b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/recursive/Author.java new file mode 100644 index 0000000000..a19afb3f6f --- /dev/null +++ b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/recursive/Author.java @@ -0,0 +1,12 @@ +package com.baeldung.jsonschemageneration.recursive; + +import java.util.List; +import java.util.UUID; + +public class Author { + private UUID id; + private String name; + private String role; + + private List articles; +} diff --git a/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/recursive/AuthoredArticle.java b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/recursive/AuthoredArticle.java new file mode 100644 index 0000000000..3ab7464aaf --- /dev/null +++ b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/recursive/AuthoredArticle.java @@ -0,0 +1,68 @@ +package com.baeldung.jsonschemageneration.recursive; + +import java.util.Date; +import java.util.UUID; + +enum Area { + JAVA("JAVA"), KOTLIN("KOTLIN"), SCALA("SCALA"), LINUX("LINUX"); + + private final String area; + + Area(String area) { + this.area = area; + } + + public String getArea() { + return area; + } +} + +public class AuthoredArticle { + private UUID id; + private String title; + private String content; + private Date createdAt; + private Area area; + + private Author author; + + public Area getArea() { + return area; + } + + public void setArea(Area area) { + this.area = area; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} diff --git a/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/recursive/RecursiveSchemaGenerator.java b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/recursive/RecursiveSchemaGenerator.java new file mode 100644 index 0000000000..2047dac53f --- /dev/null +++ b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/recursive/RecursiveSchemaGenerator.java @@ -0,0 +1,23 @@ +package com.baeldung.jsonschemageneration.recursive; + +import com.fasterxml.jackson.databind.JsonNode; +import com.github.victools.jsonschema.generator.Option; +import com.github.victools.jsonschema.generator.OptionPreset; +import com.github.victools.jsonschema.generator.SchemaGenerator; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfig; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder; +import com.github.victools.jsonschema.generator.SchemaVersion; + +public class RecursiveSchemaGenerator { + public static void main(String[] args) { + + SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2020_12, OptionPreset.PLAIN_JSON); + SchemaGeneratorConfig config = configBuilder.with(Option.EXTRA_OPEN_API_FORMAT_VALUES).without(Option.FLATTENED_ENUMS_FROM_TOSTRING).build(); + + SchemaGenerator generator = new SchemaGenerator(config); + JsonNode jsonSchema = generator.generateSchema(AuthoredArticle.class); + + System.out.println(jsonSchema.toPrettyString()); + } + +} diff --git a/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/simple/Article.java b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/simple/Article.java new file mode 100644 index 0000000000..480dc2e425 --- /dev/null +++ b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/simple/Article.java @@ -0,0 +1,66 @@ +package com.baeldung.jsonschemageneration.simple; + +import java.util.Date; +import java.util.UUID; + +enum Area { + JAVA("JAVA"), KOTLIN("KOTLIN"), SCALA("SCALA"), LINUX("LINUX"); + + private final String area; + + Area(String area) { + this.area = area; + } + + public String getArea() { + return area; + } +} + +public class Article { + private UUID id; + private String title; + private String content; + private Date createdAt; + private Area area; + + public Area getArea() { + return area; + } + + public void setArea(Area area) { + this.area = area; + } + + public Date getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} diff --git a/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/simple/SimpleSchemaGenerator.java b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/simple/SimpleSchemaGenerator.java new file mode 100644 index 0000000000..daea643b1b --- /dev/null +++ b/json-modules/json-2/src/main/java/com/baeldung/jsonschemageneration/simple/SimpleSchemaGenerator.java @@ -0,0 +1,23 @@ +package com.baeldung.jsonschemageneration.simple; + +import com.fasterxml.jackson.databind.JsonNode; +import com.github.victools.jsonschema.generator.Option; +import com.github.victools.jsonschema.generator.OptionPreset; +import com.github.victools.jsonschema.generator.SchemaGenerator; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfig; +import com.github.victools.jsonschema.generator.SchemaGeneratorConfigBuilder; +import com.github.victools.jsonschema.generator.SchemaVersion; + +public class SimpleSchemaGenerator { + public static void main(String[] args) { + + SchemaGeneratorConfigBuilder configBuilder = new SchemaGeneratorConfigBuilder(SchemaVersion.DRAFT_2020_12, OptionPreset.PLAIN_JSON); + SchemaGeneratorConfig config = configBuilder.with(Option.EXTRA_OPEN_API_FORMAT_VALUES).without(Option.FLATTENED_ENUMS_FROM_TOSTRING).build(); + + SchemaGenerator generator = new SchemaGenerator(config); + JsonNode jsonSchema = generator.generateSchema(Article.class); + + System.out.println(jsonSchema.toPrettyString()); + } + +} diff --git a/json-modules/json-2/src/main/resources/schemas/com/baeldung/jsonschemageneration/plugin/Person.json b/json-modules/json-2/src/main/resources/schemas/com/baeldung/jsonschemageneration/plugin/Person.json new file mode 100644 index 0000000000..d52a527684 --- /dev/null +++ b/json-modules/json-2/src/main/resources/schemas/com/baeldung/jsonschemageneration/plugin/Person.json @@ -0,0 +1,54 @@ +{ + "$defs" : { + "Address" : { + "type" : "object", + "properties" : { + "city" : { + "type" : "string" + }, + "country" : { + "type" : "string" + }, + "street" : { + "type" : [ "string", "null" ] + } + }, + "required" : [ "city", "country" ], + "additionalProperties" : false + } + }, + "type" : "object", + "properties" : { + "address" : { + "$ref" : "#/$defs/Address" + }, + "createdAt" : { + "type" : "string", + "readOnly" : true + }, + "email" : { + "type" : "string", + "format" : "email", + "pattern" : "\\b[A-Za-z0-9._%+-]+@baeldung\\.com\\b" + }, + "friends" : { + "maxItems" : 10, + "type" : "array", + "items" : { + "$ref" : "#" + } + }, + "id" : { + "type" : "string", + "readOnly" : true + }, + "name" : { + "type" : "string" + }, + "surname" : { + "type" : "string" + } + }, + "required" : [ "address", "email", "id", "name", "surname" ], + "additionalProperties" : false +} \ No newline at end of file diff --git a/json-modules/json-conversion/README.md b/json-modules/json-conversion/README.md new file mode 100644 index 0000000000..86e8365c70 --- /dev/null +++ b/json-modules/json-conversion/README.md @@ -0,0 +1,6 @@ +## JSON-CONVERSIONS + +This module contains articles about JSON Conversions + +### Relevant Articles: +- [Convert JSON Array to Java List](https://www.baeldung.com/java-convert-json-array-to-list) diff --git a/json-modules/json-conversion/pom.xml b/json-modules/json-conversion/pom.xml new file mode 100644 index 0000000000..1af13cbbcb --- /dev/null +++ b/json-modules/json-conversion/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + org.baeldung + json-conversion + json-conversion + + + json-modules + com.baeldung + 1.0.0-SNAPSHOT + + + + + org.json + json + ${json.version} + + + com.google.code.gson + gson + ${gson.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + + + 20211205 + 2.10.1 + + + diff --git a/json-modules/json-conversion/src/main/java/com/baeldung/jsonarraytolist/ConvertJsonArrayToList.java b/json-modules/json-conversion/src/main/java/com/baeldung/jsonarraytolist/ConvertJsonArrayToList.java new file mode 100644 index 0000000000..88701e1955 --- /dev/null +++ b/json-modules/json-conversion/src/main/java/com/baeldung/jsonarraytolist/ConvertJsonArrayToList.java @@ -0,0 +1,31 @@ +package com.baeldung.jsonarraytolist; + +import java.lang.reflect.Type; +import java.util.List; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; + +import entities.Product; + +public class ConvertJsonArrayToList { + + public List convertJsonArrayUsingGsonLibrary(String jsonArray) { + Gson gson = new Gson(); + + Type listType = new TypeToken>() {}.getType(); + + List gsonList = gson.fromJson(jsonArray, listType); + return gsonList; + } + + public List convertJsonArrayUsingJacksonLibrary(String jsonArray) throws JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + + List typeReferenceList = objectMapper.readValue(jsonArray, new TypeReference>() {}); + return typeReferenceList; + } +} diff --git a/json-modules/json-conversion/src/main/java/entities/Product.java b/json-modules/json-conversion/src/main/java/entities/Product.java new file mode 100644 index 0000000000..64ab5064cc --- /dev/null +++ b/json-modules/json-conversion/src/main/java/entities/Product.java @@ -0,0 +1,29 @@ +package entities; + +public class Product { + + private int id; + private String name; + private String description; + + public Product() {} + + public Product(int id, String name, String description) { + this.id = id; + this.name = name; + this.description = description; + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + +} diff --git a/json-modules/json-conversion/src/main/resources/logback.xml b/json-modules/json-conversion/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/json-modules/json-conversion/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/json-modules/json-conversion/src/test/java/com/baeldung/jsonarraytolist/ConvertJsonArrayToListUnitTest.java b/json-modules/json-conversion/src/test/java/com/baeldung/jsonarraytolist/ConvertJsonArrayToListUnitTest.java new file mode 100644 index 0000000000..d88b75f0ce --- /dev/null +++ b/json-modules/json-conversion/src/test/java/com/baeldung/jsonarraytolist/ConvertJsonArrayToListUnitTest.java @@ -0,0 +1,60 @@ +package com.baeldung.jsonarraytolist; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.gson.Gson; + +import entities.Product; + +public class ConvertJsonArrayToListUnitTest { + + private static ObjectMapper objectMapper; + private static List productList; + private ConvertJsonArrayToList obj; + + @Before + public void setup() { + obj = new ConvertJsonArrayToList(); + productList = getProducts(); + objectMapper = new ObjectMapper(); + } + + private List getProducts() { + List productList = new ArrayList<>(); + Product prod1 = new Product(1, "Icecream", "Sweet and cold"); + Product prod2 = new Product(2, "Apple", "Red and sweet"); + Product prod3 = new Product(3, "Carrot", "Good for eyes"); + productList.add(prod1); + productList.add(prod2); + productList.add(prod3); + return productList; + } + + @Test + public void whenUsingGsonLibrary_thenCompareTwoProducts() { + Gson gson = new Gson(); + String jsonArray = gson.toJson(productList); + List arrList = obj.convertJsonArrayUsingGsonLibrary(jsonArray); + Assert.assertEquals(productList.get(0).getId(), arrList.get(0).getId()); + Assert.assertEquals(productList.get(1).getDescription(), arrList.get(1).getDescription()); + Assert.assertEquals(productList.get(2).getName(), arrList.get(2).getName()); + } + + @Test + public void whenUsingJacksonLibrary_thenCompareTwoProducts() throws JsonProcessingException { + String jsonArray = objectMapper.writeValueAsString(productList); + List arrList = obj.convertJsonArrayUsingJacksonLibrary(jsonArray); + + Assert.assertEquals(productList.get(0).getId(), arrList.get(0).getId()); + Assert.assertEquals(productList.get(1).getDescription(), arrList.get(1).getDescription()); + Assert.assertEquals(productList.get(2).getName(), arrList.get(2).getName()); + } + +} diff --git a/json-modules/json-conversion/src/test/resources/.gitignore b/json-modules/json-conversion/src/test/resources/.gitignore new file mode 100644 index 0000000000..df6ca255ed --- /dev/null +++ b/json-modules/json-conversion/src/test/resources/.gitignore @@ -0,0 +1,13 @@ +*.class + +#folders# +/target +/neoDb* +/data +/src/main/webapp/WEB-INF/classes +*/META-INF/* + +# Packaged files # +*.jar +*.war +*.ear diff --git a/json-modules/json-conversion/src/test/resources/logback-test.xml b/json-modules/json-conversion/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..b64f069594 --- /dev/null +++ b/json-modules/json-conversion/src/test/resources/logback-test.xml @@ -0,0 +1,19 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + diff --git a/json-modules/pom.xml b/json-modules/pom.xml index 983618b6cb..306b404049 100644 --- a/json-modules/pom.xml +++ b/json-modules/pom.xml @@ -17,10 +17,10 @@ json json-2 json-arrays + json-conversion json-path gson gson-2 - diff --git a/kubernetes-modules/README.md b/kubernetes-modules/README.md new file mode 100644 index 0000000000..cb52c12465 --- /dev/null +++ b/kubernetes-modules/README.md @@ -0,0 +1,2 @@ +## Relevant Articles +- [Guide to Eclipse JKube](https://www.baeldung.com/ops/eclipse-jkube) diff --git a/kubernetes-modules/jkube-demo/mvnw b/kubernetes-modules/jkube-demo/mvnw new file mode 100755 index 0000000000..66df285428 --- /dev/null +++ b/kubernetes-modules/jkube-demo/mvnw @@ -0,0 +1,308 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.2.0 +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /usr/local/etc/mavenrc ] ; then + . /usr/local/etc/mavenrc + fi + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "$(uname)" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME + else + JAVA_HOME="/Library/Java/Home"; export JAVA_HOME + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=$(java-config --jre-home) + fi +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --unix "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --unix "$CLASSPATH") +fi + +# For Mingw, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] && + JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)" +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="$(which javac)" + if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=$(which readlink) + if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then + if $darwin ; then + javaHome="$(dirname "\"$javaExecutable\"")" + javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac" + else + javaExecutable="$(readlink -f "\"$javaExecutable\"")" + fi + javaHome="$(dirname "\"$javaExecutable\"")" + javaHome=$(expr "$javaHome" : '\(.*\)/bin') + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=$(cd "$wdir/.." || exit 1; pwd) + fi + # end of workaround + done + printf '%s' "$(cd "$basedir" || exit 1; pwd)" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + # Remove \r in case we run on Windows within Git Bash + # and check out the repository with auto CRLF management + # enabled. Otherwise, we may read lines that are delimited with + # \r\n and produce $'-Xarg\r' rather than -Xarg due to word + # splitting rules. + tr -s '\r\n' ' ' < "$1" + fi +} + +log() { + if [ "$MVNW_VERBOSE" = true ]; then + printf '%s\n' "$1" + fi +} + +BASE_DIR=$(find_maven_basedir "$(dirname "$0")") +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR +log "$MAVEN_PROJECTBASEDIR" + +########################################################################################## +# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +# This allows using the maven wrapper in projects that prohibit checking in binary data. +########################################################################################## +wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" +if [ -r "$wrapperJarPath" ]; then + log "Found $wrapperJarPath" +else + log "Couldn't find $wrapperJarPath, downloading it ..." + + if [ -n "$MVNW_REPOURL" ]; then + wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + else + wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + fi + while IFS="=" read -r key value; do + # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' ) + safeValue=$(echo "$value" | tr -d '\r') + case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;; + esac + done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" + log "Downloading from: $wrapperUrl" + + if $cygwin; then + wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath") + fi + + if command -v wget > /dev/null; then + log "Found wget ... using wget" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + else + wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath" + fi + elif command -v curl > /dev/null; then + log "Found curl ... using curl" + [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent" + if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then + curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + else + curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath" + fi + else + log "Falling back to using Java to download" + javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java" + javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class" + # For Cygwin, switch paths to Windows format before running javac + if $cygwin; then + javaSource=$(cygpath --path --windows "$javaSource") + javaClass=$(cygpath --path --windows "$javaClass") + fi + if [ -e "$javaSource" ]; then + if [ ! -e "$javaClass" ]; then + log " - Compiling MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/javac" "$javaSource") + fi + if [ -e "$javaClass" ]; then + log " - Running MavenWrapperDownloader.java ..." + ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath" + fi + fi + fi +fi +########################################################################################## +# End of extension +########################################################################################## + +# If specified, validate the SHA-256 sum of the Maven wrapper jar file +wrapperSha256Sum="" +while IFS="=" read -r key value; do + case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;; + esac +done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties" +if [ -n "$wrapperSha256Sum" ]; then + wrapperSha256Result=false + if command -v sha256sum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + elif command -v shasum > /dev/null; then + if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then + wrapperSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." + echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties." + exit 1 + fi + if [ $wrapperSha256Result = false ]; then + echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2 + echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2 + echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2 + exit 1 + fi +fi + +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$JAVA_HOME" ] && + JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME") + [ -n "$CLASSPATH" ] && + CLASSPATH=$(cygpath --path --windows "$CLASSPATH") + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR") +fi + +# Provide a "standardized" way to retrieve the CLI args that will +# work with both Windows and non-Windows executions. +MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*" +export MAVEN_CMD_LINE_ARGS + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +# shellcheck disable=SC2086 # safe args +exec "$JAVACMD" \ + $MAVEN_OPTS \ + $MAVEN_DEBUG_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/kubernetes-modules/jkube-demo/mvnw.cmd b/kubernetes-modules/jkube-demo/mvnw.cmd new file mode 100644 index 0000000000..95ba6f54ac --- /dev/null +++ b/kubernetes-modules/jkube-demo/mvnw.cmd @@ -0,0 +1,205 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM https://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.2.0 +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM set title of command window +title %0 +@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %* +if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %* +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B +) + +@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central +@REM This allows using the maven wrapper in projects that prohibit checking in binary data. +if exist %WRAPPER_JAR% ( + if "%MVNW_VERBOSE%" == "true" ( + echo Found %WRAPPER_JAR% + ) +) else ( + if not "%MVNW_REPOURL%" == "" ( + SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar" + ) + if "%MVNW_VERBOSE%" == "true" ( + echo Couldn't find %WRAPPER_JAR%, downloading it ... + echo Downloading from: %WRAPPER_URL% + ) + + powershell -Command "&{"^ + "$webclient = new-object System.Net.WebClient;"^ + "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ + "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ + "}"^ + "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^ + "}" + if "%MVNW_VERBOSE%" == "true" ( + echo Finished downloading %WRAPPER_JAR% + ) +) +@REM End of extension + +@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file +SET WRAPPER_SHA_256_SUM="" +FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( + IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B +) +IF NOT %WRAPPER_SHA_256_SUM%=="" ( + powershell -Command "&{"^ + "$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^ + "If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^ + " Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^ + " Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^ + " Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^ + " exit 1;"^ + "}"^ + "}" + if ERRORLEVEL 1 goto error +) + +@REM Provide a "standardized" way to retrieve the CLI args that will +@REM work with both Windows and non-Windows executions. +set MAVEN_CMD_LINE_ARGS=%* + +%MAVEN_JAVA_EXE% ^ + %JVM_CONFIG_MAVEN_PROPS% ^ + %MAVEN_OPTS% ^ + %MAVEN_DEBUG_OPTS% ^ + -classpath %WRAPPER_JAR% ^ + "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^ + %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat" +if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%"=="on" pause + +if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE% + +cmd /C exit /B %ERROR_CODE% diff --git a/kubernetes-modules/jkube-demo/pom.xml b/kubernetes-modules/jkube-demo/pom.xml new file mode 100644 index 0000000000..7bb662c4a3 --- /dev/null +++ b/kubernetes-modules/jkube-demo/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + com.baeldung + jkube-demo + 0.0.1-SNAPSHOT + jkube-demo + jkube-demo + + + org.springframework.boot + spring-boot-starter + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + org.eclipse.jkube + kubernetes-maven-plugin + 1.13.1 + + + + + diff --git a/kubernetes-modules/jkube-demo/src/main/java/com/example/jkubedemo/JkubeDemoApplication.java b/kubernetes-modules/jkube-demo/src/main/java/com/example/jkubedemo/JkubeDemoApplication.java new file mode 100644 index 0000000000..c702def257 --- /dev/null +++ b/kubernetes-modules/jkube-demo/src/main/java/com/example/jkubedemo/JkubeDemoApplication.java @@ -0,0 +1,14 @@ +package com.example.jkubedemo; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class JkubeDemoApplication { + + public static void main(String[] args) { + SpringApplication.run(JkubeDemoApplication.class, args); + System.out.println("Hello from JKube Demo"); + } + +} diff --git a/kubernetes-modules/jkube-demo/src/main/resources/application.properties b/kubernetes-modules/jkube-demo/src/main/resources/application.properties new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/kubernetes-modules/jkube-demo/src/main/resources/application.properties @@ -0,0 +1 @@ + diff --git a/kubernetes-modules/pom.xml b/kubernetes-modules/pom.xml index 5b6510e58b..ffe9c42472 100644 --- a/kubernetes-modules/pom.xml +++ b/kubernetes-modules/pom.xml @@ -13,9 +13,10 @@ + jkube-demo k8s-intro k8s-admission-controller kubernetes-spring - \ No newline at end of file + diff --git a/libraries-data-2/pom.xml b/libraries-data-2/pom.xml index b9b785cebb..e19067daa3 100644 --- a/libraries-data-2/pom.xml +++ b/libraries-data-2/pom.xml @@ -86,11 +86,13 @@ spring-web ${spring.version} + org.derive4j derive4j @@ -160,7 +162,8 @@ - + + 1.16.1 diff --git a/libraries-data-2/src/main/java/com/baeldung/suanshu/SuanShuMath.java b/libraries-data-2/src/main/java/com/baeldung/suanshu/SuanShuMath.java index ce7bc60a3a..a5365871c6 100644 --- a/libraries-data-2/src/main/java/com/baeldung/suanshu/SuanShuMath.java +++ b/libraries-data-2/src/main/java/com/baeldung/suanshu/SuanShuMath.java @@ -1,5 +1,6 @@ package com.baeldung.suanshu; +/* import com.numericalmethod.suanshu.algebra.linear.matrix.doubles.Matrix; import com.numericalmethod.suanshu.algebra.linear.matrix.doubles.matrixtype.dense.DenseMatrix; import com.numericalmethod.suanshu.algebra.linear.matrix.doubles.operation.Inverse; @@ -9,13 +10,14 @@ import com.numericalmethod.suanshu.analysis.function.polynomial.Polynomial; import com.numericalmethod.suanshu.analysis.function.polynomial.root.PolyRoot; import com.numericalmethod.suanshu.analysis.function.polynomial.root.PolyRootSolver; import com.numericalmethod.suanshu.number.complex.Complex; +*/ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; class SuanShuMath { - +/** fixing in JAVA-24004 private static final Logger log = LoggerFactory.getLogger(SuanShuMath.class); public static void main(String[] args) throws Exception { @@ -137,5 +139,5 @@ class SuanShuMath { List roots = solver.solve(p); log.info("Finding polynomial roots: {}", roots); } - +*/ } diff --git a/linux-bash-modules/linux-bash-text/README.md b/linux-bash-modules/linux-bash-text/README.md index 5423ddf916..7d843af9ea 100644 --- a/linux-bash-modules/linux-bash-text/README.md +++ b/linux-bash-modules/linux-bash-text/README.md @@ -1,3 +1 @@ ### Relevant Articles: - -- [Linux Commands for Appending Multiple Lines to a File](https://www.baeldung.com/linux/appending-multiple-lines-to-file2) diff --git a/logging-modules/logback/src/main/java/com/baeldung/parameterized/logging/README.md b/logging-modules/logback/src/main/java/com/baeldung/parameterized/logging/README.md new file mode 100644 index 0000000000..fd38f41082 --- /dev/null +++ b/logging-modules/logback/src/main/java/com/baeldung/parameterized/logging/README.md @@ -0,0 +1,2 @@ +## Relevant Articles +- [Parameterized Logging With SLF4J](https://www.baeldung.com/slf4j-parameterized-logging) diff --git a/lombok-modules/lombok-2/pom.xml b/lombok-modules/lombok-2/pom.xml index 88fbaf530f..ea562ad896 100644 --- a/lombok-modules/lombok-2/pom.xml +++ b/lombok-modules/lombok-2/pom.xml @@ -25,10 +25,58 @@ jackson-databind ${jackson.version} + + com.google.code.gson + gson + ${gson.version} + + + javax.annotation + javax.annotation-api + ${javax.annotation} + + + io.swagger + swagger-annotations + ${swagger.annotation} + org.springframework.boot spring-boot-starter-web + + + + org.openapitools + openapi-generator-maven-plugin + ${openapi.version} + + + + generate + + + ${project.basedir}/src/main/resources/bookapi.yml + java + com.baeldung.openapi.model + + @lombok.Data @lombok.NoArgsConstructor @lombok.AllArgsConstructor + + false + false + false + + + + + + + + 4.2.3 + 2.10.1 + 1.3.2 + 1.6.2 + \ No newline at end of file diff --git a/lombok-modules/lombok-2/src/main/java/com/baeldung/lombok/openapiandlombook/Book.java b/lombok-modules/lombok-2/src/main/java/com/baeldung/lombok/openapiandlombook/Book.java new file mode 100644 index 0000000000..2da2e74a40 --- /dev/null +++ b/lombok-modules/lombok-2/src/main/java/com/baeldung/lombok/openapiandlombook/Book.java @@ -0,0 +1,12 @@ +package com.baeldung.lombok.openapiandlombook; + +@lombok.Data +@lombok.NoArgsConstructor +@lombok.AllArgsConstructor +public class Book { + + private Long id; + private String name; + private String author; + +} diff --git a/lombok-modules/lombok-2/src/main/resources/bookapi.yml b/lombok-modules/lombok-2/src/main/resources/bookapi.yml new file mode 100644 index 0000000000..e9b63b2f85 --- /dev/null +++ b/lombok-modules/lombok-2/src/main/resources/bookapi.yml @@ -0,0 +1,39 @@ +openapi: 3.0.2 +info: + version: 1.0.0 + title: Book Store + license: + name: MIT +paths: + /books: + get: + tags: + - book + summary: Get All Books + responses: + 200: + description: successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/Book' + + 404: + description: Book not found + content: { } +components: + schemas: + Book: + type: object + required: + - id + - name + - author + properties: + id: + type: integer + format: int64 + name: + type: string + author: + type: string diff --git a/lombok-modules/lombok/pom.xml b/lombok-modules/lombok/pom.xml index 6ba90f33b5..a04233bc2b 100644 --- a/lombok-modules/lombok/pom.xml +++ b/lombok-modules/lombok/pom.xml @@ -43,7 +43,6 @@ - edge-SNAPSHOT 1.0.0.Final 1.18.20.0 23.0.0 diff --git a/maven-modules/maven-build-optimization/.mvn/jvm.config.txt b/maven-modules/maven-build-optimization/.mvn/jvm.config.txt new file mode 100644 index 0000000000..37dd0076c2 --- /dev/null +++ b/maven-modules/maven-build-optimization/.mvn/jvm.config.txt @@ -0,0 +1 @@ +-XX:-TieredCompilation -XX:TieredStopAtLevel=1 \ No newline at end of file diff --git a/maven-modules/maven-build-optimization/.profiler/profiler-report-2023-08-05-19-34-46.html b/maven-modules/maven-build-optimization/.profiler/profiler-report-2023-08-05-19-34-46.html new file mode 100644 index 0000000000..807679bbf6 --- /dev/null +++ b/maven-modules/maven-build-optimization/.profiler/profiler-report-2023-08-05-19-34-46.html @@ -0,0 +1,2542 @@ + + + + + Maven Profiler Report + + + +
+

maven-build-optimization (21,91 s)

+

Run clean install on 2023/08/05 19:34:46 with parameters: {}

+ + +
+

maven-build-optimization (18,81 s)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Plugin executionDuration
org.apache.maven.plugins:maven-pmd-plugin:3.19.0:pmd {execution: pmd}10,45 s
org.commonjava.maven.plugins:directory-maven-plugin:0.3.1:directory-of {execution: directories}2,108 s
org.apache.maven.plugins:maven-install-plugin:2.5.2:install-file {execution: install-jar-lib}1,982 s
org.apache.maven.plugins:maven-clean-plugin:3.2.0:clean {execution: default-clean}541,7 ms
org.apache.maven.plugins:maven-install-plugin:2.5.2:install {execution: default-install}22,76 ms
org.apache.maven.plugins:maven-pmd-plugin:3.19.0:check {execution: default}9,651 ms
+
+ + + +
+

Artifact Downloading (168,3 s)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ArtifactDuration
org.codehaus.plexus:plexus-utils:jar:3.3.01,649 s
javax.inject:javax.inject:jar:11,646 s
org.codehaus.plexus:plexus-resources:jar:1.2.01,643 s
org.apache.maven.doxia:doxia-integration-tools:jar:1.11.11,640 s
org.eclipse.sisu:org.eclipse.sisu.inject:jar:0.3.51,636 s
javax.enterprise:cdi-api:jar:1.21,634 s
javax.annotation:javax.annotation-api:jar:1.21,632 s
org.eclipse.sisu:org.eclipse.sisu.plexus:jar:0.3.51,630 s
org.apache.maven:maven-plugin-api:jar:3.1.01,627 s
org.apache.maven.reporting:maven-reporting-impl:jar:3.2.01,623 s
org.apache.maven.reporting:maven-reporting-api:jar:3.1.11,620 s
commons-collections:commons-collections:jar:3.2.21,618 s
oro:oro:jar:2.0.81,616 s
dom4j:dom4j:jar:1.11,613 s
commons-logging:commons-logging:jar:1.11,611 s
commons-chain:commons-chain:jar:1.11,607 s
commons-digester:commons-digester:jar:1.81,604 s
commons-beanutils:commons-beanutils:jar:1.7.01,602 s
org.apache.velocity:velocity-tools:jar:2.01,600 s
commons-lang:commons-lang:jar:2.41,597 s
org.apache.velocity:velocity:jar:1.71,595 s
org.codehaus.plexus:plexus-velocity:jar:1.21,592 s
org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-301,589 s
org.codehaus.plexus:plexus-i18n:jar:1.0-beta-101,586 s
org.apache.maven.doxia:doxia-module-xhtml5:jar:1.11.11,583 s
org.apache.maven.doxia:doxia-module-xhtml:jar:1.11.11,578 s
org.apache.maven.doxia:doxia-skin-model:jar:1.11.11,572 s
org.apache.httpcomponents:httpcore:jar:4.4.141,569 s
org.apache.commons:commons-text:jar:1.31,566 s
org.apache.maven.doxia:doxia-core:jar:1.11.11,563 s
org.apache.maven.doxia:doxia-site-renderer:jar:1.11.11,560 s
org.apache.maven.doxia:doxia-decoration-model:jar:1.11.11,556 s
org.apache.maven.doxia:doxia-logging-api:jar:1.11.11,553 s
org.apache.maven.doxia:doxia-sink-api:jar:1.11.11,551 s
org.slf4j:jul-to-slf4j:jar:1.7.361,549 s
org.slf4j:slf4j-api:jar:1.7.361,546 s
net.sourceforge.pmd:pmd-jsp:jar:6.49.01,543 s
org.mozilla:rhino:jar:1.7.141,540 s
net.sourceforge.pmd:pmd-javascript:jar:6.49.01,537 s
net.sourceforge.pmd:pmd-java:jar:6.49.01,535 s
net.sourceforge.saxon:saxon:jar:dom:9.1.0.81,533 s
com.google.code.gson:gson:jar:2.8.91,530 s
org.ow2.asm:asm:jar:9.31,528 s
net.sourceforge.saxon:saxon:jar:9.1.0.81,524 s
com.beust:jcommander:jar:1.481,521 s
org.antlr:antlr4-runtime:jar:4.7.21,519 s
net.sourceforge.pmd:pmd-core:jar:6.49.01,516 s
org.apache.commons:commons-lang3:jar:3.12.01,513 s
commons-io:commons-io:jar:2.11.01,511 s
org.apache.maven.shared:maven-common-artifact-filters:jar:3.3.11,508 s
org.codehaus.plexus:plexus-component-annotations:jar:2.1.11,504 s
org.apache.maven:maven-artifact:jar:3.01,501 s
org.codehaus.plexus:plexus-classworlds:jar:2.2.31,498 s
org.sonatype.sisu:sisu-guice:jar:noaop:2.1.71,495 s
org.sonatype.sisu:sisu-inject-bean:jar:1.4.21,481 s
org.sonatype.sisu:sisu-inject-plexus:jar:1.4.21,472 s
org.sonatype.aether:aether-util:jar:1.71,468 s
org.sonatype.aether:aether-api:jar:1.71,465 s
org.sonatype.aether:aether-spi:jar:1.71,462 s
org.sonatype.aether:aether-impl:jar:1.71,459 s
org.apache.maven:maven-aether-provider:jar:3.01,455 s
org.apache.maven:maven-model-builder:jar:3.01,453 s
org.apache.maven:maven-repository-metadata:jar:3.01,450 s
org.apache.maven:maven-settings-builder:jar:3.01,447 s
org.apache.maven:maven-settings:jar:3.01,444 s
org.apache.maven:maven-model:jar:3.01,441 s
org.apache.maven:maven-core:jar:3.01,437 s
org.apache.maven.shared:maven-artifact-transfer:jar:0.13.11,434 s
org.apache.maven.surefire:surefire-logger-api:jar:2.22.21,110 s
org.objenesis:objenesis:jar:3.21,107 s
net.bytebuddy:byte-buddy-agent:jar:1.12.81,104 s
net.bytebuddy:byte-buddy:jar:1.12.81,102 s
org.mockito:mockito-core:jar:4.4.01,097 s
org.hamcrest:hamcrest-all:jar:1.31,094 s
org.hamcrest:hamcrest:jar:2.21,092 s
org.assertj:assertj-core:jar:3.21.01,090 s
org.hamcrest:hamcrest-core:jar:1.31,087 s
junit:junit:jar:4.13.21,081 s
org.junit.vintage:junit-vintage-engine:jar:5.9.21,072 s
org.junit.platform:junit-platform-commons:jar:1.9.21,053 s
org.opentest4j:opentest4j:jar:1.2.01,046 s
org.junit.jupiter:junit-jupiter-api:jar:5.9.21,043 s
org.junit.jupiter:junit-jupiter-params:jar:5.9.21,041 s
org.apiguardian:apiguardian-api:jar:1.1.21,037 s
org.junit.platform:junit-platform-engine:jar:1.9.21,034 s
org.junit.jupiter:junit-jupiter-engine:jar:5.9.21,030 s
org.slf4j:jcl-over-slf4j:jar:1.7.321,027 s
ch.qos.logback:logback-core:jar:1.2.71,025 s
ch.qos.logback:logback-classic:jar:1.2.71,021 s
org.slf4j:slf4j-api:jar:1.7.321,018 s
com.vackosar.gitflowincrementalbuilder:gitflow-incremental-builder:pom:3.12.2912,3 ms
com.jcraft:jsch.agentproxy.sshagent:jar:0.0.9714,0 ms
net.java.dev.jna:jna-platform:jar:4.1.0709,2 ms
net.java.dev.jna:jna:jar:4.1.0700,3 ms
com.jcraft:jsch.agentproxy.pageant:jar:0.0.9696,9 ms
com.jcraft:jsch.agentproxy.jsch:jar:0.0.9691,3 ms
com.jcraft:jsch.agentproxy.usocket-nc:jar:0.0.9687,5 ms
com.jcraft:jsch.agentproxy.usocket-jna:jar:0.0.9681,7 ms
com.jcraft:jsch.agentproxy.core:jar:0.0.9677,3 ms
com.jcraft:jsch.agentproxy.connector-factory:jar:0.0.9673,1 ms
com.jcraft:jzlib:jar:1.1.1669,0 ms
com.jcraft:jsch:jar:0.1.55665,4 ms
org.eclipse.jgit:org.eclipse.jgit.ssh.jsch:jar:5.10.0.202012080955-r662,5 ms
com.googlecode.javaewah:JavaEWAH:jar:1.1.7659,3 ms
org.eclipse.jgit:org.eclipse.jgit:jar:5.10.0.202012080955-r656,1 ms
com.vackosar.gitflowincrementalbuilder:gitflow-incremental-builder:jar:3.12.2653,0 ms
org.apache.maven:maven-model:jar:3.0.3435,3 ms
org.apache.maven:maven-plugin-api:jar:3.0.3430,5 ms
org.sonatype.plexus:plexus-cipher:jar:1.4427,8 ms
org.sonatype.plexus:plexus-sec-dispatcher:jar:1.3424,9 ms
org.codehaus.plexus:plexus-component-annotations:jar:1.5.5421,3 ms
org.codehaus.plexus:plexus-classworlds:jar:2.4418,1 ms
org.codehaus.plexus:plexus-utils:jar:2.0.6414,4 ms
org.codehaus.plexus:plexus-interpolation:jar:1.14411,1 ms
org.sonatype.sisu:sisu-guice:jar:no_aop:2.9.4403,0 ms
org.sonatype.sisu:sisu-inject-bean:jar:2.1.1396,1 ms
org.sonatype.sisu:sisu-inject-plexus:jar:2.1.1392,9 ms
org.sonatype.aether:aether-util:jar:1.11388,1 ms
org.sonatype.aether:aether-api:jar:1.11385,0 ms
org.sonatype.aether:aether-impl:jar:1.11381,0 ms
org.sonatype.aether:aether-spi:jar:1.11377,5 ms
org.apache.maven:maven-aether-provider:jar:3.0.3374,7 ms
org.apache.maven:maven-model-builder:jar:3.0.3371,9 ms
org.apache.maven:maven-artifact:jar:3.0.3369,1 ms
org.apache.maven:maven-repository-metadata:jar:3.0.3365,9 ms
org.apache.maven:maven-settings-builder:jar:3.0.3361,7 ms
org.apache.maven:maven-settings:jar:3.0.3358,7 ms
org.apache.maven:maven-core:jar:3.0.3355,7 ms
org.codehaus.plexus:plexus-utils:jar:3.0.15320,8 ms
com.google.code.findbugs:jsr305:jar:2.0.1312,4 ms
org.apache.maven.shared:maven-shared-utils:jar:0.4309,8 ms
commons-codec:commons-codec:jar:1.6307,2 ms
org.apache.maven:maven-artifact:jar:2.2.1304,6 ms
backport-util-concurrent:backport-util-concurrent:jar:3.1302,0 ms
org.apache.maven:maven-repository-metadata:jar:2.2.1298,3 ms
org.apache.maven:maven-artifact-manager:jar:2.2.1294,0 ms
org.apache.maven:maven-model:jar:2.2.1291,5 ms
classworlds:classworlds:jar:1.1-alpha-2288,9 ms
junit:junit:jar:3.8.1286,4 ms
org.codehaus.plexus:plexus-container-default:jar:1.0-alpha-9-stable-1282,9 ms
org.codehaus.plexus:plexus-interpolation:jar:1.11278,9 ms
org.apache.maven:maven-plugin-registry:jar:2.2.1276,5 ms
org.apache.maven:maven-profile:jar:2.2.1273,8 ms
org.apache.maven:maven-settings:jar:2.2.1271,4 ms
org.apache.maven:maven-project:jar:2.2.1268,8 ms
org.apache.maven:maven-plugin-api:jar:2.2.1265,4 ms
commons-io:commons-io:jar:2.6111,6 ms
org.apache.maven.shared:maven-shared-utils:jar:3.3.4109,0 ms
org.apache.velocity:velocity:pom:1.6.297,59 ms
commons-collections:commons-collections:pom:3.2.284,54 ms
org.apache:apache:pom:576,39 ms
org.eclipse.aether:aether-impl:pom:0.9.0.M277,00 ms
org.eclipse.sisu:org.eclipse.sisu.inject:pom:0.3.572,70 ms
org.eclipse.aether:aether-util:pom:0.9.0.M271,60 ms
org.codehaus.plexus:plexus-container-default:pom:1.0-alpha-3070,94 ms
org.codehaus.plexus:plexus-utils:pom:2.0.669,83 ms
org.mozilla:rhino:pom:1.7.1468,12 ms
org.eclipse.jgit:org.eclipse.jgit-parent:pom:5.10.0.202012080955-r67,22 ms
org.codehaus.plexus:plexus:pom:2.0.767,22 ms
oro:oro:pom:2.0.866,76 ms
org.slf4j:slf4j-api:pom:1.7.3262,58 ms
commons-collections:commons-collections:pom:2.062,45 ms
org.eclipse.jgit:org.eclipse.jgit.ssh.jsch:pom:5.10.0.202012080955-r61,11 ms
org.sonatype.aether:aether-impl:pom:1.1161,37 ms
org.codehaus.plexus:plexus-container-default:pom:1.0-alpha-9-stable-161,22 ms
com.google.code.findbugs:jsr305:pom:2.0.160,24 ms
com.jcraft:jsch:pom:0.1.4959,02 ms
org.codehaus.plexus:plexus-classworlds:pom:1.2-alpha-958,04 ms
ch.qos.logback:logback-classic:pom:1.2.757,91 ms
org.sonatype.sisu:sisu-guice:pom:2.1.757,63 ms
commons-io:commons-io:pom:2.557,02 ms
commons-beanutils:commons-beanutils:pom:1.657,12 ms
javax.inject:javax.inject:pom:157,82 ms
com.jcraft:jzlib:pom:1.1.156,09 ms
org.jboss.weld:weld-parent:pom:2656,42 ms
org.apache.maven:maven:pom:2.2.155,59 ms
org.apache.maven:maven-project:pom:2.2.155,15 ms
org.slf4j:slf4j-parent:pom:1.7.3255,55 ms
ch.qos.logback:logback-core:pom:1.2.755,62 ms
org.junit.jupiter:junit-jupiter-params:pom:5.9.255,39 ms
org.apache.maven:maven-plugin-api:pom:3.055,91 ms
org.sonatype.oss:oss-parent:pom:355,16 ms
org.apache.maven:maven:pom:3.1.055,12 ms
org.apache:apache:pom:1453,84 ms
org.assertj:assertj-core:pom:3.21.053,16 ms
org.apache.maven.doxia:doxia-logging-api:pom:1.11.153,83 ms
commons-codec:commons-codec:pom:1.652,94 ms
org.apache:apache:pom:1352,42 ms
ch.qos.logback:logback-parent:pom:1.2.752,44 ms
net.sourceforge.pmd:pmd-javascript:pom:6.49.052,50 ms
org.apache.maven:maven-model:pom:3.1.052,30 ms
org.apache.maven:maven-settings:pom:3.1.052,33 ms
com.jcraft:jsch.agentproxy.core:pom:0.0.951,97 ms
org.apache.maven:maven-parent:pom:3551,64 ms
org.apache:apache:pom:651,83 ms
org.codehaus.plexus:plexus-utils:pom:3.3.051,78 ms
org.sonatype.aether:aether-api:pom:1.751,32 ms
org.apache.velocity:velocity:pom:1.751,33 ms
org.apache.maven.shared:maven-artifact-transfer:pom:0.13.150,31 ms
org.junit:junit-bom:pom:5.7.150,17 ms
org.apache.httpcomponents:httpcore:pom:4.4.1450,00 ms
xml-apis:xml-apis:pom:1.0.b250,17 ms
org.apache.maven.reporting:maven-reporting-impl:pom:3.2.050,00 ms
org.apache.maven:maven-core:pom:3.1.050,88 ms
org.apache.maven:maven-core:pom:3.0.348,45 ms
org.apache.maven:maven-parent:pom:3648,84 ms
org.apache.commons:commons-parent:pom:4748,48 ms
net.sourceforge.pmd:pmd-java:pom:6.49.048,23 ms
org.apache.maven.doxia:doxia-core:pom:1.11.148,46 ms
commons-chain:commons-chain:pom:1.148,33 ms
org.eclipse.jgit:org.eclipse.jgit:pom:5.10.0.202012080955-r47,77 ms
com.googlecode.javaewah:JavaEWAH:pom:1.1.747,41 ms
com.jcraft:jsch:pom:0.1.5547,14 ms
org.apache.maven.plugins:maven-clean-plugin:pom:3.2.047,30 ms
org.apache:apache:pom:2547,29 ms
org.apache.maven:maven-profile:pom:2.2.147,30 ms
org.apache.maven:maven-artifact:pom:3.047,23 ms
org.commonjava.maven.plugins:directory-maven-plugin:pom:0.3.146,74 ms
org.apache.maven.plugins:maven-pmd-plugin:jar:3.19.046,85 ms
org.sonatype.sisu:sisu-parent:pom:2.1.146,14 ms
org.apache.maven.doxia:doxia-site-renderer:pom:1.11.146,37 ms
org.apache.httpcomponents:httpcomponents-parent:pom:1146,78 ms
log4j:log4j:pom:1.2.1246,66 ms
commons-digester:commons-digester:pom:1.646,89 ms
org.sonatype.oss:oss-parent:pom:645,87 ms
org.apache.maven:maven-parent:pom:1545,51 ms
org.apache.maven.plugins:maven-install-plugin:pom:2.5.245,87 ms
org.apache.maven:maven-settings-builder:pom:3.0.345,01 ms
org.sonatype.sisu:sisu-inject-bean:pom:2.1.145,81 ms
org.hamcrest:hamcrest-core:pom:1.345,43 ms
org.hamcrest:hamcrest:pom:2.245,94 ms
net.bytebuddy:byte-buddy-agent:pom:1.12.845,38 ms
org.codehaus.plexus:plexus-classworlds:pom:2.2.345,57 ms
net.sourceforge.pmd:pmd:pom:6.49.045,12 ms
org.sonatype.oss:oss-parent:pom:945,17 ms
com.beust:jcommander:pom:1.4845,36 ms
org.apache.maven.doxia:doxia-skin-model:pom:1.11.145,26 ms
avalon-framework:avalon-framework:pom:4.1.345,37 ms
org.apache.commons:commons-parent:pom:4244,20 ms
org.apache.maven:maven-settings:pom:3.0.344,16 ms
org.apache.maven:maven-model:pom:2.2.144,03 ms
org.codehaus.plexus:plexus:pom:6.544,63 ms
org.apache.commons:commons-parent:pom:3944,23 ms
org.slf4j:slf4j-parent:pom:1.7.3644,75 ms
org.ow2.asm:asm:pom:9.344,39 ms
logkit:logkit:pom:1.0.144,09 ms
org.apache.maven.reporting:maven-reporting-api:pom:3.1.144,16 ms
org.apache.maven.shared:maven-shared-components:pom:1544,84 ms
com.jcraft:jsch.agentproxy:pom:0.0.943,31 ms
net.java.dev.jna:jna-platform:pom:4.1.043,11 ms
org.commonjava.maven.plugins:directory-maven-plugin:jar:0.3.143,95 ms
org.apache.maven.plugins:maven-install-plugin:jar:2.5.243,19 ms
org.apache.maven.shared:maven-shared-components:pom:3443,48 ms
org.sonatype.forge:forge-parent:pom:743,50 ms
org.apache.maven:maven-model-builder:pom:3.0.343,32 ms
org.codehaus.plexus:plexus-containers:pom:1.0.343,70 ms
org.junit.jupiter:junit-jupiter-engine:pom:5.9.243,63 ms
net.bytebuddy:byte-buddy-parent:pom:1.12.843,82 ms
org.apache:apache:pom:2143,91 ms
org.apache.httpcomponents:httpcomponents-core:pom:4.4.1443,69 ms
org.apache.maven.doxia:doxia-modules:pom:1.11.143,31 ms
org.codehaus.plexus:plexus-components:pom:1.1.1243,70 ms
commons-collections:commons-collections:pom:3.143,62 ms
org.apache.velocity:velocity-tools:pom:2.043,88 ms
commons-collections:commons-collections:pom:3.243,92 ms
org.eclipse.sisu:sisu-inject:pom:0.3.543,24 ms
org.apache.maven:maven-model-builder:pom:3.1.043,18 ms
org.apache.httpcomponents:httpclient:pom:4.5.1343,56 ms
org.apache.maven.doxia:doxia-integration-tools:pom:1.11.143,28 ms
org.sonatype.oss:oss-parent:pom:542,01 ms
org.apache.maven.plugins:maven-plugins:pom:3542,47 ms
org.apache.maven.plugins:maven-clean-plugin:jar:3.2.042,26 ms
org.apache.maven.plugins:maven-plugins:pom:3742,31 ms
commons-io:commons-io:pom:2.642,61 ms
org.sonatype.sisu.inject:guice-plexus:pom:2.1.142,22 ms
org.sonatype.aether:aether-util:pom:1.1142,96 ms
org.codehaus.plexus:plexus:pom:2.0.242,03 ms
org.apache.maven:maven-parent:pom:2342,40 ms
org.junit:junit-bom:pom:5.8.042,55 ms
org.objenesis:objenesis-parent:pom:3.242,08 ms
org.sonatype.sisu:sisu-inject-bean:pom:1.4.242,36 ms
org.apache.maven:maven-model-builder:pom:3.042,71 ms
org.codehaus.plexus:plexus-container-default:pom:2.1.042,77 ms
org.apache.commons:commons-text:pom:1.342,56 ms
org.apache.commons:commons-parent:pom:4542,72 ms
org.codehaus.plexus:plexus-interpolation:pom:1.1642,98 ms
org.codehaus.plexus:plexus:pom:3.342,67 ms
com.jcraft:jsch.agentproxy.pageant:pom:0.0.941,70 ms
org.apache.maven.plugins:maven-plugins:pom:2541,58 ms
org.apache.maven.shared:maven-shared-utils:pom:3.3.441,60 ms
org.apache.maven:maven-model:pom:3.0.341,28 ms
org.sonatype.plexus:plexus-sec-dispatcher:pom:1.341,49 ms
org.sonatype.forge:forge-parent:pom:441,12 ms
org.codehaus.plexus:plexus:pom:3.3.141,32 ms
org.junit:junit-bom:pom:5.9.241,89 ms
org.hamcrest:hamcrest-all:pom:1.341,23 ms
org.apache.maven:maven-repository-metadata:pom:3.041,58 ms
org.ow2:ow2:pom:1.541,73 ms
org.apache.geronimo.genesis:genesis-default-flava:pom:2.041,83 ms
org.codehaus.plexus:plexus-i18n:pom:1.0-beta-1041,30 ms
org.apache.commons:commons-parent:pom:941,92 ms
commons-logging:commons-logging:pom:1.041,40 ms
dom4j:dom4j:pom:1.141,17 ms
javax.annotation:javax.annotation-api:pom:1.241,69 ms
org.codehaus.plexus:plexus:pom:3.0.141,86 ms
com.jcraft:jsch.agentproxy.connector-factory:pom:0.0.940,94 ms
com.jcraft:jsch.agentproxy.jsch:pom:0.0.940,90 ms
org.sonatype.sisu:sisu-inject-plexus:pom:2.1.140,48 ms
org.sonatype.aether:aether-parent:pom:1.1140,15 ms
classworlds:classworlds:pom:1.1-alpha-240,71 ms
org.apache.maven:maven-aether-provider:pom:3.040,45 ms
org.sonatype.aether:aether-spi:pom:1.740,35 ms
org.apache:apache:pom:1640,00 ms
org.junit:junit-bom:pom:5.7.240,99 ms
org.antlr:antlr4-master:pom:4.7.240,97 ms
org.apache.commons:commons-lang3:pom:3.8.140,64 ms
com.google.code.gson:gson-parent:pom:2.8.940,24 ms
org.apache.xbean:xbean-reflect:pom:3.740,35 ms
org.apache.geronimo.genesis:genesis-java5-flava:pom:2.040,09 ms
org.apache.maven.doxia:doxia-module-xhtml5:pom:1.11.140,48 ms
com.jcraft:jsch.agentproxy.sshagent:pom:0.0.939,63 ms
org.apache.maven:maven-parent:pom:2439,98 ms
org.apache.maven.plugins:maven-pmd-plugin:pom:3.19.039,32 ms
org.apache.maven:maven-parent:pom:3739,06 ms
org.apache:apache:pom:2339,62 ms
org.codehaus.plexus:plexus-interpolation:pom:1.1439,03 ms
org.sonatype.sisu.inject:guice-bean:pom:2.1.139,53 ms
org.sonatype.sisu:sisu-inject:pom:2.1.139,26 ms
org.sonatype.sisu:sisu-guice:pom:2.9.439,61 ms
org.apache.maven:maven-settings:pom:2.2.139,79 ms
org.junit.platform:junit-platform-commons:pom:1.9.239,25 ms
org.apache.maven:maven:pom:3.039,95 ms
org.sonatype.sisu:sisu-parent:pom:1.4.239,06 ms
org.slf4j:slf4j-api:pom:1.7.3639,61 ms
commons-collections:commons-collections:pom:3.2.139,98 ms
org.apache.maven:maven-plugin-api:pom:3.1.039,75 ms
org.eclipse.sisu:org.eclipse.sisu.plexus:pom:0.3.539,14 ms
org.apache.httpcomponents:httpcore:pom:4.4.1339,01 ms
org.apache.maven.reporting:maven-reporting-api:pom:3.039,80 ms
org.apache.maven.doxia:doxia:pom:1.039,41 ms
org.codehaus.plexus:plexus-resources:pom:1.2.039,79 ms
net.java.dev.jna:jna:pom:4.1.038,09 ms
org.apache.maven:maven:pom:3.0.338,51 ms
org.apache:apache:pom:2738,99 ms
org.sonatype.plexus:plexus-cipher:pom:1.438,91 ms
org.apache.maven:maven-artifact:pom:3.0.338,26 ms
org.apache:apache:pom:938,99 ms
org.junit.jupiter:junit-jupiter-api:pom:5.9.238,90 ms
junit:junit:pom:4.13.238,54 ms
org.assertj:assertj-parent-pom:pom:2.2.1338,07 ms
org.apache.maven:maven-parent:pom:3338,50 ms
org.apache.maven:maven-model:pom:3.038,40 ms
org.codehaus.plexus:plexus-containers:pom:2.1.138,59 ms
org.codehaus.plexus:plexus:pom:2.0.638,25 ms
org.apache.maven.shared:maven-common-artifact-filters:pom:3.1.038,98 ms
org.apache.maven:maven-parent:pom:3038,45 ms
org.apache.commons:commons-parent:pom:5238,74 ms
org.apache.geronimo.genesis:genesis:pom:2.038,35 ms
org.codehaus.plexus:plexus:pom:1.0.1038,11 ms
commons-logging:commons-logging:pom:1.138,41 ms
javax.enterprise:cdi-api:pom:1.238,86 ms
org.eclipse.aether:aether-spi:pom:0.9.0.M238,01 ms
org.apache.httpcomponents:httpcomponents-client:pom:4.5.1338,87 ms
org.apache.commons:commons-parent:pom:3438,24 ms
org.apache.maven:maven-parent:pom:1038,57 ms
com.jcraft:jsch.agentproxy.usocket-jna:pom:0.0.937,73 ms
com.jcraft:jsch.agentproxy.usocket-nc:pom:0.0.937,70 ms
org.apache.maven:maven-parent:pom:3437,84 ms
org.apache.maven:maven-aether-provider:pom:3.0.337,14 ms
org.codehaus.plexus:plexus-utils:pom:1.5.1537,16 ms
org.apache.maven:maven-repository-metadata:pom:2.2.137,94 ms
org.apache.maven:maven-plugin-registry:pom:2.2.137,76 ms
org.hamcrest:hamcrest-parent:pom:1.337,16 ms
org.apache.maven.surefire:surefire:pom:2.22.237,51 ms
org.codehaus.plexus:plexus:pom:5.137,75 ms
org.codehaus.plexus:plexus-component-annotations:pom:2.1.137,62 ms
org.slf4j:slf4j-api:pom:1.7.537,15 ms
net.sourceforge.pmd:pmd-core:pom:6.49.037,11 ms
com.google.code.gson:gson:pom:2.8.937,75 ms
org.apache.maven.doxia:doxia-sink-api:pom:1.11.137,14 ms
org.codehaus.plexus:plexus-containers:pom:2.1.037,25 ms
org.apache.xbean:xbean:pom:3.737,25 ms
com.google:google:pom:137,52 ms
org.apache.maven.doxia:doxia-module-xhtml:pom:1.11.137,70 ms
org.codehaus.plexus:plexus-containers:pom:1.0-alpha-3037,07 ms
org.codehaus.plexus:plexus-components:pom:4.037,10 ms
org.eclipse.aether:aether:pom:0.9.0.M237,23 ms
org.apache:apache:pom:1836,22 ms
org.codehaus.plexus:plexus-components:pom:1.1.1836,26 ms
org.codehaus.plexus:plexus-component-annotations:pom:1.5.536,67 ms
org.apache.maven:maven-repository-metadata:pom:3.0.336,72 ms
org.codehaus.plexus:plexus-classworlds:pom:2.436,29 ms
org.sonatype.sisu.inject:guice-parent:pom:2.9.436,18 ms
org.sonatype.aether:aether-api:pom:1.1136,69 ms
org.sonatype.aether:aether-spi:pom:1.1136,84 ms
org.apache.maven:maven-plugin-api:pom:2.2.136,35 ms
org.apache.maven:maven-artifact-manager:pom:2.2.136,45 ms
org.apache.commons:commons-parent:pom:2236,60 ms
org.codehaus.plexus:plexus-utils:pom:3.0.1536,29 ms
org.junit.platform:junit-platform-engine:pom:1.9.236,04 ms
org.mockito:mockito-core:pom:4.4.036,15 ms
org.objenesis:objenesis:pom:3.236,89 ms
org.apache.maven:maven-settings:pom:3.036,73 ms
org.sonatype.sisu.inject:guice-plexus:pom:1.4.236,89 ms
org.apache.maven.shared:maven-shared-utils:pom:3.1.036,08 ms
org.apache.maven.shared:maven-common-artifact-filters:pom:3.3.136,16 ms
net.sourceforge.pmd:pmd-jsp:pom:6.49.036,48 ms
org.apache.maven.doxia:doxia:pom:1.11.136,98 ms
com.google.collections:google-collections:pom:1.036,84 ms
org.apache.maven:maven-repository-metadata:pom:3.1.036,82 ms
org.eclipse.sisu:sisu-plexus:pom:0.3.536,74 ms
net.java:jvnet-parent:pom:336,83 ms
org.codehaus.plexus:plexus-classworlds:pom:2.4.236,24 ms
org.apache.httpcomponents:httpcomponents-core:pom:4.4.1336,86 ms
org.apache:apache:pom:736,60 ms
org.codehaus.plexus:plexus-container-default:pom:1.0-alpha-936,51 ms
org.sonatype.forge:forge-parent:pom:635,58 ms
org.apache.maven:maven-parent:pom:1135,64 ms
org.codehaus.plexus:plexus:pom:1.0.435,29 ms
org.codehaus.plexus:plexus-utils:pom:1.0.435,69 ms
backport-util-concurrent:backport-util-concurrent:pom:3.135,38 ms
org.apache.maven.shared:maven-shared-utils:pom:0.435,84 ms
org.slf4j:jcl-over-slf4j:pom:1.7.3235,15 ms
org.opentest4j:opentest4j:pom:1.2.035,58 ms
net.bytebuddy:byte-buddy:pom:1.12.835,52 ms
org.sonatype.sisu:sisu-inject-plexus:pom:1.4.235,46 ms
org.sonatype.sisu:sisu-inject:pom:1.4.235,22 ms
org.apache.maven.shared:maven-shared-components:pom:3635,28 ms
org.apache:apache:pom:2635,25 ms
org.apache.commons:commons-lang3:pom:3.12.035,54 ms
org.antlr:antlr4-runtime:pom:4.7.235,18 ms
net.sourceforge.saxon:saxon:pom:9.1.0.835,76 ms
org.apache:apache:pom:1935,50 ms
org.codehaus.plexus:plexus-classworlds:pom:2.6.035,71 ms
org.apache.maven.doxia:doxia-sitetools:pom:1.11.135,39 ms
commons-digester:commons-digester:pom:1.835,20 ms
commons-logging:commons-logging:pom:1.235,75 ms
commons-codec:commons-codec:pom:1.1135,24 ms
org.apache.maven:maven-parent:pom:1635,28 ms
org.sonatype.oss:oss-parent:pom:734,14 ms
org.codehaus.plexus:plexus-containers:pom:1.5.534,23 ms
org.codehaus.plexus:plexus-components:pom:1.1.1434,12 ms
junit:junit:pom:3.8.134,09 ms
org.apache.maven.shared:maven-shared-components:pom:1934,01 ms
org.sonatype.forge:forge-parent:pom:1034,20 ms
org.apiguardian:apiguardian-api:pom:1.1.234,54 ms
org.junit.vintage:junit-vintage-engine:pom:5.9.234,23 ms
org.apache.maven.surefire:surefire-logger-api:pom:2.22.234,84 ms
org.apache.maven:maven-core:pom:3.034,67 ms
org.sonatype.aether:aether-parent:pom:1.734,08 ms
org.sonatype.aether:aether-util:pom:1.734,82 ms
org.sonatype.aether:aether-impl:pom:1.734,32 ms
org.slf4j:slf4j-parent:pom:1.7.534,23 ms
commons-io:commons-io:pom:2.11.034,39 ms
org.slf4j:jul-to-slf4j:pom:1.7.3634,66 ms
org.apache.maven.doxia:doxia-decoration-model:pom:1.11.134,92 ms
org.codehaus.plexus:plexus:pom:1.0.1134,91 ms
org.codehaus.plexus:plexus-velocity:pom:1.234,82 ms
org.codehaus.plexus:plexus:pom:4.034,51 ms
org.apache:apache:pom:434,13 ms
commons-beanutils:commons-beanutils:pom:1.7.034,92 ms
org.apache.maven:maven-settings-builder:pom:3.1.034,20 ms
org.apache.maven:maven-artifact:pom:3.1.034,42 ms
org.codehaus.plexus:plexus-classworlds:pom:2.5.234,87 ms
org.eclipse.aether:aether-api:pom:0.9.0.M234,42 ms
org.codehaus.plexus:plexus-components:pom:6.634,12 ms
org.codehaus.plexus:plexus:pom:834,82 ms
org.sonatype.spice:spice-parent:pom:1233,99 ms
org.apache.maven:maven-plugin-api:pom:3.0.333,53 ms
org.codehaus.plexus:plexus-interpolation:pom:1.1133,07 ms
org.apache.maven:maven-artifact:pom:2.2.133,82 ms
org.apache.maven:maven-settings-builder:pom:3.033,79 ms
org.apache.maven.shared:maven-shared-components:pom:3333,07 ms
org.apache.maven.shared:maven-shared-components:pom:3033,90 ms
org.apache.commons:commons-lang3:pom:3.733,77 ms
commons-lang:commons-lang:pom:2.433,27 ms
commons-logging:commons-logging:pom:1.0.333,41 ms
commons-collections:commons-collections:pom:2.133,89 ms
org.apache.maven:maven-aether-provider:pom:3.1.033,63 ms
org.sonatype.spice:spice-parent:pom:1732,83 ms
org.sonatype.sisu.inject:guice-bean:pom:1.4.232,52 ms
org.codehaus.plexus:plexus-components:pom:1.332,73 ms
org.apache.maven.doxia:doxia-sink-api:pom:1.032,06 ms
org.codehaus.plexus:plexus-interpolation:pom:1.2632,64 ms
+
+ +
+ + + + diff --git a/maven-modules/maven-build-optimization/README.md b/maven-modules/maven-build-optimization/README.md new file mode 100644 index 0000000000..c1764b67ac --- /dev/null +++ b/maven-modules/maven-build-optimization/README.md @@ -0,0 +1,2 @@ +## Relevant Articles +- [How to Speed Up Maven Build](https://www.baeldung.com/maven-fast-build) diff --git a/maven-modules/maven-build-optimization/pom.xml b/maven-modules/maven-build-optimization/pom.xml new file mode 100644 index 0000000000..f0da31ceda --- /dev/null +++ b/maven-modules/maven-build-optimization/pom.xml @@ -0,0 +1,62 @@ + + + 4.0.0 + maven-build-optimization + 0.0.1-SNAPSHOT + maven-build-optimization + pom + + + com.baeldung + maven-modules + 0.0.1-SNAPSHOT + + + + + + org.apache.maven.plugins + maven-profiler-plugin + ${profiler.version} + + + org.apache.maven.plugins + maven-failsafe-plugin + ${failsafe.version} + + + + integration-test + verify + + + + + + + + + + skipITs + + + + org.apache.maven.plugins + maven-failsafe-plugin + + true + + + + + + + + + 3.1.2 + 1.7 + + + \ No newline at end of file diff --git a/maven-modules/pom.xml b/maven-modules/pom.xml index f7bba3a8ff..e139a4b921 100644 --- a/maven-modules/pom.xml +++ b/maven-modules/pom.xml @@ -20,6 +20,7 @@ dependency-exclusion host-maven-repo-example maven-archetype + maven-build-optimization maven-builder-plugin maven-classifier maven-copy-files diff --git a/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqManualTest.java b/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqIntegrationTest.java similarity index 82% rename from messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqManualTest.java rename to messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqIntegrationTest.java index 676dcb1dd8..f88cf81cf7 100644 --- a/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqManualTest.java +++ b/messaging-modules/spring-jms/src/test/java/com/baeldung/spring/jms/testing/EmbeddedActiveMqIntegrationTest.java @@ -23,11 +23,9 @@ import org.springframework.jms.core.JmsTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; -import com.baeldung.spring.jms.testing.EmbeddedActiveMqManualTest.TestConfiguration; - @RunWith(SpringRunner.class) -@ContextConfiguration(classes = { TestConfiguration.class }) -public class EmbeddedActiveMqManualTest { +@ContextConfiguration(classes = { EmbeddedActiveMqIntegrationTest.TestConfiguration.class }) +public class EmbeddedActiveMqIntegrationTest { @ClassRule public static EmbeddedActiveMQBroker embeddedBroker = new EmbeddedActiveMQBroker(); @@ -43,16 +41,20 @@ public class EmbeddedActiveMqManualTest { String queueName = "queue-1"; String messageText = "Test message"; + assertEquals(0, embeddedBroker.getDestination(queueName).getDestinationStatistics().getDispatched().getCount()); + assertEquals(0, embeddedBroker.getDestination(queueName).getDestinationStatistics().getMessages().getCount()); + embeddedBroker.pushMessage(queueName, messageText); - assertEquals(1, embeddedBroker.getMessageCount(queueName)); ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(TextMessage.class); - Mockito.verify(messageListener, Mockito.timeout(100)) .sampleJmsListenerMethod(messageCaptor.capture()); - + TextMessage receivedMessage = messageCaptor.getValue(); assertEquals(messageText, receivedMessage.getText()); + + assertEquals(1, embeddedBroker.getDestination(queueName).getDestinationStatistics().getDispatched().getCount()); + assertEquals(0, embeddedBroker.getDestination(queueName).getDestinationStatistics().getMessages().getCount()); } @Test @@ -61,7 +63,6 @@ public class EmbeddedActiveMqManualTest { String messageText = "Test message"; messageSender.sendTextMessage(queueName, messageText); - assertEquals(1, embeddedBroker.getMessageCount(queueName)); TextMessage sentMessage = embeddedBroker.peekTextMessage(queueName); assertEquals(messageText, sentMessage.getText()); diff --git a/pants/.gitignore b/pants/.gitignore new file mode 100644 index 0000000000..d63d1b0265 --- /dev/null +++ b/pants/.gitignore @@ -0,0 +1,5 @@ +.idea/ +.pants.d/ +.pids/ +dist/ +pants.toml.bak \ No newline at end of file diff --git a/pants/3rdparty/jvm/com/google/guava/BUILD b/pants/3rdparty/jvm/com/google/guava/BUILD new file mode 100644 index 0000000000..d7f77b1bf5 --- /dev/null +++ b/pants/3rdparty/jvm/com/google/guava/BUILD @@ -0,0 +1,5 @@ +jvm_artifact( + group="com.google.guava", + artifact="guava", + version="18.0", +) \ No newline at end of file diff --git a/pants/3rdparty/jvm/default.lock b/pants/3rdparty/jvm/default.lock new file mode 100644 index 0000000000..707d122e1d --- /dev/null +++ b/pants/3rdparty/jvm/default.lock @@ -0,0 +1,63 @@ +# This lockfile was autogenerated by Pants. To regenerate, run: +# +# pants generate-lockfiles +# +# --- BEGIN PANTS LOCKFILE METADATA: DO NOT EDIT OR REMOVE --- +# { +# "version": 1, +# "generated_with_requirements": [ +# "com.google.guava:guava:18.0,url=not_provided,jar=not_provided", +# "junit:junit:4.13.2,url=not_provided,jar=not_provided" +# ] +# } +# --- END PANTS LOCKFILE METADATA --- + +[[entries]] +directDependencies = [] +dependencies = [] +file_name = "com.google.guava_guava_18.0.jar" + +[entries.coord] +group = "com.google.guava" +artifact = "guava" +version = "18.0" +packaging = "jar" +[entries.file_digest] +fingerprint = "d664fbfc03d2e5ce9cab2a44fb01f1d0bf9dfebeccc1a473b1f9ea31f79f6f99" +serialized_bytes_length = 2256213 +[[entries]] +file_name = "junit_junit_4.13.2.jar" +[[entries.directDependencies]] +group = "org.hamcrest" +artifact = "hamcrest-core" +version = "1.3" +packaging = "jar" + +[[entries.dependencies]] +group = "org.hamcrest" +artifact = "hamcrest-core" +version = "1.3" +packaging = "jar" + + +[entries.coord] +group = "junit" +artifact = "junit" +version = "4.13.2" +packaging = "jar" +[entries.file_digest] +fingerprint = "8e495b634469d64fb8acfa3495a065cbacc8a0fff55ce1e31007be4c16dc57d3" +serialized_bytes_length = 384581 +[[entries]] +directDependencies = [] +dependencies = [] +file_name = "org.hamcrest_hamcrest-core_1.3.jar" + +[entries.coord] +group = "org.hamcrest" +artifact = "hamcrest-core" +version = "1.3" +packaging = "jar" +[entries.file_digest] +fingerprint = "66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9" +serialized_bytes_length = 45024 diff --git a/pants/3rdparty/jvm/junit/junit/BUILD b/pants/3rdparty/jvm/junit/junit/BUILD new file mode 100644 index 0000000000..ed934d9bc8 --- /dev/null +++ b/pants/3rdparty/jvm/junit/junit/BUILD @@ -0,0 +1,5 @@ +jvm_artifact( + group="junit", + artifact="junit", + version="4.13.2" +) \ No newline at end of file diff --git a/pants/README.md b/pants/README.md new file mode 100644 index 0000000000..a37d2e3d31 --- /dev/null +++ b/pants/README.md @@ -0,0 +1,2 @@ +## Relevant Articles +- [Introduction to the Pants Build Tool](https://www.baeldung.com/ops/pants-build-tool-guide) diff --git a/pants/bsp-groups.toml b/pants/bsp-groups.toml new file mode 100644 index 0000000000..2651f66162 --- /dev/null +++ b/pants/bsp-groups.toml @@ -0,0 +1,7 @@ +[groups.default] +addresses = [ + "src/jvm::", + "tests/jvm::", +] + +resolve = "jvm:jvm-default" \ No newline at end of file diff --git a/pants/pants.toml b/pants/pants.toml new file mode 100644 index 0000000000..92eead557e --- /dev/null +++ b/pants/pants.toml @@ -0,0 +1,22 @@ +[GLOBAL] +backend_packages = [ + "pants.backend.experimental.java", + "pants.backend.experimental.java.lint.google_java_format" +] +pants_version = "2.16.0" + +[source] +root_patterns = [ + "/src/*", + "/tests/*", +] + +[jvm] +jdk = 1.8 + +[test] +timeout_default = 60 +timeout_maximum = 120 + +[experimental-bsp] +groups_config_files = ["bsp-groups.toml"] \ No newline at end of file diff --git a/pants/src/com/baeldung/hellopant/BUILD b/pants/src/com/baeldung/hellopant/BUILD new file mode 100644 index 0000000000..d8fa19e8f5 --- /dev/null +++ b/pants/src/com/baeldung/hellopant/BUILD @@ -0,0 +1,15 @@ +java_sources( + dependencies=[ + "src/resources/com/baeldung/hellopant:word", + ], +) + + + +deploy_jar( + name="HelloPant", + main="com.baeldung.hellopant", + dependencies=[ + ":hellopant", + ], +) diff --git a/pants/src/com/baeldung/hellopant/Hello.java b/pants/src/com/baeldung/hellopant/Hello.java new file mode 100644 index 0000000000..e9f6111312 --- /dev/null +++ b/pants/src/com/baeldung/hellopant/Hello.java @@ -0,0 +1,20 @@ +package com.baeldung.hellopant; + +import com.google.common.base.Charsets; +import com.google.common.base.Joiner; +import com.google.common.collect.Lists; +import com.google.common.io.Resources; +import java.io.IOException; +import java.util.List; + +public class Hello { + public static void main(String[] args) throws IOException { + System.out.println("Hello World!"); + + final List names = Lists.newArrayList("John", null, "Jane", "Adam", "Tom"); + final String result = Joiner.on(",").skipNulls().join(names); + + System.out.println(result); + + } +} diff --git a/pants/src/resources/com/baeldung/hellopant/BUILD b/pants/src/resources/com/baeldung/hellopant/BUILD new file mode 100644 index 0000000000..2d67dbd40a --- /dev/null +++ b/pants/src/resources/com/baeldung/hellopant/BUILD @@ -0,0 +1 @@ +resources(name = "word", sources=["word.txt"]) \ No newline at end of file diff --git a/pants/src/resources/com/baeldung/hellopant/word.txt b/pants/src/resources/com/baeldung/hellopant/word.txt new file mode 100644 index 0000000000..0e9a12644b --- /dev/null +++ b/pants/src/resources/com/baeldung/hellopant/word.txt @@ -0,0 +1 @@ +from Us \ No newline at end of file diff --git a/pants/test/com/baeldung/hellopant/BUILD b/pants/test/com/baeldung/hellopant/BUILD new file mode 100644 index 0000000000..59fbb0113f --- /dev/null +++ b/pants/test/com/baeldung/hellopant/BUILD @@ -0,0 +1,8 @@ +junit_tests( + name="tests", + timeout=120, + + dependencies=[ + "src/resources/com/baeldung/hellopant:word", + ], +) diff --git a/pants/test/com/baeldung/hellopant/GuavaUnitTest.java b/pants/test/com/baeldung/hellopant/GuavaUnitTest.java new file mode 100644 index 0000000000..07523de6d2 --- /dev/null +++ b/pants/test/com/baeldung/hellopant/GuavaUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.hellopant; + +import static org.junit.Assert.assertEquals; + +import com.google.common.base.Charsets; +import com.google.common.base.Joiner; +import com.google.common.collect.Lists; +import com.google.common.io.Resources; +import java.io.IOException; +import java.util.List; +import org.junit.Test; + +public class GuavaUnitTest { + + @Test + public void whenConvertListToStringAndSkipNull_thenConverted() { + final List names = Lists.newArrayList("John", null, "Jane", "Adam", "Tom"); + final String result = Joiner.on(",").skipNulls().join(names); + + assertEquals(result, "John,Jane,Adam,Tom"); + } + + @Test + public void whenGettingTextFromAResourceFile_thenJoined() throws IOException { + String world = Resources.toString(Resources.getResource(GuavaUnitTest.class, "word.txt"), Charsets.UTF_8).strip(); + String result = Joiner.on(" ").join("Hello", world); + assertEquals(result, "Hello from Us"); + } + +} diff --git a/parent-boot-3/README.md b/parent-boot-3/README.md index 738d97bdfd..d0b11d44d8 100644 --- a/parent-boot-3/README.md +++ b/parent-boot-3/README.md @@ -1,3 +1,3 @@ -## Parent Boot 2 +## Parent Boot 3 This is a parent module for all projects using Spring Boot 3. diff --git a/parent-boot-3/pom.xml b/parent-boot-3/pom.xml index dcb5e179bb..dabcd7850b 100644 --- a/parent-boot-3/pom.xml +++ b/parent-boot-3/pom.xml @@ -230,7 +230,7 @@ 3.3.0 2.22.2 - 3.0.0 + 3.1.2 5.8.2 0.9.17 17 diff --git a/persistence-modules/core-java-persistence-2/pom.xml b/persistence-modules/core-java-persistence-2/pom.xml index 0bec7a808f..2013bdb6af 100644 --- a/persistence-modules/core-java-persistence-2/pom.xml +++ b/persistence-modules/core-java-persistence-2/pom.xml @@ -70,6 +70,16 @@ ${assertj.version} test + + org.mybatis + mybatis + ${mybatis.version} + + + org.springframework + spring-jdbc + ${spring-jdbc.version} + @@ -80,6 +90,8 @@ 20220320 07.00.00-MS-GA 2.1.214 + 5.3.29 + 3.5.7 \ No newline at end of file diff --git a/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/script/MyBatisScriptUtility.java b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/script/MyBatisScriptUtility.java new file mode 100644 index 0000000000..8a9bbb6e20 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/script/MyBatisScriptUtility.java @@ -0,0 +1,13 @@ +package com.baeldung.script; + +import org.apache.ibatis.jdbc.ScriptRunner; +import java.sql.Connection; + +public class MyBatisScriptUtility { + public static void runScript(String path, Connection connection) throws Exception { + ScriptRunner scriptRunner = new ScriptRunner(connection); + scriptRunner.setSendFullScript(false); + scriptRunner.setStopOnError(true); + scriptRunner.runScript(new java.io.FileReader(path)); + } +} diff --git a/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/script/SpringScriptUtility.java b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/script/SpringScriptUtility.java new file mode 100644 index 0000000000..cf70dfa890 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/script/SpringScriptUtility.java @@ -0,0 +1,29 @@ +package com.baeldung.script; + +import org.springframework.core.io.PathResource; +import org.springframework.core.io.support.EncodedResource; +import org.springframework.jdbc.datasource.init.ScriptUtils; + +import java.sql.Connection; + +public class SpringScriptUtility { + public static void runScript(String path, Connection connection) { + boolean continueOrError = false; + boolean ignoreFailedDrops = false; + String commentPrefix = "--"; + String separator = ";"; + String blockCommentStartDelimiter = "/*"; + String blockCommentEndDelimiter = "*/"; + + ScriptUtils.executeSqlScript( + connection, + new EncodedResource(new PathResource(path)), + continueOrError, + ignoreFailedDrops, + commentPrefix, + separator, + blockCommentStartDelimiter, + blockCommentEndDelimiter + ); + } +} diff --git a/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/script/SqlScriptBatchExecutor.java b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/script/SqlScriptBatchExecutor.java new file mode 100644 index 0000000000..b9da968abe --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/main/java/com/baeldung/script/SqlScriptBatchExecutor.java @@ -0,0 +1,74 @@ +package com.baeldung.script; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class SqlScriptBatchExecutor { + private static final Log logger = LogFactory.getLog(SqlScriptBatchExecutor.class); + private static final Pattern COMMENT_PATTERN = Pattern.compile("--.*|/\\*(.|[\\r\\n])*?\\*/"); + public static void executeBatchedSQL(String scriptFilePath, Connection connection, int batchSize) throws Exception { + List sqlStatements = parseSQLScript(scriptFilePath); + executeSQLBatches(connection, sqlStatements, batchSize); + } + private static List parseSQLScript(String scriptFilePath) throws IOException { + List sqlStatements = new ArrayList<>(); + + try (BufferedReader reader = new BufferedReader(new FileReader(scriptFilePath))) { + StringBuilder currentStatement = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + Matcher commentMatcher = COMMENT_PATTERN.matcher(line); + line = commentMatcher.replaceAll(""); + line = line.trim(); + + if (line.isEmpty()) { + continue; + } + + currentStatement.append(line).append(" "); + + if (line.endsWith(";")) { + sqlStatements.add(currentStatement.toString()); + logger.info(currentStatement.toString()); + currentStatement.setLength(0); + } + } + } catch (IOException e) { + throw e; + } + return sqlStatements; + } + + private static void executeSQLBatches(Connection connection, List sqlStatements, int batchSize) + throws SQLException { + int count = 0; + Statement statement = connection.createStatement(); + + for (String sql : sqlStatements) { + statement.addBatch(sql); + count++; + + if (count % batchSize == 0) { + logger.info("Executing batch"); + statement.executeBatch(); + statement.clearBatch(); + } + } + // Execute any remaining statements + if (count % batchSize != 0) { + statement.executeBatch(); + } + connection.commit(); + } +} diff --git a/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/script/MyBatisScriptUtilityUnitTest.java b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/script/MyBatisScriptUtilityUnitTest.java new file mode 100644 index 0000000000..98f82cfbd5 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/script/MyBatisScriptUtilityUnitTest.java @@ -0,0 +1,46 @@ +package com.baeldung.script; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.jupiter.api.AfterAll; + +import java.io.File; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; + +public class MyBatisScriptUtilityUnitTest { + private static final Log logger = LogFactory.getLog(MyBatisScriptUtilityUnitTest.class); + private static Connection connection = null; + private static final String JDBC_URL = "jdbc:h2:mem:testdb1"; + private static final String USERNAME = "user"; + private static final String PASSWORD = "password"; + + @Before + public void prepareConnection() throws Exception { + connection = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD); + } + + @AfterAll + public static void closeConnection() throws Exception { + connection.close(); + } + + @Test + public void givenConnectionObject_whenSQLFile_thenExecute() throws Exception { + String path = new File(ClassLoader.getSystemClassLoader() + .getResource("employee.sql").getFile()).toPath().toString(); + MyBatisScriptUtility.runScript(path, connection); + + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT COUNT(1) FROM employees"); + if (resultSet.next()) { + int count = resultSet.getInt(1); + Assert.assertEquals("Incorrect number of records inserted", 20, count); + } + } +} diff --git a/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/script/SpringScriptUtilityUnitTest.java b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/script/SpringScriptUtilityUnitTest.java new file mode 100644 index 0000000000..be6e39ca31 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/script/SpringScriptUtilityUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.script; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.jupiter.api.AfterAll; + +import java.io.File; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; + +public class SpringScriptUtilityUnitTest { + private static final Log logger = LogFactory.getLog(SpringScriptUtilityUnitTest.class); + + private static Connection connection = null; + private static final String JDBC_URL = "jdbc:h2:mem:testdb2"; + private static final String USERNAME = "user"; + private static final String PASSWORD = "password"; + + @Before + public void prepareConnection() throws Exception { + connection = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD); + } + + @AfterAll + public static void closeConnection() throws Exception { + connection.close(); + } + + @Test + public void givenConnectionObject_whenSQLFile_thenExecute() throws Exception { + String path = new File(ClassLoader.getSystemClassLoader() + .getResource("employee.sql").getFile()).toPath().toString(); + SpringScriptUtility.runScript(path, connection); + + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT COUNT(1) FROM employees"); + if (resultSet.next()) { + int count = resultSet.getInt(1); + Assert.assertEquals("Incorrect number of records inserted", 20, count); + } + } +} diff --git a/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/script/SqlScriptBatchExecutorUnitTest.java b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/script/SqlScriptBatchExecutorUnitTest.java new file mode 100644 index 0000000000..3b1210fd00 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/test/java/com/baeldung/script/SqlScriptBatchExecutorUnitTest.java @@ -0,0 +1,47 @@ +package com.baeldung.script; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.jupiter.api.AfterAll; + +import java.io.File; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.Statement; + +public class SqlScriptBatchExecutorUnitTest { + private static final Log logger = LogFactory.getLog(SqlScriptBatchExecutorUnitTest.class); + private static Connection connection = null; + private static final String JDBC_URL = "jdbc:h2:mem:testdb3"; + private static final String USERNAME = "user"; + private static final String PASSWORD = "password"; + + @Before + public void prepareConnection() throws Exception { + connection = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD); + } + + @AfterAll + public static void closeConnection() throws Exception { + connection.close(); + } + + @Test + public void givenConnectionObject_whenSQLFile_thenExecute() throws Exception { + String path = new File(ClassLoader.getSystemClassLoader() + .getResource("employee.sql").getFile()).toPath().toString(); + SqlScriptBatchExecutor.executeBatchedSQL(path, connection, 10); + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SELECT COUNT(1) FROM employees"); + + if (resultSet.next()) { + int count = resultSet.getInt(1); + Assert.assertEquals("Incorrect number of records inserted", 20, count); + } + } + +} diff --git a/persistence-modules/core-java-persistence-2/src/test/resources/employee.sql b/persistence-modules/core-java-persistence-2/src/test/resources/employee.sql new file mode 100644 index 0000000000..c532458163 --- /dev/null +++ b/persistence-modules/core-java-persistence-2/src/test/resources/employee.sql @@ -0,0 +1,75 @@ +/** +Script Name : Create employees script +Author: Parthiv Pradhan + +**/ + +-- Create the employees table if it doesn't exist +CREATE TABLE employees ( + id INT PRIMARY KEY, + first_name VARCHAR(50), + last_name VARCHAR(50), + department VARCHAR(50), + salary DECIMAL(10, 2) +); + +-- Insert employee records +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (1, 'John', 'Doe', 'HR', 50000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (2, 'Jane', 'Smith', 'IT', 60000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (3, 'Michael', 'Johnson', 'Finance', 55000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (4, 'Emily', 'Williams', 'Marketing', 52000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (5, 'David', 'Brown', 'IT', 65000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (6, 'Sarah', 'Miller', 'Finance', 58000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (7, 'Robert', 'Jones', 'HR', 53000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (8, 'Jessica', 'Davis', 'Marketing', 51000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (9, 'William', 'Wilson', 'IT', 59000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (10, 'Jennifer', 'Taylor', 'Finance', 57000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (11, 'Daniel', 'Anderson', 'Marketing', 54000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (12, 'Linda', 'Martinez', 'HR', 52000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (13, 'Christopher', 'Lopez', 'IT', 62000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (14, 'Karen', 'Hernandez', 'Finance', 56000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (15, 'Mark', 'Garcia', 'Marketing', 53000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (16, 'Patricia', 'Lee', 'HR', 51000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (17, 'Anthony', 'Clark', 'IT', 60000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (18, 'Maria', 'Lewis', 'Finance', 59000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (19, 'Paul', 'Walker', 'Marketing', 55000.00); + +INSERT INTO employees (id, first_name, last_name, department, salary) +VALUES (20, 'Ruth', 'Young', 'HR', 54000.00); diff --git a/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/joincolumn/Email.java b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/joincolumn/Email.java index 096faf7984..c25820300e 100644 --- a/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/joincolumn/Email.java +++ b/persistence-modules/hibernate-annotations/src/main/java/com/baeldung/hibernate/joincolumn/Email.java @@ -18,7 +18,7 @@ public class Email { private String address; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "employee_id") + @JoinColumn(name = "employee_id", referencedColumnName = "id") private OfficialEmployee employee; public Long getId() { diff --git a/persistence-modules/hibernate-enterprise/pom.xml b/persistence-modules/hibernate-enterprise/pom.xml index eaa7b0e765..954f8f40d3 100644 --- a/persistence-modules/hibernate-enterprise/pom.xml +++ b/persistence-modules/hibernate-enterprise/pom.xml @@ -82,7 +82,6 @@ 8.0.32 2.6.0 0.9 - 1.14.2
\ No newline at end of file diff --git a/persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/Neo4jLiveTest.java b/persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/Neo4jLiveTest.java deleted file mode 100644 index 8591dd3a8d..0000000000 --- a/persistence-modules/neo4j/src/test/java/com/baeldung/neo4j/Neo4jLiveTest.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.baeldung.neo4j; - - -import static org.neo4j.configuration.GraphDatabaseSettings.DEFAULT_DATABASE_NAME; - -import java.io.File; -import java.time.Duration; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -import org.junit.After; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.neo4j.configuration.GraphDatabaseSettings; -import org.neo4j.dbms.api.DatabaseManagementService; -import org.neo4j.dbms.api.DatabaseManagementServiceBuilder; -import org.neo4j.graphdb.GraphDatabaseService; -import org.neo4j.graphdb.Label; -import org.neo4j.graphdb.Node; -import org.neo4j.graphdb.NotFoundException; -import org.neo4j.graphdb.RelationshipType; -import org.neo4j.graphdb.Result; -import org.neo4j.graphdb.Transaction; - -/** - * To run this test you will need to have an instance of the docker running on your machine (Docker desktop - for Windows and Docker instance for linux) - * After your docker instance is up run this test - */ -public class Neo4jLiveTest { - - private static GraphDatabaseService graphDb; - private static Transaction transaction; - private static DatabaseManagementService managementService; - - @Before - public void setUp() { - managementService = new DatabaseManagementServiceBuilder(new File("data/cars").toPath()) - .setConfig( GraphDatabaseSettings.transaction_timeout, Duration.ofSeconds( 60 ) ) - .setConfig( GraphDatabaseSettings.preallocate_logical_logs, false ).build(); - graphDb = managementService.database( DEFAULT_DATABASE_NAME ); - } - - @After - public void tearDown() { - managementService.shutdown(); - } - - @Test - public void testPersonCar() { - transaction = graphDb.beginTx(); - Node car = transaction.createNode(Label.label("Car")); - car.setProperty("make", "tesla"); - car.setProperty("model", "model3"); - - Node owner = transaction.createNode(Label.label("Person")); - owner.setProperty("firstName", "baeldung"); - owner.setProperty("lastName", "baeldung"); - - owner.createRelationshipTo(car, RelationshipType.withName("owner")); - - Result result = transaction.execute("MATCH (c:Car) <-[owner]- (p:Person) " + - "WHERE c.make = 'tesla'" + - "RETURN p.firstName, p.lastName"); - - Map firstResult = result.next(); - - Assert.assertEquals("baeldung", firstResult.get("p.firstName")); - } - - @Test - public void testCreateNode() { - transaction = graphDb.beginTx(); - Result result = transaction.execute("CREATE (baeldung:Company {name:\"Baeldung\"})" + - "RETURN baeldung"); - - Map firstResult = result.next(); - Node firstNode = (Node) firstResult.get("baeldung"); - - Assert.assertEquals(firstNode.getProperty("name"), "Baeldung"); - } - - @Test - public void testCreateNodeAndLink() { - transaction = graphDb.beginTx(); - Result result = transaction.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + - "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + - "RETURN baeldung, tesla"); - - Map firstResult = result.next(); - - Assert.assertTrue(firstResult.containsKey("baeldung")); - Assert.assertTrue(firstResult.containsKey("tesla")); - } - - @Test - public void testFindAndReturn() { - transaction = graphDb.beginTx(); - transaction.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + - "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + - "RETURN baeldung, tesla"); - - Result result = transaction.execute("MATCH (company:Company)-[:owns]-> (car:Car)" + - "WHERE car.make='tesla' and car.model='modelX'" + - "RETURN company.name"); - - Map firstResult = result.next(); - - Assert.assertEquals(firstResult.get("company.name"), "Baeldung"); - } - - @Test - public void testUpdate() { - transaction = graphDb.beginTx(); - transaction.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + - "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + - "RETURN baeldung, tesla"); - - Result result = transaction.execute("MATCH (car:Car)" + - "WHERE car.make='tesla'" + - " SET car.milage=120" + - " SET car :Car:Electro" + - " SET car.model=NULL" + - " RETURN car"); - - Map firstResult = result.next(); - Node car = (Node) firstResult.get("car"); - - Assert.assertEquals(car.getProperty("milage"), 120L); - Assert.assertEquals(car.getLabels(), Arrays.asList(Label.label("Car"), Label.label("Electro"))); - - try { - car.getProperty("model"); - Assert.fail(); - } catch (NotFoundException e) { - // expected - } - } - - @Test - public void testDelete() { - transaction = graphDb.beginTx(); - transaction.execute("CREATE (baeldung:Company {name:\"Baeldung\"}) " + - "-[:owns]-> (tesla:Car {make: 'tesla', model: 'modelX'})" + - "RETURN baeldung, tesla"); - - transaction.execute("MATCH (company:Company)" + - " WHERE company.name='Baeldung'" + - " DELETE company"); - - Result result = transaction.execute("MATCH (company:Company)" + - " WHERE company.name='Baeldung'" + - " RETURN company"); - - Assert.assertFalse(result.hasNext()); - } - - @Test - public void testBindings() { - transaction = graphDb.beginTx(); - Map params = new HashMap<>(); - params.put("name", "baeldung"); - params.put("make", "tesla"); - params.put("model", "modelS"); - - Result result = transaction.execute("CREATE (baeldung:Company {name:$name}) " + - "-[:owns]-> (tesla:Car {make: $make, model: $model})" + - "RETURN baeldung, tesla", params); - - Map firstResult = result.next(); - Assert.assertTrue(firstResult.containsKey("baeldung")); - Assert.assertTrue(firstResult.containsKey("tesla")); - - Node car = (Node) firstResult.get("tesla"); - Assert.assertEquals(car.getProperty("model"), "modelS"); - } -} diff --git a/persistence-modules/spring-boot-persistence-4/README.md b/persistence-modules/spring-boot-persistence-4/README.md new file mode 100644 index 0000000000..bb2da31d9c --- /dev/null +++ b/persistence-modules/spring-boot-persistence-4/README.md @@ -0,0 +1,2 @@ +## Relevant Articles +- [Scroll API in Spring Data JPA](https://www.baeldung.com/spring-data-jpa-scroll-api) diff --git a/persistence-modules/spring-boot-persistence-h2/pom.xml b/persistence-modules/spring-boot-persistence-h2/pom.xml index 023e20837b..f643db2260 100644 --- a/persistence-modules/spring-boot-persistence-h2/pom.xml +++ b/persistence-modules/spring-boot-persistence-h2/pom.xml @@ -17,6 +17,10 @@ + + org.springframework.boot + spring-boot-starter-web + org.springframework.boot spring-boot-starter-data-jpa diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/resources/app-h2.properties b/persistence-modules/spring-boot-persistence-h2/src/main/resources/app-h2.properties index bb88e7fef4..13500d1c1f 100644 --- a/persistence-modules/spring-boot-persistence-h2/src/main/resources/app-h2.properties +++ b/persistence-modules/spring-boot-persistence-h2/src/main/resources/app-h2.properties @@ -1 +1 @@ -spring.sql.init.data-locations=user-data.sql +spring.sql.init.data-locations=classpath:user-data.sql diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-h2.properties b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-h2.properties index 6fb436f520..799bb67959 100644 --- a/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-h2.properties +++ b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-h2.properties @@ -1 +1 @@ -spring.sql.init.data-locations=data-h2.sql +spring.sql.init.data-locations=classpath:data-h2.sql diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-lazy-load-no-trans-off.properties b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-lazy-load-no-trans-off.properties index b030527cca..df322cd15e 100644 --- a/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-lazy-load-no-trans-off.properties +++ b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-lazy-load-no-trans-off.properties @@ -5,7 +5,7 @@ spring.datasource.password= spring.jpa.hibernate.ddl-auto=create-drop spring.h2.console.enabled=true spring.h2.console.path=/h2-console -spring.sql.init.data-locations=data-trans.sql +spring.sql.init.data-locations=classpath:data-trans.sql logging.level.org.hibernate.SQL=INFO logging.level.org.hibernate.type=INFO diff --git a/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-lazy-load-no-trans-on.properties b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-lazy-load-no-trans-on.properties index 972a7bb0f3..e5c488f3be 100644 --- a/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-lazy-load-no-trans-on.properties +++ b/persistence-modules/spring-boot-persistence-h2/src/main/resources/application-lazy-load-no-trans-on.properties @@ -5,7 +5,7 @@ spring.datasource.password= spring.jpa.hibernate.ddl-auto=create-drop spring.h2.console.enabled=true spring.h2.console.path=/h2-console -spring.sql.init.data-locations=data-trans.sql +spring.sql.init.data-locations=classpath:data-trans.sql logging.level.org.hibernate.SQL=INFO logging.level.org.hibernate.type=INFO diff --git a/persistence-modules/spring-data-elasticsearch/pom.xml b/persistence-modules/spring-data-elasticsearch/pom.xml index 7e91a5b15c..8e5e8ab7c7 100644 --- a/persistence-modules/spring-data-elasticsearch/pom.xml +++ b/persistence-modules/spring-data-elasticsearch/pom.xml @@ -34,6 +34,21 @@ fastjson ${fastjson.version} + + org.elasticsearch.client + elasticsearch-rest-high-level-client + 7.17.11 + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + org.projectlombok + lombok + 1.18.28 + org.locationtech.spatial4j spatial4j @@ -59,11 +74,12 @@ - 4.0.0.RELEASE - 7.6.2 - 1.2.47 - 0.7 - 1.15.0 + 5.1.2 + 8.9.0 + 2.0.37 + 0.8 + 1.18.2 + 2.15.2 \ No newline at end of file diff --git a/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/elasticsearch/Person.java b/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/elasticsearch/Person.java index 09b971fdc2..d51d1a0576 100644 --- a/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/elasticsearch/Person.java +++ b/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/elasticsearch/Person.java @@ -1,7 +1,14 @@ package com.baeldung.elasticsearch; +import lombok.*; + import java.util.Date; +@AllArgsConstructor +@Getter +@ToString +@EqualsAndHashCode +@NoArgsConstructor public class Person { private int age; @@ -9,43 +16,4 @@ public class Person { private String fullName; private Date dateOfBirth; - - public Person() { - } - - Person(int age, String fullName, Date dateOfBirth) { - super(); - this.age = age; - this.fullName = fullName; - this.dateOfBirth = dateOfBirth; - } - - public int getAge() { - return age; - } - - public void setAge(int age) { - this.age = age; - } - - public String getFullName() { - return fullName; - } - - public void setFullName(String fullName) { - this.fullName = fullName; - } - - public Date getDateOfBirth() { - return dateOfBirth; - } - - public void setDateOfBirth(Date dateOfBirth) { - this.dateOfBirth = dateOfBirth; - } - - @Override - public String toString() { - return "Person [age=" + age + ", fullName=" + fullName + ", dateOfBirth=" + dateOfBirth + "]"; - } } diff --git a/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/config/Config.java b/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/config/Config.java index 7f6653d7a8..3a72493038 100644 --- a/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/config/Config.java +++ b/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/config/Config.java @@ -5,8 +5,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.data.elasticsearch.client.ClientConfiguration; -import org.springframework.data.elasticsearch.client.RestClients; -import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration; +import org.springframework.data.elasticsearch.client.erhlc.AbstractElasticsearchConfiguration; +import org.springframework.data.elasticsearch.client.erhlc.RestClients; import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories; @Configuration diff --git a/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Article.java b/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Article.java index e901d0d0ed..b77f47dcc1 100644 --- a/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Article.java +++ b/persistence-modules/spring-data-elasticsearch/src/main/java/com/baeldung/spring/data/es/model/Article.java @@ -13,7 +13,7 @@ import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.InnerField; import org.springframework.data.elasticsearch.annotations.MultiField; -@Document(indexName = "blog", type = "article") +@Document(indexName = "blog"/*, type = "article"*/) public class Article { @Id diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java index 2ca5f28f13..0d4117c75e 100644 --- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java +++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/ElasticSearchManualTest.java @@ -1,173 +1,174 @@ package com.baeldung.elasticsearch; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.Result; +import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery; +import co.elastic.clients.elasticsearch._types.query_dsl.Query; +import co.elastic.clients.elasticsearch._types.query_dsl.RangeQuery; +import co.elastic.clients.elasticsearch._types.query_dsl.SimpleQueryStringQuery; +import co.elastic.clients.elasticsearch.core.DeleteResponse; +import co.elastic.clients.elasticsearch.core.GetResponse; +import co.elastic.clients.elasticsearch.core.IndexResponse; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.Hit; +import co.elastic.clients.json.jackson.JacksonJsonpMapper; +import co.elastic.clients.transport.ElasticsearchTransport; +import co.elastic.clients.transport.rest_client.RestClientTransport; +import lombok.extern.slf4j.Slf4j; +import org.apache.http.HttpHost; +import org.elasticsearch.client.RestClient; +import org.junit.Before; +import org.junit.Test; +import org.junit.jupiter.api.Disabled; + +import java.io.IOException; +import java.io.StringReader; +import java.util.Date; +import java.util.List; + import static org.junit.Assert.assertEquals; -import java.io.IOException; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import com.alibaba.fastjson.JSON; - -import org.elasticsearch.action.DocWriteResponse.Result; -import org.elasticsearch.action.delete.DeleteRequest; -import org.elasticsearch.action.delete.DeleteResponse; -import org.elasticsearch.action.get.GetRequest; -import org.elasticsearch.action.get.GetResponse; -import org.elasticsearch.action.index.IndexRequest; -import org.elasticsearch.action.index.IndexResponse; -import org.elasticsearch.action.search.SearchRequest; -import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.action.search.SearchType; -import org.elasticsearch.client.RequestOptions; -import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.index.query.QueryBuilders; -import org.elasticsearch.search.SearchHit; -import org.elasticsearch.search.builder.SearchSourceBuilder; -import org.junit.Before; -import org.junit.Test; -import org.springframework.data.elasticsearch.client.ClientConfiguration; -import org.springframework.data.elasticsearch.client.RestClients; - /** * This Manual test requires: Elasticsearch instance running on localhost:9200. - * - * The following docker command can be used: docker run -d --name es762 -p - * 9200:9200 -e "discovery.type=single-node" elasticsearch:7.6.2 + *

+ * The following docker command can be used: + * docker run -d --name elastic-test -p 9200:9200 -e "discovery.type=single-node" -e "xpack.security.enabled=false" docker.elastic.co/elasticsearch/elasticsearch:8.9.0 */ +@Slf4j +@Disabled("Manual test") public class ElasticSearchManualTest { - private List listOfPersons = new ArrayList<>(); - private RestHighLevelClient client = null; + private ElasticsearchClient client = null; @Before - public void setUp() throws UnknownHostException { + public void setUp() throws IOException { + RestClient restClient = RestClient + .builder(HttpHost.create("http://localhost:9200")) + .build(); + ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper()); + client = new ElasticsearchClient(transport); Person person1 = new Person(10, "John Doe", new Date()); Person person2 = new Person(25, "Janette Doe", new Date()); - listOfPersons.add(person1); - listOfPersons.add(person2); + Person person3 = new Person(8, "Mark Doe", new Date()); + client.index(builder -> builder + .index("person") + .id(person1.getFullName()) + .document(person1)); + client.index(builder -> builder + .index("person") + .id(person2.getFullName()) + .document(person2)); + client.index(builder -> builder + .index("person") + .id(person3.getFullName()) + .document(person3)); + } - ClientConfiguration clientConfiguration = ClientConfiguration.builder() - .connectedTo("localhost:9200") - .build(); - client = RestClients.create(clientConfiguration) - .rest(); + @Test + public void givenJsonDocument_whenJavaObject_thenIndexDocument() throws Exception { + Person person = new Person(20, "Mark Doe", new Date(1471466076564L)); + IndexResponse response = client.index(i -> i + .index("person") + .id(person.getFullName()) + .document(person)); + + log.info("Indexed with version: {}", response.version()); + assertEquals(Result.Created, response.result()); + assertEquals("person", response.index()); + assertEquals("Mark Doe", response.id()); } @Test public void givenJsonString_whenJavaObject_thenIndexDocument() throws Exception { - String jsonObject = "{\"age\":20,\"dateOfBirth\":1471466076564,\"fullName\":\"John Doe\"}"; - IndexRequest request = new IndexRequest("people"); - request.source(jsonObject, XContentType.JSON); - - IndexResponse response = client.index(request, RequestOptions.DEFAULT); - String index = response.getIndex(); - long version = response.getVersion(); - - assertEquals(Result.CREATED, response.getResult()); - assertEquals(1, version); - assertEquals("people", index); + String jsonString = "{\"age\":10,\"dateOfBirth\":1471466076564,\"fullName\":\"John Doe\"}"; + StringReader stringReader = new StringReader(jsonString); + IndexResponse response = client.index(i -> i + .index("person") + .id("John Doe") + .withJson(stringReader)); + log.info("Indexed with version: {}", response.version()); + assertEquals("person", response.index()); + assertEquals("John Doe", response.id()); } @Test public void givenDocumentId_whenJavaObject_thenDeleteDocument() throws Exception { - String jsonObject = "{\"age\":10,\"dateOfBirth\":1471455886564,\"fullName\":\"Johan Doe\"}"; - IndexRequest indexRequest = new IndexRequest("people"); - indexRequest.source(jsonObject, XContentType.JSON); - - IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT); - String id = response.getId(); - - GetRequest getRequest = new GetRequest("people"); - getRequest.id(id); - - GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT); - System.out.println(getResponse.getSourceAsString()); - - DeleteRequest deleteRequest = new DeleteRequest("people"); - deleteRequest.id(id); - - DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT); - - assertEquals(Result.DELETED, deleteResponse.getResult()); + String documentId = "Mark Doe"; + DeleteResponse response = client.delete(i -> i + .index("person") + .id(documentId)); + assertEquals(Result.Deleted, response.result()); + assertEquals("Mark Doe", response.id()); } @Test - public void givenSearchRequest_whenMatchAll_thenReturnAllResults() throws Exception { - SearchRequest searchRequest = new SearchRequest(); - SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); - SearchHit[] searchHits = response.getHits() - .getHits(); - List results = Arrays.stream(searchHits) - .map(hit -> JSON.parseObject(hit.getSourceAsString(), Person.class)) - .collect(Collectors.toList()); + public void givenSearchRequest_whenMatch_thenReturnAllResults() throws Exception { + String searchText = "John"; + SearchResponse searchResponse = client.search(s -> s + .index("person") + .query(q -> q + .match(t -> t + .field("fullName") + .query(searchText))), Person.class); - results.forEach(System.out::println); + List> hits = searchResponse.hits().hits(); + assertEquals(1, hits.size()); + assertEquals("John Doe", hits.get(0).source().getFullName()); } @Test - public void givenSearchParameters_thenReturnResults() throws Exception { - SearchSourceBuilder builder = new SearchSourceBuilder().postFilter(QueryBuilders.rangeQuery("age") - .from(5) - .to(15)); - - SearchRequest searchRequest = new SearchRequest(); - searchRequest.searchType(SearchType.DFS_QUERY_THEN_FETCH); - searchRequest.source(builder); - - SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); - - builder = new SearchSourceBuilder().postFilter(QueryBuilders.simpleQueryStringQuery("+John -Doe OR Janette")); - - searchRequest = new SearchRequest(); - searchRequest.searchType(SearchType.DFS_QUERY_THEN_FETCH); - searchRequest.source(builder); - - SearchResponse response2 = client.search(searchRequest, RequestOptions.DEFAULT); - - builder = new SearchSourceBuilder().postFilter(QueryBuilders.matchQuery("John", "Name*")); - searchRequest = new SearchRequest(); - searchRequest.searchType(SearchType.DFS_QUERY_THEN_FETCH); - searchRequest.source(builder); - - SearchResponse response3 = client.search(searchRequest, RequestOptions.DEFAULT); - - response2.getHits(); - response3.getHits(); - - final List results = Stream.of(response.getHits() - .getHits(), - response2.getHits() - .getHits(), - response3.getHits() - .getHits()) - .flatMap(Arrays::stream) - .map(hit -> JSON.parseObject(hit.getSourceAsString(), Person.class)) - .collect(Collectors.toList()); - - results.forEach(System.out::println); + public void givenGetRequest_whenMatch_thenReturnAllResults() throws IOException { + String documentId = "John Doe"; + GetResponse getResponse = client.get(s -> s + .index("person") + .id(documentId), Person.class); + Person source = getResponse.source(); + assertEquals("John Doe", source.getFullName()); } @Test - public void givenContentBuilder_whenHelpers_thanIndexJson() throws IOException { - XContentBuilder builder = XContentFactory.jsonBuilder() - .startObject() - .field("fullName", "Test") - .field("salary", "11500") - .field("age", "10") - .endObject(); + public void givenSearchRequest_whenMatchAndRange_thenReturnAllResults() throws Exception { + String searchText = "John"; + SearchResponse searchResponse = client.search(s -> s + .index("person") + .query(q -> q + .match(t -> t + .field("fullName").query(searchText))) + .query(q -> q + .range(range -> range + .field("age").from("1").to("10"))), + Person.class); - IndexRequest indexRequest = new IndexRequest("people"); - indexRequest.source(builder); + List> hits = searchResponse.hits().hits(); + assertEquals(1, hits.size()); + assertEquals("John Doe", hits.get(0).source().getFullName()); + } - IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT); - assertEquals(Result.CREATED, response.getResult()); + @Test + public void givenMultipleQueries_thenReturnResults() throws Exception { + Query ageQuery = RangeQuery.of(r -> r.field("age").from("5").to("15"))._toQuery(); + SearchResponse response1 = client.search(s -> s.query(q -> q.bool(b -> b + .must(ageQuery))), Person.class); + response1.hits().hits().forEach(hit -> log.info("Response 1: {}", hit.source())); + + Query fullNameQuery = MatchQuery.of(m -> m.field("fullName").query("John"))._toQuery(); + SearchResponse response2 = client.search(s -> s.query(q -> q.bool(b -> b + .must(fullNameQuery))), Person.class); + response2.hits().hits().forEach(hit -> log.info("Response 2: {}", hit.source())); + Query doeContainsQuery = SimpleQueryStringQuery.of(q -> q.query("*Doe"))._toQuery(); + SearchResponse response3 = client.search(s -> s.query(q -> q.bool(b -> b + .must(doeContainsQuery))), Person.class); + response3.hits().hits().forEach(hit -> log.info("Response 3: {}", hit.source())); + + Query simpleStringQuery = SimpleQueryStringQuery.of(q -> q.query("+John -Doe OR Janette"))._toQuery(); + SearchResponse response4 = client.search(s -> s.query(q -> q.bool(b -> b + .must(simpleStringQuery))), Person.class); + response4.hits().hits().forEach(hit -> log.info("Response 4: {}", hit.source())); + + SearchResponse response5 = client.search(s -> s.query(q -> q.bool(b -> b + .must(ageQuery) + .must(fullNameQuery) + .must(simpleStringQuery))), Person.class); + response5.hits().hits().forEach(hit -> log.info("Response 5: {}", hit.source())); } } diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java index 64b2ea2437..abe10f4607 100644 --- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java +++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/elasticsearch/GeoQueriesManualTest.java @@ -21,14 +21,13 @@ import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.ShapeRelation; -import org.elasticsearch.common.geo.builders.EnvelopeBuilder; import org.elasticsearch.common.unit.DistanceUnit; -import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.query.GeoShapeQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.builder.SearchSourceBuilder; +import org.elasticsearch.xcontent.XContentType; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -64,38 +63,38 @@ public class GeoQueriesManualTest { .create(req, RequestOptions.DEFAULT); } - @Test - public void givenGeoShapeData_whenExecutedGeoShapeQuery_thenResultNonEmpty() throws IOException { - String jsonObject = "{\"name\":\"Agra\",\"region\":{\"type\":\"envelope\",\"coordinates\":[[75,30.2],[80.1, 25]]}}"; - IndexRequest indexRequest = new IndexRequest(WONDERS_OF_WORLD); - indexRequest.source(jsonObject, XContentType.JSON); - IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT); - - String tajMahalId = response.getId(); - - RefreshRequest refreshRequest = new RefreshRequest(WONDERS_OF_WORLD); - client.indices() - .refresh(refreshRequest, RequestOptions.DEFAULT); - - Coordinate topLeft = new Coordinate(74, 31.2); - Coordinate bottomRight = new Coordinate(81.1, 24); - - GeoShapeQueryBuilder qb = QueryBuilders.geoShapeQuery("region", new EnvelopeBuilder(topLeft, bottomRight).buildGeometry()); - qb.relation(ShapeRelation.INTERSECTS); - - SearchSourceBuilder source = new SearchSourceBuilder().query(qb); - SearchRequest searchRequest = new SearchRequest(WONDERS_OF_WORLD); - searchRequest.source(source); - - SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); - - List ids = Arrays.stream(searchResponse.getHits() - .getHits()) - .map(SearchHit::getId) - .collect(Collectors.toList()); - - assertTrue(ids.contains(tajMahalId)); - } +// @Test +// public void givenGeoShapeData_whenExecutedGeoShapeQuery_thenResultNonEmpty() throws IOException { +// String jsonObject = "{\"name\":\"Agra\",\"region\":{\"type\":\"envelope\",\"coordinates\":[[75,30.2],[80.1, 25]]}}"; +// IndexRequest indexRequest = new IndexRequest(WONDERS_OF_WORLD); +// indexRequest.source(jsonObject, XContentType.JSON); +// IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT); +// +// String tajMahalId = response.getId(); +// +// RefreshRequest refreshRequest = new RefreshRequest(WONDERS_OF_WORLD); +// client.indices() +// .refresh(refreshRequest, RequestOptions.DEFAULT); +// +// Coordinate topLeft = new Coordinate(74, 31.2); +// Coordinate bottomRight = new Coordinate(81.1, 24); +// +// GeoShapeQueryBuilder qb = QueryBuilders.geoShapeQuery("region", new EnvelopeBuilder(topLeft, bottomRight).buildGeometry()); +// qb.relation(ShapeRelation.INTERSECTS); +// +// SearchSourceBuilder source = new SearchSourceBuilder().query(qb); +// SearchRequest searchRequest = new SearchRequest(WONDERS_OF_WORLD); +// searchRequest.source(source); +// +// SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); +// +// List ids = Arrays.stream(searchResponse.getHits() +// .getHits()) +// .map(SearchHit::getId) +// .collect(Collectors.toList()); +// +// assertTrue(ids.contains(tajMahalId)); +// } @Test public void givenGeoPointData_whenExecutedGeoBoundingBoxQuery_thenResultNonEmpty() throws Exception { diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java index cc38acc41c..59d02997f0 100644 --- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java +++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchManualTest.java @@ -22,10 +22,10 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; +import org.springframework.data.elasticsearch.client.erhlc.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; -import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.Query; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; diff --git a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java index 03c8da80c9..479d75c673 100644 --- a/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java +++ b/persistence-modules/spring-data-elasticsearch/src/test/java/com/baeldung/spring/data/es/ElasticSearchQueryManualTest.java @@ -39,11 +39,11 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.elasticsearch.client.erhlc.NativeSearchQuery; +import org.springframework.data.elasticsearch.client.erhlc.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.ElasticsearchOperations; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; -import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; -import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; diff --git a/persistence-modules/spring-data-neo4j/pom.xml b/persistence-modules/spring-data-neo4j/pom.xml index 33f2966db3..8a0a9ff464 100644 --- a/persistence-modules/spring-data-neo4j/pom.xml +++ b/persistence-modules/spring-data-neo4j/pom.xml @@ -15,53 +15,39 @@ - org.neo4j - neo4j-ogm-embedded-driver - ${neo4j-ogm.version} + org.neo4j.test + neo4j-harness + ${neo4j-harness.version} + test - org.springframework.data - spring-data-neo4j - ${spring-data-neo4j.version} - - - com.voodoodyne.jackson.jsog - jackson-jsog - ${jackson-jsog.version} - compile + org.springframework.boot + spring-boot-starter-data-neo4j + ${spring-boot.version} + + + org.springframework.boot + spring-boot-starter-logging + + org.springframework.boot spring-boot-starter-test ${spring-boot.version} test - - - org.neo4j - neo4j-ogm-test - ${neo4j-ogm.version} - test - - - org.neo4j.test - neo4j-harness - ${neo4j.version} - test - - - org.springframework - spring-test - ${spring-test.version} + + + org.springframework.boot + spring-boot-starter-logging + + - 3.4.6 - 5.0.1.RELEASE - 1.1 - 2.0.1.RELEASE - 5.0.1.RELEASE - 3.1.2 + 2.7.14 + 5.10.0 \ No newline at end of file diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/Neo4JApplication.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/Neo4JApplication.java new file mode 100644 index 0000000000..8e1f104be5 --- /dev/null +++ b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/Neo4JApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.spring.data.neo4j; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Neo4JApplication { + + public static void main(String[] args) { + SpringApplication.run(Neo4JApplication.class, args); + } +} diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jConfiguration.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jConfiguration.java deleted file mode 100644 index 4e87c24614..0000000000 --- a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jConfiguration.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.baeldung.spring.data.neo4j.config; - -import org.neo4j.ogm.config.Configuration.Builder; -import org.neo4j.ogm.session.SessionFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories; - -@ComponentScan(basePackages = { "com.baeldung.spring.data.neo4j.services" }) -@Configuration -@EnableNeo4jRepositories(basePackages = "com.baeldung.spring.data.neo4j.repository") -public class MovieDatabaseNeo4jConfiguration { - - public static final String URL = System.getenv("NEO4J_URL") != null ? System.getenv("NEO4J_URL") : "http://neo4j:movies@localhost:7474"; - - @Bean - public org.neo4j.ogm.config.Configuration getConfiguration() { - return new Builder().uri(URL).build(); - } - - @Bean - public SessionFactory getSessionFactory() { - return new SessionFactory(getConfiguration(), "com.baeldung.spring.data.neo4j.domain"); - } -} diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jTestConfiguration.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jTestConfiguration.java deleted file mode 100644 index a4cbe4b809..0000000000 --- a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/MovieDatabaseNeo4jTestConfiguration.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.baeldung.spring.data.neo4j.config; - -import org.neo4j.ogm.config.Configuration.Builder; -import org.neo4j.ogm.session.SessionFactory; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; -import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories; -import org.springframework.data.neo4j.transaction.Neo4jTransactionManager; -import org.springframework.transaction.annotation.EnableTransactionManagement; - -@Configuration -@EnableTransactionManagement -@ComponentScan(basePackages = { "com.baeldung.spring.data.neo4j.services" }) -@EnableNeo4jRepositories(basePackages = "com.baeldung.spring.data.neo4j.repository") -@Profile({ "embedded", "test" }) -public class MovieDatabaseNeo4jTestConfiguration { - - @Bean - public org.neo4j.ogm.config.Configuration getConfiguration() { - org.neo4j.ogm.config.Configuration config = new Builder().build(); - return config; - } - - @Bean - public SessionFactory getSessionFactory() { - return new SessionFactory(getConfiguration(), "com.baeldung.spring.data.neo4j.domain"); - } - - @Bean - public Neo4jTransactionManager transactionManager() { - return new Neo4jTransactionManager(getSessionFactory()); - } - -} diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/Neo4jConfig.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/Neo4jConfig.java new file mode 100644 index 0000000000..7571d01c68 --- /dev/null +++ b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/config/Neo4jConfig.java @@ -0,0 +1,14 @@ +package com.baeldung.spring.data.neo4j.config; + +import org.neo4j.cypherdsl.core.renderer.Dialect; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class Neo4jConfig { + @Bean + org.neo4j.cypherdsl.core.renderer.Configuration cypherDslConfiguration() { + return org.neo4j.cypherdsl.core.renderer.Configuration.newConfig() + .withDialect(Dialect.NEO4J_5).build(); + } +} diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Author.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Author.java new file mode 100644 index 0000000000..69f035dcae --- /dev/null +++ b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Author.java @@ -0,0 +1,48 @@ +package com.baeldung.spring.data.neo4j.domain; + + +import org.springframework.data.neo4j.core.schema.Id; +import org.springframework.data.neo4j.core.schema.Node; +import org.springframework.data.neo4j.core.schema.Relationship; + +import java.util.List; + +@Node("Author") +public class Author { + @Id + private Long id; + + private String name; + + @Relationship(type = "WRITTEN_BY", direction = Relationship.Direction.INCOMING) + private List books; + + public Author(Long id, String name) { + this.id = id; + this.name = 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; + } + + public List getBooks() { + return books; + } + + public void setBooks(List books) { + this.books = books; + } +} diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Book.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Book.java new file mode 100644 index 0000000000..4e6aff6798 --- /dev/null +++ b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Book.java @@ -0,0 +1,58 @@ +package com.baeldung.spring.data.neo4j.domain; + +import org.springframework.data.neo4j.core.schema.Id; +import org.springframework.data.neo4j.core.schema.Node; +import org.springframework.data.neo4j.core.schema.Property; +import org.springframework.data.neo4j.core.schema.Relationship; + +@Node("Book") +public class Book { + @Id + private String isbn; + + @Property("name") + private String title; + + private Integer year; + + @Relationship(type = "WRITTEN_BY", direction = Relationship.Direction.OUTGOING) + private Author author; + + public Book(String isbn, String title, Integer year) { + this.isbn = isbn; + this.title = title; + this.year = year; + } + + public String getIsbn() { + return isbn; + } + + public void setIsbn(String isbn) { + this.isbn = isbn; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Integer getYear() { + return year; + } + + public void setYear(Integer year) { + this.year = year; + } + + public Author getAuthor() { + return author; + } + + public void setAuthor(Author author) { + this.author = author; + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Car.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Car.java deleted file mode 100644 index 455407a92b..0000000000 --- a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Car.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.baeldung.spring.data.neo4j.domain; - -import org.neo4j.ogm.annotation.GeneratedValue; -import org.neo4j.ogm.annotation.Id; -import org.neo4j.ogm.annotation.NodeEntity; -import org.neo4j.ogm.annotation.Relationship; - -@NodeEntity -public class Car { - @Id @GeneratedValue - private Long id; - - private String make; - - @Relationship(direction = "INCOMING") - private Company company; - - public Car(String make, String model) { - this.make = make; - this.model = model; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getMake() { - return make; - } - - public void setMake(String make) { - this.make = make; - } - - public String getModel() { - return model; - } - - public void setModel(String model) { - this.model = model; - } - - private String model; -} diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Company.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Company.java deleted file mode 100644 index 4422ade44f..0000000000 --- a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Company.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.baeldung.spring.data.neo4j.domain; - -import org.neo4j.ogm.annotation.NodeEntity; -import org.neo4j.ogm.annotation.Relationship; - -@NodeEntity -public class Company { - private Long id; - - private String name; - - @Relationship(type="owns") - private Car car; - - public Company(String name) { - this.name = 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; - } - - public Car getCar() { - return car; - } - - public void setCar(Car car) { - this.car = car; - } -} diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Movie.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Movie.java deleted file mode 100644 index 996a661b07..0000000000 --- a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Movie.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.baeldung.spring.data.neo4j.domain; - -import com.fasterxml.jackson.annotation.JsonIdentityInfo; -import com.voodoodyne.jackson.jsog.JSOGGenerator; - -import org.neo4j.ogm.annotation.GeneratedValue; -import org.neo4j.ogm.annotation.Id; -import org.neo4j.ogm.annotation.NodeEntity; -import org.neo4j.ogm.annotation.Relationship; - -import java.util.Collection; -import java.util.List; - -@JsonIdentityInfo(generator = JSOGGenerator.class) - -@NodeEntity -public class Movie { - @Id @GeneratedValue - Long id; - - private String title; - - private int released; - private String tagline; - - @Relationship(type = "ACTED_IN", direction = Relationship.INCOMING) - private List roles; - - public Movie() { - } - - public String getTitle() { - return title; - } - - public int getReleased() { - return released; - } - - public String getTagline() { - return tagline; - } - - public Collection getRoles() { - return roles; - } - - public void setTitle(String title) { - this.title = title; - } - - public void setReleased(int released) { - this.released = released; - } - - public void setTagline(String tagline) { - this.tagline = tagline; - } - - public void setRoles(List roles) { - this.roles = roles; - } - -} diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Person.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Person.java deleted file mode 100644 index 453ca1c3f3..0000000000 --- a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Person.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.baeldung.spring.data.neo4j.domain; - -import com.fasterxml.jackson.annotation.JsonIdentityInfo; -import com.voodoodyne.jackson.jsog.JSOGGenerator; - -import org.neo4j.ogm.annotation.GeneratedValue; -import org.neo4j.ogm.annotation.Id; -import org.neo4j.ogm.annotation.NodeEntity; -import org.neo4j.ogm.annotation.Relationship; - -import java.util.List; - -@JsonIdentityInfo(generator = JSOGGenerator.class) -@NodeEntity -public class Person { - @Id @GeneratedValue - Long id; - - private String name; - private int born; - - @Relationship(type = "ACTED_IN") - private List movies; - - public Person() { - } - - public String getName() { - return name; - } - - public int getBorn() { - return born; - } - - public List getMovies() { - return movies; - } - - public void setName(String name) { - this.name = name; - } - - public void setBorn(int born) { - this.born = born; - } - - public void setMovies(List movies) { - this.movies = movies; - } - -} diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Role.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Role.java deleted file mode 100644 index 5a18837dae..0000000000 --- a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/domain/Role.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.baeldung.spring.data.neo4j.domain; - -import com.fasterxml.jackson.annotation.JsonIdentityInfo; -import com.voodoodyne.jackson.jsog.JSOGGenerator; -import org.neo4j.ogm.annotation.EndNode; -import org.neo4j.ogm.annotation.GeneratedValue; -import org.neo4j.ogm.annotation.Id; -import org.neo4j.ogm.annotation.RelationshipEntity; -import org.neo4j.ogm.annotation.StartNode; - -import java.util.Collection; - -@JsonIdentityInfo(generator = JSOGGenerator.class) -@RelationshipEntity(type = "ACTED_IN") -public class Role { - @Id @GeneratedValue - Long id; - private Collection roles; - @StartNode - private Person person; - @EndNode - private Movie movie; - - public Role() { - } - - public Collection getRoles() { - return roles; - } - - public Person getPerson() { - return person; - } - - public Movie getMovie() { - return movie; - } - - public void setRoles(Collection roles) { - this.roles = roles; - } - - public void setPerson(Person person) { - this.person = person; - } - - public void setMovie(Movie movie) { - this.movie = movie; - } -} diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repository/AuthorRepository.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repository/AuthorRepository.java new file mode 100644 index 0000000000..16949dfeef --- /dev/null +++ b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repository/AuthorRepository.java @@ -0,0 +1,16 @@ +package com.baeldung.spring.data.neo4j.repository; + +import com.baeldung.spring.data.neo4j.domain.Author; +import com.baeldung.spring.data.neo4j.domain.Book; +import org.springframework.data.neo4j.repository.Neo4jRepository; +import org.springframework.data.neo4j.repository.query.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface AuthorRepository extends Neo4jRepository { + @Query("MATCH (b:Book)-[:WRITTEN_BY]->(a:Author) WHERE a.name = $name AND b.year > $year RETURN b") + List findBooksAfterYear(@Param("name") String name, @Param("year") Integer year); +} diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repository/BookRepository.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repository/BookRepository.java new file mode 100644 index 0000000000..0489ff3c30 --- /dev/null +++ b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repository/BookRepository.java @@ -0,0 +1,14 @@ +package com.baeldung.spring.data.neo4j.repository; + + +import com.baeldung.spring.data.neo4j.domain.Book; +import org.springframework.data.neo4j.repository.Neo4jRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface BookRepository extends Neo4jRepository { + Book findOneByTitle(String title); + List findAllByYear(Integer year); +} \ No newline at end of file diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repository/MovieRepository.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repository/MovieRepository.java deleted file mode 100644 index dde946ea73..0000000000 --- a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repository/MovieRepository.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.baeldung.spring.data.neo4j.repository; - -import com.baeldung.spring.data.neo4j.domain.Movie; -import org.springframework.data.neo4j.annotation.Query; -import org.springframework.data.neo4j.repository.Neo4jRepository; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; - -import java.util.Collection; -import java.util.List; -import java.util.Map; - -@Repository -public interface MovieRepository extends Neo4jRepository { - - Movie findByTitle(@Param("title") String title); - - @Query("MATCH (m:Movie) WHERE m.title =~ ('(?i).*'+{title}+'.*') RETURN m") - Collection findByTitleContaining(@Param("title") String title); - - @Query("MATCH (m:Movie)<-[:ACTED_IN]-(a:Person) RETURN m.title as movie, collect(a.name) as cast LIMIT {limit}") - List> graph(@Param("limit") int limit); -} diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repository/PersonRepository.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repository/PersonRepository.java deleted file mode 100644 index 22094d26b6..0000000000 --- a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/repository/PersonRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.baeldung.spring.data.neo4j.repository; - -import com.baeldung.spring.data.neo4j.domain.Person; -import org.springframework.data.neo4j.repository.Neo4jRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface PersonRepository extends Neo4jRepository { -} diff --git a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/services/MovieService.java b/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/services/MovieService.java deleted file mode 100644 index 086bf48bfa..0000000000 --- a/persistence-modules/spring-data-neo4j/src/main/java/com/baeldung/spring/data/neo4j/services/MovieService.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.baeldung.spring.data.neo4j.services; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -import com.baeldung.spring.data.neo4j.repository.MovieRepository; - -import java.util.*; - -@Service -@Transactional -public class MovieService { - - @Autowired - private MovieRepository movieRepository; - - private Map toD3Format(Iterator> result) { - List> nodes = new ArrayList<>(); - List> rels = new ArrayList<>(); - int i = 0; - while (result.hasNext()) { - Map row = result.next(); - nodes.add(map("title", row.get("movie"), "label", "movie")); - int target = i; - i++; - for (Object name : (Collection) row.get("cast")) { - Map actor = map("title", name, "label", "actor"); - int source = nodes.indexOf(actor); - if (source == -1) { - nodes.add(actor); - source = i++; - } - rels.add(map("source", source, "target", target)); - } - } - return map("nodes", nodes, "links", rels); - } - - private Map map(String key1, Object value1, String key2, Object value2) { - Map result = new HashMap<>(2); - result.put(key1, value1); - result.put(key2, value2); - return result; - } - - public Map graph(int limit) { - Iterator> result = movieRepository.graph(limit).iterator(); - return toD3Format(result); - } -} diff --git a/persistence-modules/spring-data-neo4j/src/main/resources/application.properties b/persistence-modules/spring-data-neo4j/src/main/resources/application.properties new file mode 100644 index 0000000000..6a0b6712fd --- /dev/null +++ b/persistence-modules/spring-data-neo4j/src/main/resources/application.properties @@ -0,0 +1,3 @@ +spring.neo4j.uri=bolt://localhost:7687 +spring.neo4j.authentication.username=neo4j +spring.neo4j.authentication.password=password \ No newline at end of file diff --git a/persistence-modules/spring-data-neo4j/src/main/resources/test.png b/persistence-modules/spring-data-neo4j/src/main/resources/test.png deleted file mode 100644 index c3b5e80276..0000000000 Binary files a/persistence-modules/spring-data-neo4j/src/main/resources/test.png and /dev/null differ diff --git a/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/SpringContextTest.java b/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/SpringContextTest.java deleted file mode 100644 index 7029905c49..0000000000 --- a/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/SpringContextTest.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.baeldung; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import com.baeldung.spring.data.neo4j.config.MovieDatabaseNeo4jTestConfiguration; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = MovieDatabaseNeo4jTestConfiguration.class) -@ActiveProfiles(profiles = "test") -public class SpringContextTest { - - @Test - public void whenSpringContextIsBootstrapped_thenNoExceptions() { - } -} diff --git a/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/spring/data/neo4j/BookAndAuthorRepositoryIntegrationTest.java b/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/spring/data/neo4j/BookAndAuthorRepositoryIntegrationTest.java new file mode 100644 index 0000000000..f08af19825 --- /dev/null +++ b/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/spring/data/neo4j/BookAndAuthorRepositoryIntegrationTest.java @@ -0,0 +1,69 @@ +package com.baeldung.spring.data.neo4j; + +import com.baeldung.spring.data.neo4j.domain.Book; +import com.baeldung.spring.data.neo4j.repository.AuthorRepository; +import com.baeldung.spring.data.neo4j.repository.BookRepository; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.neo4j.harness.Neo4j; +import org.neo4j.harness.Neo4jBuilders; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.data.neo4j.DataNeo4jTest; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; + +import java.util.List; + +@DataNeo4jTest +public class BookAndAuthorRepositoryIntegrationTest { + + private static Neo4j newServer; + + @BeforeAll + static void initializeNeo4j() { + newServer = Neo4jBuilders.newInProcessBuilder() + .withDisabledServer() + .withFixture("CREATE (b:Book {isbn: '978-0547928210', name: 'The Fellowship of the Ring', year: 1954})" + + "-[:WRITTEN_BY]->(a:Author {id: 1, name: 'J. R. R. Tolkien'})" + + "CREATE (b2:Book {isbn: '978-0547928203', name: 'The Two Towers', year: 1956})-[:WRITTEN_BY]->(a)") + .build(); + } + + @AfterAll + static void stopNeo4j() { + newServer.close(); + } + + @DynamicPropertySource + static void neo4jProperties(DynamicPropertyRegistry registry) { + registry.add("spring.neo4j.uri", newServer::boltURI); + registry.add("spring.neo4j.authentication.username", () -> "neo4j"); + registry.add("spring.neo4j.authentication.password", () -> "null"); + } + + @Autowired + private BookRepository bookRepository; + + @Autowired + private AuthorRepository authorRepository; + + @Test + void givenBookExists_whenFindOneByTitle_thenBookIsReturned() { + Book book = bookRepository.findOneByTitle("The Two Towers"); + Assertions.assertEquals("978-0547928203", book.getIsbn()); + } + + @Test + void givenOneBookExistsForYear_whenFindAllByYear_thenOneBookIsReturned() { + List books = bookRepository.findAllByYear(1954); + Assertions.assertEquals(1, books.size()); + } + + @Test + void givenOneBookExistsAfterYear_whenFindBooksAfterYear_thenOneBookIsReturned() { + List books = authorRepository.findBooksAfterYear("J. R. R. Tolkien", 1955); + Assertions.assertEquals(1, books.size()); + } +} \ No newline at end of file diff --git a/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/spring/data/neo4j/MovieRepositoryIntegrationTest.java b/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/spring/data/neo4j/MovieRepositoryIntegrationTest.java deleted file mode 100644 index 3d9215f32f..0000000000 --- a/persistence-modules/spring-data-neo4j/src/test/java/com/baeldung/spring/data/neo4j/MovieRepositoryIntegrationTest.java +++ /dev/null @@ -1,131 +0,0 @@ -package com.baeldung.spring.data.neo4j; - -import com.baeldung.spring.data.neo4j.config.MovieDatabaseNeo4jTestConfiguration; -import com.baeldung.spring.data.neo4j.domain.Movie; -import com.baeldung.spring.data.neo4j.domain.Person; -import com.baeldung.spring.data.neo4j.domain.Role; -import com.baeldung.spring.data.neo4j.repository.MovieRepository; -import com.baeldung.spring.data.neo4j.repository.PersonRepository; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; - -import java.util.*; - -import static junit.framework.TestCase.assertNull; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = MovieDatabaseNeo4jTestConfiguration.class) -@ActiveProfiles(profiles = "test") -public class MovieRepositoryIntegrationTest { - - @Autowired - private MovieRepository movieRepository; - - @Autowired - private PersonRepository personRepository; - - public MovieRepositoryIntegrationTest() { - } - - @Before - public void initializeDatabase() { - System.out.println("seeding embedded database"); - Movie italianJob = new Movie(); - italianJob.setTitle("The Italian Job"); - italianJob.setReleased(1999); - movieRepository.save(italianJob); - - Person mark = new Person(); - mark.setName("Mark Wahlberg"); - personRepository.save(mark); - - Role charlie = new Role(); - charlie.setMovie(italianJob); - charlie.setPerson(mark); - Collection roleNames = new HashSet<>(); - roleNames.add("Charlie Croker"); - charlie.setRoles(roleNames); - List roles = new ArrayList<>(); - roles.add(charlie); - italianJob.setRoles(roles); - movieRepository.save(italianJob); - } - - @Test - @DirtiesContext - public void testFindByTitle() { - System.out.println("findByTitle"); - String title = "The Italian Job"; - Movie result = movieRepository.findByTitle(title); - assertNotNull(result); - assertEquals(1999, result.getReleased()); - } - - @Test - @DirtiesContext - public void testCount() { - System.out.println("count"); - long movieCount = movieRepository.count(); - assertNotNull(movieCount); - assertEquals(1, movieCount); - } - - @Test - @DirtiesContext - public void testFindAll() { - System.out.println("findAll"); - Collection result = (Collection) movieRepository.findAll(); - assertNotNull(result); - assertEquals(1, result.size()); - } - - @Test - @DirtiesContext - public void testFindByTitleContaining() { - System.out.println("findByTitleContaining"); - String title = "Italian"; - Collection result = movieRepository.findByTitleContaining(title); - assertNotNull(result); - assertEquals(1, result.size()); - } - - @Test - @DirtiesContext - public void testGraph() { - System.out.println("graph"); - List> graph = movieRepository.graph(5); - assertEquals(1, graph.size()); - Map map = graph.get(0); - assertEquals(2, map.size()); - String[] cast = (String[]) map.get("cast"); - String movie = (String) map.get("movie"); - assertEquals("The Italian Job", movie); - assertEquals("Mark Wahlberg", cast[0]); - } - - @Test - @DirtiesContext - public void testDeleteMovie() { - System.out.println("deleteMovie"); - movieRepository.delete(movieRepository.findByTitle("The Italian Job")); - assertNull(movieRepository.findByTitle("The Italian Job")); - } - - @Test - @DirtiesContext - public void testDeleteAll() { - System.out.println("deleteAll"); - movieRepository.deleteAll(); - Collection result = (Collection) movieRepository.findAll(); - assertEquals(0, result.size()); - } -} diff --git a/persistence-modules/spring-data-shardingsphere/README.md b/persistence-modules/spring-data-shardingsphere/README.md new file mode 100644 index 0000000000..865b46fc96 --- /dev/null +++ b/persistence-modules/spring-data-shardingsphere/README.md @@ -0,0 +1,2 @@ +## Relevant Articles +- [A Guide to ShardingSphere](https://www.baeldung.com/java-shardingsphere) diff --git a/persistence-modules/spring-data-shardingsphere/src/test/java/com/baeldung/shardingsphere/OrderServiceIntegrationTest.java b/persistence-modules/spring-data-shardingsphere/src/test/java/com/baeldung/shardingsphere/OrderServiceLiveTest.java similarity index 98% rename from persistence-modules/spring-data-shardingsphere/src/test/java/com/baeldung/shardingsphere/OrderServiceIntegrationTest.java rename to persistence-modules/spring-data-shardingsphere/src/test/java/com/baeldung/shardingsphere/OrderServiceLiveTest.java index 938d250058..139081182f 100644 --- a/persistence-modules/spring-data-shardingsphere/src/test/java/com/baeldung/shardingsphere/OrderServiceIntegrationTest.java +++ b/persistence-modules/spring-data-shardingsphere/src/test/java/com/baeldung/shardingsphere/OrderServiceLiveTest.java @@ -21,7 +21,7 @@ import java.util.List; @Testcontainers @SpringBootTest -class OrderServiceIntegrationTest { +class OrderServiceLiveTest { @Container static MySQLContainer mySQLContainer1 = new MySQLContainer<>("mysql:8.0.23") diff --git a/pom.xml b/pom.xml index 8fb2234a23..fa35813c11 100644 --- a/pom.xml +++ b/pom.xml @@ -346,7 +346,7 @@ core-java-modules/core-java-serialization core-java-modules/core-java-lang core-java-modules/core-java-lang-math-3 - core-java-modules/core-java-collections-conversions-2 + core-java-modules/core-java-streams-2 @@ -355,6 +355,7 @@ + libraries-jdk8 @@ -367,7 +368,6 @@ persistence-modules/hibernate-ogm persistence-modules/java-cassandra persistence-modules/spring-data-cassandra-reactive - persistence-modules/spring-data-neo4j java-nashorn jeromq @@ -524,7 +524,7 @@ core-java-modules/core-java-serialization core-java-modules/core-java-lang core-java-modules/core-java-lang-math-3 - core-java-modules/core-java-collections-conversions-2 + core-java-modules/core-java-streams-2 @@ -544,7 +544,6 @@ persistence-modules/hibernate-ogm persistence-modules/java-cassandra persistence-modules/spring-data-cassandra-reactive - persistence-modules/spring-data-neo4j java-nashorn @@ -704,7 +703,6 @@ osgi spring-katharsis logging-modules - spring-boot-documentation spring-boot-modules apache-httpclient apache-httpclient4 @@ -759,6 +757,7 @@ algorithms-modules apache-libraries + apache-libraries-2 apache-poi apache-velocity di-modules @@ -871,7 +870,7 @@ libraries-apache-commons-2 libraries-apache-commons-collections libraries-apache-commons-io - libraries-data-2 + libraries-data-io libraries-files libraries-http @@ -939,6 +938,7 @@ image-processing language-interop gradle-modules/gradle/maven-to-gradle + persistence-modules/spring-data-neo4j @@ -976,7 +976,6 @@ osgi spring-katharsis logging-modules - spring-boot-documentation spring-boot-modules apache-httpclient apache-httpclient4 @@ -1025,6 +1024,7 @@ algorithms-modules apache-libraries + apache-libraries-2 apache-poi apache-velocity di-modules @@ -1141,7 +1141,7 @@ libraries-apache-commons-2 libraries-apache-commons-collections libraries-apache-commons-io - libraries-data-2 + libraries-data-io libraries-files libraries-http @@ -1210,6 +1210,7 @@ image-processing language-interop gradle-modules/gradle/maven-to-gradle + persistence-modules/spring-data-neo4j @@ -1260,7 +1261,7 @@ 2.2 1.3 4.4.0 - 1.12.13 + 1.14.6 @@ -1277,17 +1278,17 @@ 1.36 2.21.0 4.4 - 2.11.0 + 2.13.0 2.6 - 3.12.0 + 3.13.0 1.5.0 3.3.2 4.0.1 1.2 2.3.3 1.2 - 2.13.3 - 1.4 + 2.15.2 + 1.5 1.9.2 5.9.2 1.3.2 diff --git a/quarkus-modules/quarkus-vs-springboot/pom.xml b/quarkus-modules/quarkus-vs-springboot/pom.xml index 2e9d0b8a7f..4ec10f385d 100644 --- a/quarkus-modules/quarkus-vs-springboot/pom.xml +++ b/quarkus-modules/quarkus-vs-springboot/pom.xml @@ -16,7 +16,7 @@ quarkus-project - spring-project + \ No newline at end of file diff --git a/spring-boot-documentation/pom.xml b/spring-boot-documentation/pom.xml deleted file mode 100644 index d718f33a99..0000000000 --- a/spring-boot-documentation/pom.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - 4.0.0 - com.baeldung.spring-boot-documentation - spring-boot-documentation - 1.0.0-SNAPSHOT - spring-boot-documentation - pom - - - com.baeldung - parent-boot-3 - 0.0.1-SNAPSHOT - ../parent-boot-3 - - - - springwolf - - - - - - org.junit - junit-bom - ${junit-jupiter.version} - pom - import - - - org.springframework.boot - spring-boot-dependencies - ${spring-boot.version} - pom - import - - - - - - 3.3.2 - - - diff --git a/spring-boot-documentation/springwolf/pom.xml b/spring-boot-documentation/springwolf/pom.xml deleted file mode 100644 index 4bd9f24065..0000000000 --- a/spring-boot-documentation/springwolf/pom.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - 4.0.0 - springwolf - 0.0.1-SNAPSHOT - springwolf - Documentation Spring Event Driven API Using AsyncAPI and Springwolf - - - com.baeldung.spring-boot-documentation - spring-boot-documentation - 1.0.0-SNAPSHOT - - - - - org.springframework.boot - spring-boot-starter - - - org.springframework.boot - spring-boot-starter-web - - - org.springframework.kafka - spring-kafka - - - io.swagger.core.v3 - swagger-core-jakarta - ${swagger-core.version} - - - io.github.springwolf - springwolf-kafka - ${springwolf-kafka.version} - - - io.github.springwolf - springwolf-ui - ${springwolf-ui.version} - - - org.projectlombok - lombok - ${lombok.version} - - - org.springframework.kafka - spring-kafka-test - test - - - org.testcontainers - junit-jupiter - ${testcontainers-kafka.version} - test - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - com.baeldung.boot.documentation.springwolf.SpringwolfApplication - - - - - - - 2.2.11 - 0.12.1 - 0.8.0 - 1.18.3 - - - diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index 0679f33ae7..a2febc8156 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -44,7 +44,7 @@ spring-boot-graphql spring-boot-groovy - spring-boot-jasypt + spring-boot-jsp spring-boot-keycloak spring-boot-keycloak-2 @@ -97,6 +97,7 @@ spring-boot-properties-3 spring-boot-properties-4 spring-boot-properties-migrator-demo + spring-boot-documentation diff --git a/spring-boot-modules/spring-boot-3/README.md b/spring-boot-modules/spring-boot-3/README.md index e99eb79127..8791aaae1f 100644 --- a/spring-boot-modules/spring-boot-3/README.md +++ b/spring-boot-modules/spring-boot-3/README.md @@ -7,3 +7,4 @@ - [Using Java Records with JPA](https://www.baeldung.com/spring-jpa-java-records) - [HTTP Interface in Spring 6](https://www.baeldung.com/spring-6-http-interface) - [Working with Virtual Threads in Spring 6](https://www.baeldung.com/spring-6-virtual-threads) +- [Docker Compose Support in Spring Boot 3](https://www.baeldung.com/ops/docker-compose-support-spring-boot) diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/QueryService.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/QueryService.java index 4c1e73e530..7e2dbd93e9 100644 --- a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/QueryService.java +++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/QueryService.java @@ -27,14 +27,15 @@ public class QueryService { return entityManager.createQuery(query).getResultList(); } - public BookRecord findBookById(Long id) { + public BookRecord findBookByTitle(String title) { TypedQuery query = entityManager - .createQuery("SELECT new com.baeldung.recordswithjpa.records.BookRecord(b.id, b.title, b.author, b.isbn) " + - "FROM Book b WHERE b.id = :id", BookRecord.class); - query.setParameter("id", id); + .createQuery("SELECT new com.baeldung.recordswithjpa.records.BookRecord(b.id, b.title, b.author, b.isbn) " + + "FROM Book b WHERE b.title = :title", BookRecord.class); + query.setParameter("title", title); return query.getSingleResult(); } + public List findAllBooksUsingMapping() { Query query = entityManager.createNativeQuery("SELECT * FROM book", "BookRecordMapping"); return query.getResultList(); diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/Author.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/Author.java new file mode 100644 index 0000000000..4f2fa664db --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/Author.java @@ -0,0 +1,9 @@ +package com.baeldung.recordswithjpa.embeddable; + +import jakarta.persistence.Embeddable; + +@Embeddable +public record Author( + String firstName, + String lastName +) {} diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/AuthorInstallator.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/AuthorInstallator.java new file mode 100644 index 0000000000..7debfb5071 --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/AuthorInstallator.java @@ -0,0 +1,23 @@ +package com.baeldung.recordswithjpa.embeddable; + +import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.metamodel.spi.EmbeddableInstantiator; +import org.hibernate.metamodel.spi.ValueAccess; + +public class AuthorInstallator implements EmbeddableInstantiator { + + public boolean isInstance(Object object, SessionFactoryImplementor sessionFactory) { + return object instanceof Author; + } + + public boolean isSameClass(Object object, SessionFactoryImplementor sessionFactory) { + return object.getClass().equals(Author.class); + } + + @Override + public Object instantiate(final ValueAccess valueAccess, final SessionFactoryImplementor sessionFactoryImplementor) { + final String firstName = valueAccess.getValue(0, String.class); + final String secondName = valueAccess.getValue(1, String.class); + return new Author(firstName, secondName); + } +} diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/EmbeddableBook.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/EmbeddableBook.java new file mode 100644 index 0000000000..74bd7d78ae --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/embeddable/EmbeddableBook.java @@ -0,0 +1,65 @@ +package com.baeldung.recordswithjpa.embeddable; + +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import org.hibernate.annotations.EmbeddableInstantiator; + +@Entity +@Table(name = "embeadable_author_book") +public class EmbeddableBook { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String title; + @Embedded + @EmbeddableInstantiator(AuthorInstallator.class) + private Author author; + private String isbn; + + public EmbeddableBook() { + } + + public EmbeddableBook(Long id, String title, Author author, String isbn) { + this.id = id; + this.title = title; + this.author = author; + this.isbn = isbn; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public Author getAuthor() { + return author; + } + + public void setAuthor(Author author) { + this.author = author; + } + + public String getIsbn() { + return isbn; + } + + public void setIsbn(String isbn) { + this.isbn = isbn; + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/repository/EmbeddableBookRepository.java b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/repository/EmbeddableBookRepository.java new file mode 100644 index 0000000000..3d6e558050 --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/main/java/com/baeldung/recordswithjpa/repository/EmbeddableBookRepository.java @@ -0,0 +1,14 @@ +package com.baeldung.recordswithjpa.repository; + +import com.baeldung.recordswithjpa.embeddable.EmbeddableBook; +import com.baeldung.recordswithjpa.embeddable.Author; +import java.util.List; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; + +public interface EmbeddableBookRepository extends CrudRepository { + @Query("SELECT b FROM EmbeddableBook b WHERE b.author = :author") + List findBookByAuthor(@Param("author") Author author); + +} diff --git a/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/QueryServiceIntegrationTest.java b/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/QueryServiceIntegrationTest.java index 011895e7fa..09c6805544 100644 --- a/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/QueryServiceIntegrationTest.java +++ b/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/QueryServiceIntegrationTest.java @@ -1,13 +1,8 @@ package com.baeldung.recordswithjpa; -import com.baeldung.recordswithjpa.entity.Book; import com.baeldung.recordswithjpa.records.BookRecord; -import com.baeldung.recordswithjpa.repository.BookRepository; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; import java.util.List; @@ -27,8 +22,8 @@ public class QueryServiceIntegrationTest extends RecordsAsJpaIntegrationTest { @Test void findBookById() { - BookRecord bookById = queryService.findBookById(1L); - assertEquals("The Lord of the Rings", bookById.title()); + BookRecord bookByTitle = queryService.findBookByTitle("The Lord of the Rings"); + assertNotNull(bookByTitle); } @Test diff --git a/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/RecordsAsJpaEmbeddableIntegrationTest.java b/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/RecordsAsJpaEmbeddableIntegrationTest.java new file mode 100644 index 0000000000..2d0b834def --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/RecordsAsJpaEmbeddableIntegrationTest.java @@ -0,0 +1,31 @@ +package com.baeldung.recordswithjpa; + +import com.baeldung.recordswithjpa.embeddable.Author; +import com.baeldung.recordswithjpa.embeddable.EmbeddableBook; +import com.baeldung.recordswithjpa.repository.EmbeddableBookRepository; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class RecordsAsJpaEmbeddableIntegrationTest { + @Autowired + protected EmbeddableBookRepository bookRepository; + + @BeforeEach + void setUp() { + + Author author = new Author("J.R.R.", "Tolkien"); + EmbeddableBook book1 = new EmbeddableBook(null, "The Lord of the Rings", author, "978-0544003415"); + EmbeddableBook book2 = new EmbeddableBook(null, "The Hobbit", author, "978-0547928227"); + + bookRepository.save(book1); + bookRepository.save(book2); + } + + @AfterEach + void tearDown() { + bookRepository.deleteAll(); + } +} diff --git a/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/repository/EmbeddableBookRepositoryIntegrationTest.java b/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/repository/EmbeddableBookRepositoryIntegrationTest.java new file mode 100644 index 0000000000..8f9e9680ba --- /dev/null +++ b/spring-boot-modules/spring-boot-3/src/test/java/com/baeldung/recordswithjpa/repository/EmbeddableBookRepositoryIntegrationTest.java @@ -0,0 +1,16 @@ +package com.baeldung.recordswithjpa.repository; + +import com.baeldung.recordswithjpa.RecordsAsJpaEmbeddableIntegrationTest; +import com.baeldung.recordswithjpa.embeddable.Author; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class EmbeddableBookRepositoryIntegrationTest extends RecordsAsJpaEmbeddableIntegrationTest { + + @Test + void findBookByAuthor() { + assertEquals(2, bookRepository.findBookByAuthor(new Author("J.R.R.", "Tolkien")).size()); + } + +} diff --git a/spring-boot-documentation/README.md b/spring-boot-modules/spring-boot-documentation/README.md similarity index 100% rename from spring-boot-documentation/README.md rename to spring-boot-modules/spring-boot-documentation/README.md diff --git a/spring-boot-documentation/springwolf/docker-compose.yml b/spring-boot-modules/spring-boot-documentation/docker-compose.yml similarity index 100% rename from spring-boot-documentation/springwolf/docker-compose.yml rename to spring-boot-modules/spring-boot-documentation/docker-compose.yml diff --git a/spring-boot-modules/spring-boot-documentation/pom.xml b/spring-boot-modules/spring-boot-documentation/pom.xml new file mode 100644 index 0000000000..587ad8473b --- /dev/null +++ b/spring-boot-modules/spring-boot-documentation/pom.xml @@ -0,0 +1,102 @@ + + + 4.0.0 + com.baeldung.spring-boot-documentation + spring-boot-documentation + 1.0.0-SNAPSHOT + spring-boot-documentation + Documentation Spring Event Driven API Using AsyncAPI and Springwolf + pom + + + com.baeldung + parent-boot-3 + 0.0.1-SNAPSHOT + ../../parent-boot-3/pom.xml + + + + + + org.junit + junit-bom + ${junit-jupiter.version} + pom + import + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.kafka + spring-kafka + + + io.swagger.core.v3 + swagger-core-jakarta + ${swagger-core.version} + + + io.github.springwolf + springwolf-kafka + ${springwolf-kafka.version} + + + io.github.springwolf + springwolf-ui + ${springwolf-ui.version} + + + org.projectlombok + lombok + ${lombok.version} + + + org.springframework.kafka + spring-kafka-test + test + + + org.testcontainers + junit-jupiter + ${testcontainers-kafka.version} + test + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.baeldung.boot.documentation.springwolf.SpringwolfApplication + + + + + + + 3.3.2 + 2.2.11 + 0.12.1 + 0.8.0 + 1.18.3 + + + diff --git a/spring-boot-documentation/springwolf/src/main/java/com/baeldung/boot/documentation/springwolf/SpringwolfApplication.java b/spring-boot-modules/spring-boot-documentation/src/main/java/com/baeldung/boot/documentation/springwolf/SpringwolfApplication.java similarity index 100% rename from spring-boot-documentation/springwolf/src/main/java/com/baeldung/boot/documentation/springwolf/SpringwolfApplication.java rename to spring-boot-modules/spring-boot-documentation/src/main/java/com/baeldung/boot/documentation/springwolf/SpringwolfApplication.java diff --git a/spring-boot-documentation/springwolf/src/main/java/com/baeldung/boot/documentation/springwolf/adapter/incoming/IncomingConsumer.java b/spring-boot-modules/spring-boot-documentation/src/main/java/com/baeldung/boot/documentation/springwolf/adapter/incoming/IncomingConsumer.java similarity index 100% rename from spring-boot-documentation/springwolf/src/main/java/com/baeldung/boot/documentation/springwolf/adapter/incoming/IncomingConsumer.java rename to spring-boot-modules/spring-boot-documentation/src/main/java/com/baeldung/boot/documentation/springwolf/adapter/incoming/IncomingConsumer.java diff --git a/spring-boot-documentation/springwolf/src/main/java/com/baeldung/boot/documentation/springwolf/adapter/outgoing/OutgoingProducer.java b/spring-boot-modules/spring-boot-documentation/src/main/java/com/baeldung/boot/documentation/springwolf/adapter/outgoing/OutgoingProducer.java similarity index 100% rename from spring-boot-documentation/springwolf/src/main/java/com/baeldung/boot/documentation/springwolf/adapter/outgoing/OutgoingProducer.java rename to spring-boot-modules/spring-boot-documentation/src/main/java/com/baeldung/boot/documentation/springwolf/adapter/outgoing/OutgoingProducer.java diff --git a/spring-boot-documentation/springwolf/src/main/java/com/baeldung/boot/documentation/springwolf/dto/IncomingPayloadDto.java b/spring-boot-modules/spring-boot-documentation/src/main/java/com/baeldung/boot/documentation/springwolf/dto/IncomingPayloadDto.java similarity index 100% rename from spring-boot-documentation/springwolf/src/main/java/com/baeldung/boot/documentation/springwolf/dto/IncomingPayloadDto.java rename to spring-boot-modules/spring-boot-documentation/src/main/java/com/baeldung/boot/documentation/springwolf/dto/IncomingPayloadDto.java diff --git a/spring-boot-documentation/springwolf/src/main/java/com/baeldung/boot/documentation/springwolf/dto/OutgoingPayloadDto.java b/spring-boot-modules/spring-boot-documentation/src/main/java/com/baeldung/boot/documentation/springwolf/dto/OutgoingPayloadDto.java similarity index 100% rename from spring-boot-documentation/springwolf/src/main/java/com/baeldung/boot/documentation/springwolf/dto/OutgoingPayloadDto.java rename to spring-boot-modules/spring-boot-documentation/src/main/java/com/baeldung/boot/documentation/springwolf/dto/OutgoingPayloadDto.java diff --git a/spring-boot-documentation/springwolf/src/main/java/com/baeldung/boot/documentation/springwolf/service/ProcessorService.java b/spring-boot-modules/spring-boot-documentation/src/main/java/com/baeldung/boot/documentation/springwolf/service/ProcessorService.java similarity index 100% rename from spring-boot-documentation/springwolf/src/main/java/com/baeldung/boot/documentation/springwolf/service/ProcessorService.java rename to spring-boot-modules/spring-boot-documentation/src/main/java/com/baeldung/boot/documentation/springwolf/service/ProcessorService.java diff --git a/spring-boot-documentation/springwolf/src/main/resources/application.properties b/spring-boot-modules/spring-boot-documentation/src/main/resources/application.properties similarity index 100% rename from spring-boot-documentation/springwolf/src/main/resources/application.properties rename to spring-boot-modules/spring-boot-documentation/src/main/resources/application.properties diff --git a/spring-boot-documentation/springwolf/src/test/java/com/baeldung/boot/documentation/springwolf/ApiIntegrationTest.java b/spring-boot-modules/spring-boot-documentation/src/test/java/com/baeldung/boot/documentation/springwolf/ApiIntegrationTest.java similarity index 100% rename from spring-boot-documentation/springwolf/src/test/java/com/baeldung/boot/documentation/springwolf/ApiIntegrationTest.java rename to spring-boot-modules/spring-boot-documentation/src/test/java/com/baeldung/boot/documentation/springwolf/ApiIntegrationTest.java diff --git a/spring-boot-documentation/springwolf/src/test/resources/asyncapi.json b/spring-boot-modules/spring-boot-documentation/src/test/resources/asyncapi.json similarity index 100% rename from spring-boot-documentation/springwolf/src/test/resources/asyncapi.json rename to spring-boot-modules/spring-boot-documentation/src/test/resources/asyncapi.json diff --git a/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SecurityConfig.java b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SecurityConfig.java index 1ad22d9397..3423f8eb2b 100644 --- a/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SecurityConfig.java +++ b/spring-boot-modules/spring-boot-keycloak/src/main/java/com/baeldung/keycloak/SecurityConfig.java @@ -2,6 +2,7 @@ package com.baeldung.keycloak; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -27,18 +28,30 @@ class SecurityConfig { return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl()); } + @Order(1) @Bean - public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + public SecurityFilterChain clientFilterChain(HttpSecurity http) throws Exception { http.authorizeRequests() - .antMatchers("/customers*") - .hasRole("USER") + .antMatchers("/") + .permitAll() .anyRequest() - .permitAll(); + .authenticated(); http.oauth2Login() .and() .logout() .addLogoutHandler(keycloakLogoutHandler) .logoutSuccessUrl("/"); + return http.build(); + } + + @Order(2) + @Bean + public SecurityFilterChain resourceServerFilterChain(HttpSecurity http) throws Exception { + http.authorizeRequests() + .antMatchers("/customers*") + .hasRole("USER") + .anyRequest() + .authenticated(); http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt); return http.build(); } diff --git a/spring-boot-modules/spring-boot-properties/pom.xml b/spring-boot-modules/spring-boot-properties/pom.xml index bf5f514725..dc1ab067a9 100644 --- a/spring-boot-modules/spring-boot-properties/pom.xml +++ b/spring-boot-modules/spring-boot-properties/pom.xml @@ -142,7 +142,7 @@ - 2022.0.1 + 2022.0.4 1.10 @ diff --git a/spring-cloud-modules/spring-cloud-bootstrap/application-config/book-service.properties b/spring-cloud-modules/spring-cloud-bootstrap/application-config/book-service.properties index 2ea30b9ab7..597899bd16 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/application-config/book-service.properties +++ b/spring-cloud-modules/spring-cloud-bootstrap/application-config/book-service.properties @@ -10,8 +10,8 @@ eureka.client.registryFetchIntervalSeconds = 5 management.security.sessions=never -logging.level.org.springframework.web.=debug -logging.level.org.springframework.security=debug +logging.level.org.springframework.web.=INFO +logging.level.org.springframework.security=INFO spring.redis.host=localhost spring.redis.port=6379 diff --git a/spring-cloud-modules/spring-cloud-bootstrap/application-config/gateway.properties b/spring-cloud-modules/spring-cloud-bootstrap/application-config/gateway.properties index 42e114450d..44d5267d10 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/application-config/gateway.properties +++ b/spring-cloud-modules/spring-cloud-bootstrap/application-config/gateway.properties @@ -6,8 +6,8 @@ eureka.client.registryFetchIntervalSeconds = 5 management.security.sessions=always -logging.level.org.springframework.web.=debug -logging.level.org.springframework.security=debug +logging.level.org.springframework.web.=INFO +logging.level.org.springframework.security=INFO spring.redis.host=localhost spring.redis.port=6379 diff --git a/spring-cloud-modules/spring-cloud-bootstrap/application-config/rating-service.properties b/spring-cloud-modules/spring-cloud-bootstrap/application-config/rating-service.properties index 059b87e4e7..89f8ee40fe 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/application-config/rating-service.properties +++ b/spring-cloud-modules/spring-cloud-bootstrap/application-config/rating-service.properties @@ -10,8 +10,8 @@ eureka.client.registryFetchIntervalSeconds = 5 management.security.sessions=never -logging.level.org.springframework.web.=debug -logging.level.org.springframework.security=debug +logging.level.org.springframework.web.=INFO +logging.level.org.springframework.security=INFO spring.redis.host=localhost spring.redis.port=6379 diff --git a/spring-cloud-modules/spring-cloud-bootstrap/application-config/zipkin.properties b/spring-cloud-modules/spring-cloud-bootstrap/application-config/zipkin.properties index ca3aed2263..1a689123cb 100644 --- a/spring-cloud-modules/spring-cloud-bootstrap/application-config/zipkin.properties +++ b/spring-cloud-modules/spring-cloud-bootstrap/application-config/zipkin.properties @@ -4,4 +4,4 @@ server.port=9411 eureka.client.region = default eureka.client.registryFetchIntervalSeconds = 5 -logging.level.org.springframework.web=debug +logging.level.org.springframework.web=INFO diff --git a/spring-cloud-modules/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/pom.xml b/spring-cloud-modules/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/pom.xml index ba923c4ae6..3e2b1632c7 100644 --- a/spring-cloud-modules/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/pom.xml +++ b/spring-cloud-modules/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/pom.xml @@ -46,7 +46,6 @@ 1.3.1.RELEASE Edgware.SR6 5.2.12.Final - 1.11.20 3.1.0 diff --git a/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/logback-test.xml b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..fb1f109a18 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-eureka/spring-cloud-eureka-feign-client-integration-test/src/test/resources/logback-test.xml @@ -0,0 +1,17 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-openfeign-2/src/main/resources/application.properties b/spring-cloud-modules/spring-cloud-openfeign-2/src/main/resources/application.properties index aa0dc6a382..0a31d79ee0 100644 --- a/spring-cloud-modules/spring-cloud-openfeign-2/src/main/resources/application.properties +++ b/spring-cloud-modules/spring-cloud-openfeign-2/src/main/resources/application.properties @@ -4,7 +4,7 @@ feign.okhttp.enabled=true server.port=8085 spring.main.allow-bean-definition-overriding=true -logging.level.com.baeldung.cloud.openfeign.client=DEBUG +logging.level.com.baeldung.cloud.openfeign.client=INFO feign.hystrix.enabled=true spring.cloud.openfeign.client.config.postClient.url=https://jsonplaceholder.typicode.com/posts/ \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-stream/spring-cloud-stream-rabbit/src/test/resources/logback-test.xml b/spring-cloud-modules/spring-cloud-stream/spring-cloud-stream-rabbit/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..233cfa7e23 --- /dev/null +++ b/spring-cloud-modules/spring-cloud-stream/spring-cloud-stream-rabbit/src/test/resources/logback-test.xml @@ -0,0 +1,17 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + \ No newline at end of file diff --git a/aws-modules/aws-s3-v2/src/main/resources/logback.xml b/spring-cloud-modules/spring-cloud-task/springcloudtasksink/src/test/resources/logback-test.xml similarity index 60% rename from aws-modules/aws-s3-v2/src/main/resources/logback.xml rename to spring-cloud-modules/spring-cloud-task/springcloudtasksink/src/test/resources/logback-test.xml index 91d3d0cfa6..2a5eefdd1f 100644 --- a/aws-modules/aws-s3-v2/src/main/resources/logback.xml +++ b/spring-cloud-modules/spring-cloud-task/springcloudtasksink/src/test/resources/logback-test.xml @@ -1,14 +1,15 @@ - - - - %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - - - - - - - - - + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + \ No newline at end of file diff --git a/spring-cloud-modules/spring-cloud-zuul-fallback/spring-cloud-zuul-fallback-weather-service/src/test/resources/logback-test.xml b/spring-cloud-modules/spring-cloud-zuul-fallback/spring-cloud-zuul-fallback-weather-service/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..4ff950099a --- /dev/null +++ b/spring-cloud-modules/spring-cloud-zuul-fallback/spring-cloud-zuul-fallback-weather-service/src/test/resources/logback-test.xml @@ -0,0 +1,17 @@ + + + + + # Pattern of log message for console appender + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + \ No newline at end of file diff --git a/spring-core-4/README.md b/spring-core-4/README.md index a0f5ac97f9..68aec6ef08 100644 --- a/spring-core-4/README.md +++ b/spring-core-4/README.md @@ -6,4 +6,5 @@ This module contains articles about core Spring functionality - [Creating Spring Beans Through Factory Methods](https://www.baeldung.com/spring-beans-factory-methods) - [Spring BeanPostProcessor](https://www.baeldung.com/spring-beanpostprocessor) +- [Escape HTML Symbols in Java](https://www.baeldung.com/java-escape-html-symbols) - More articles: [[<-- prev]](/spring-core-3) diff --git a/spring-integration/README.md b/spring-integration/README.md index 710af2a8c7..2c1de2353f 100644 --- a/spring-integration/README.md +++ b/spring-integration/README.md @@ -8,6 +8,7 @@ This module contains articles about Spring Integration - [Spring Integration Java DSL](https://www.baeldung.com/spring-integration-java-dsl) - [Using Subflows in Spring Integration](https://www.baeldung.com/spring-integration-subflows) - [Transaction Support in Spring Integration](https://www.baeldung.com/spring-integration-transaction) +- [Receiving PostreSQL Push Notifications with Spring Integration](https://www.baeldung.com/spring-receiving-postresql-push-notifications) ### Running the Sample Executing the `mvn exec:java` maven command (either from the command line or from an IDE) will start up the application. Follow the command prompt for further instructions. diff --git a/spring-integration/src/test/resources/logback-test.xml b/spring-integration/src/test/resources/logback-test.xml index 8f1be4eb7a..98bfc86d71 100644 --- a/spring-integration/src/test/resources/logback-test.xml +++ b/spring-integration/src/test/resources/logback-test.xml @@ -9,6 +9,8 @@ + + diff --git a/spring-kafka-2/README.md b/spring-kafka-2/README.md index ea2af99e35..d71e75f15c 100644 --- a/spring-kafka-2/README.md +++ b/spring-kafka-2/README.md @@ -6,3 +6,4 @@ This module contains articles about Spring with Kafka - [Implementing Retry in Kafka Consumer](https://www.baeldung.com/spring-retry-kafka-consumer) - [Spring Kafka: Configure Multiple Listeners on Same Topic](https://www.baeldung.com/spring-kafka-multiple-listeners-same-topic) +- [Understanding Kafka Topics and Partitions](https://www.baeldung.com/kafka-topics-partitions) diff --git a/spring-native/pom.xml b/spring-native/pom.xml index 55f17c833f..97eb33c1c7 100644 --- a/spring-native/pom.xml +++ b/spring-native/pom.xml @@ -17,17 +17,27 @@ - spring-release - Spring release - https://repo.spring.io/release + spring-milestone + Spring Milestone + https://repo.spring.io/milestone + + + spring-snapshot + Spring Snapshot + https://repo.spring.io/snapshot - spring-release - Spring release - https://repo.spring.io/release + spring-plugins-snapshot + Spring Plugins Snapshot + https://repo.spring.io/plugins-snapshot + + + spring-plugins-milestone + Spring Plugins Milestone + https://repo.spring.io/plugins-milestone diff --git a/spring-pulsar/README.md b/spring-pulsar/README.md new file mode 100644 index 0000000000..dd428c2cb2 --- /dev/null +++ b/spring-pulsar/README.md @@ -0,0 +1,2 @@ +## Relevant Articles +- [Getting Started With Apache Pulsar and Spring Boot](https://www.baeldung.com/spring-boot-apache-pulsar) diff --git a/spring-pulsar/pom.xml b/spring-pulsar/pom.xml new file mode 100644 index 0000000000..4c2fc0d9b4 --- /dev/null +++ b/spring-pulsar/pom.xml @@ -0,0 +1,48 @@ + + + 4.0.0 + spring-pulsar + 0.0.1-SNAPSHOT + spring-pulsar + Intro to Apache Pulsar with Spring + + + com.baeldung + parent-boot-3 + 0.0.1-SNAPSHOT + ../parent-boot-3 + + + + 17 + 0.2.0 + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.pulsar + spring-pulsar-spring-boot-starter + 0.2.0 + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/spring-pulsar/src/main/java/com/baeldung/springpulsar/PulsarConsumer.java b/spring-pulsar/src/main/java/com/baeldung/springpulsar/PulsarConsumer.java new file mode 100644 index 0000000000..7a483d97cb --- /dev/null +++ b/spring-pulsar/src/main/java/com/baeldung/springpulsar/PulsarConsumer.java @@ -0,0 +1,59 @@ +package com.baeldung.springpulsar; + +import org.apache.pulsar.client.api.DeadLetterPolicy; +import org.apache.pulsar.client.api.SubscriptionType; +import org.apache.pulsar.common.schema.SchemaType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.pulsar.annotation.PulsarListener; +import org.springframework.pulsar.listener.AckMode; +import org.springframework.stereotype.Service; + +@Service +public class PulsarConsumer { + + private static final String STRING_TOPIC = "string-topic"; + private static final String USER_TOPIC = "user-topic"; + private static final String USER_DEAD_LETTER_TOPIC = "user-dead-letter-topic"; + private final Logger LOGGER = LoggerFactory.getLogger(PulsarConsumer.class); + + @PulsarListener( + subscriptionName = "string-topic-subscription", + topics = STRING_TOPIC, + subscriptionType = SubscriptionType.Shared + ) + public void stringTopicListener(String str) { + LOGGER.info("Received String message: {}", str); + } + + @Bean + DeadLetterPolicy deadLetterPolicy() { + return DeadLetterPolicy.builder() + .maxRedeliverCount(10) + .deadLetterTopic(USER_DEAD_LETTER_TOPIC) + .build(); + } + + @PulsarListener( + subscriptionName = "user-topic-subscription", + topics = USER_TOPIC, + subscriptionType = SubscriptionType.Shared, + schemaType = SchemaType.JSON, + ackMode = AckMode.RECORD, + deadLetterPolicy = "deadLetterPolicy", + properties = {"ackTimeout=60s"} + ) + public void userTopicListener(User user) { + LOGGER.info("Received user object with email: {}", user.getEmail()); + } + + @PulsarListener( + subscriptionName = "dead-letter-topic-subscription", + topics = USER_DEAD_LETTER_TOPIC, + subscriptionType = SubscriptionType.Shared + ) + public void userDlqTopicListener(User user) { + LOGGER.info("Received user object in user-DLQ with email: {}", user.getEmail()); + } +} diff --git a/spring-pulsar/src/main/java/com/baeldung/springpulsar/PulsarProducer.java b/spring-pulsar/src/main/java/com/baeldung/springpulsar/PulsarProducer.java new file mode 100644 index 0000000000..9415b640dc --- /dev/null +++ b/spring-pulsar/src/main/java/com/baeldung/springpulsar/PulsarProducer.java @@ -0,0 +1,37 @@ +package com.baeldung.springpulsar; + +import org.apache.pulsar.client.api.ProducerAccessMode; +import org.apache.pulsar.client.api.PulsarClientException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.pulsar.core.PulsarTemplate; +import org.springframework.stereotype.Component; + +import java.util.concurrent.TimeUnit; + +@Component +public class PulsarProducer { + + @Autowired + private PulsarTemplate template; + @Autowired + private PulsarTemplate stringTemplate; + + private static final String USER_TOPIC = "user-topic"; + private static final String USER_TOPIC_STR = "string-topic"; + + public void sendMessageToPulsarTopic(User user) throws PulsarClientException { + template.newMessage(user) + .withProducerCustomizer(pc -> { + pc.accessMode(ProducerAccessMode.Shared); + }) + .withMessageCustomizer(mc -> { + mc.deliverAfter(10L, TimeUnit.SECONDS); + }) + .withTopic(USER_TOPIC) + .send(); + } + + public void sendStringMessageToPulsarTopic(String str) throws PulsarClientException { + stringTemplate.send(USER_TOPIC_STR, str); + } +} diff --git a/spring-pulsar/src/main/java/com/baeldung/springpulsar/SpringPulsarApplication.java b/spring-pulsar/src/main/java/com/baeldung/springpulsar/SpringPulsarApplication.java new file mode 100644 index 0000000000..8fd978df76 --- /dev/null +++ b/spring-pulsar/src/main/java/com/baeldung/springpulsar/SpringPulsarApplication.java @@ -0,0 +1,15 @@ +package com.baeldung.springpulsar; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.pulsar.annotation.EnablePulsar; + +@EnablePulsar +@SpringBootApplication +public class SpringPulsarApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringPulsarApplication.class, args); + } + +} diff --git a/spring-pulsar/src/main/java/com/baeldung/springpulsar/User.java b/spring-pulsar/src/main/java/com/baeldung/springpulsar/User.java new file mode 100644 index 0000000000..1175b16d26 --- /dev/null +++ b/spring-pulsar/src/main/java/com/baeldung/springpulsar/User.java @@ -0,0 +1,31 @@ +package com.baeldung.springpulsar; + +public class User { + + private String email; + private String firstName; + + public User() { + } + + public User(String email, String firstName) { + this.email = email; + this.firstName = firstName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } +} diff --git a/spring-pulsar/src/main/resources/application.yaml b/spring-pulsar/src/main/resources/application.yaml new file mode 100644 index 0000000000..a35ed70643 --- /dev/null +++ b/spring-pulsar/src/main/resources/application.yaml @@ -0,0 +1,12 @@ +server: + port: 8085 + +spring: + pulsar: + client: + service-url: pulsar://localhost:6650 + defaults: + type-mappings: + - message-type: com.baeldung.springpulsar.User + schema-info: + schema-type: JSON \ No newline at end of file diff --git a/spring-reactive-modules/spring-5-data-reactive-2/README.md b/spring-reactive-modules/spring-5-data-reactive-2/README.md index d12e8214cd..ffc664b8af 100644 --- a/spring-reactive-modules/spring-5-data-reactive-2/README.md +++ b/spring-reactive-modules/spring-5-data-reactive-2/README.md @@ -7,3 +7,4 @@ This module contains articles about reactive Spring 5 Data The "REST With Spring" Classes: http://bit.ly/restwithspring ### Relevant Articles +- [Pagination in Spring Webflux and Spring Data Reactive](https://www.baeldung.com/spring-data-webflux-pagination) diff --git a/spring-security-modules/spring-security-azuread/README.md b/spring-security-modules/spring-security-azuread/README.md index 8b4d6d9666..1031455a45 100644 --- a/spring-security-modules/spring-security-azuread/README.md +++ b/spring-security-modules/spring-security-azuread/README.md @@ -1,2 +1,2 @@ ## Relevant Articles -- [Authenticating Users with AzureAD in Spring Boot](https://www.baeldung.com/spring-boot-azuerad-authenticate-users) +- [Authenticating Users with AzureAD in Spring Boot](https://www.baeldung.com/spring-boot-azuread-authenticate-users) diff --git a/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/pom.xml b/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/pom.xml index 8c26e9947d..38d019c683 100644 --- a/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/pom.xml +++ b/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/pom.xml @@ -1,95 +1,84 @@ + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd"> - 4.0.0 + 4.0.0 - com.baeldung.spring-thymeleaf-attributes.module - accessing-session-attributes + com.baeldung.spring-thymeleaf-attributes.module + accessing-session-attributes + 0.0.1-SNAPSHOT + war + + + com.baeldung.spring-thymeleaf-attributes + spring-thymeleaf-attributes 0.0.1-SNAPSHOT - war + ../pom.xml + - - com.baeldung.spring-thymeleaf-attributes - spring-thymeleaf-attributes - 0.0.1-SNAPSHOT - ../pom.xml - + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-thymeleaf + ${spring.boot.starter.thymeleaf} + + + + org.junit.jupiter + junit-jupiter-engine + ${junit.jupiter.engine.version} + test + + + org.mockito + mockito-core + ${mockito.version} + test + + + org.mockito + mockito-junit-jupiter + ${mockito.version} + test + + + org.junit.jupiter + junit-jupiter-api + ${junit.jupiter.engine.version} + test + + - - - jakarta.servlet - jakarta.servlet-api - provided - - - org.springframework.boot - spring-boot-starter-web - - - org.thymeleaf - thymeleaf-spring6 - ${thymeleaf.spring6.version} - - - - org.junit.jupiter - junit-jupiter-engine - ${junit.jupiter.engine.version} - test - - - org.mockito - mockito-core - ${mockito.version} - test - - - org.mockito - mockito-junit-jupiter - ${mockito.version} - test - - - org.junit.jupiter - junit-jupiter-api - ${junit.jupiter.engine.version} - test - + + + + org.springframework.boot + spring-boot-maven-plugin + + + -Dfile.encoding="UTF-8" -Xdebug + -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 + + + + + - - - - - - src/main/resources - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - -Dfile.encoding="UTF-8" -Xdebug - -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 - - - - - - - - com.baeldung.accesing_session_attributes.SpringWebApplicationInitializer - UTF-8 - UTF-8 - UTF-8 - true - true - 5.9.3 - 5.3.1 - 3.1.1.RELEASE - + + com.baeldung.accesing_session_attributes.SpringWebApplicationInitializer + UTF-8 + UTF-8 + UTF-8 + true + true + 5.9.3 + 5.3.1 + 3.1.1.RELEASE + 3.1.1 + \ No newline at end of file diff --git a/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/src/main/java/com/baeldung/accesing_session_attributes/web/SpringWebConfig.java b/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/src/main/java/com/baeldung/accesing_session_attributes/web/SpringWebConfig.java index 00b49ff392..b3cba41aad 100644 --- a/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/src/main/java/com/baeldung/accesing_session_attributes/web/SpringWebConfig.java +++ b/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/src/main/java/com/baeldung/accesing_session_attributes/web/SpringWebConfig.java @@ -1,34 +1,26 @@ package com.baeldung.accesing_session_attributes.web; -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.ResourceBundleMessageSource; -import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; -import org.thymeleaf.spring6.SpringTemplateEngine; import org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver; -import org.thymeleaf.spring6.view.ThymeleafViewResolver; import org.thymeleaf.templatemode.TemplateMode; -import org.thymeleaf.web.servlet.JakartaServletWebApplication; @Configuration @EnableWebMvc -public class SpringWebConfig implements WebMvcConfigurer, ApplicationContextAware { +public class SpringWebConfig implements WebMvcConfigurer { // , ApplicationContextAware { - private WebApplicationContext webApplicationContext; - - public SpringWebConfig() { + @Autowired + public SpringWebConfig(SpringResourceTemplateResolver templateResolver) { super(); - } - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - this.webApplicationContext = (WebApplicationContext) applicationContext; + templateResolver.setPrefix("/WEB-INF/templates/"); + templateResolver.setSuffix(".html"); + templateResolver.setTemplateMode(TemplateMode.HTML); } /* @@ -51,36 +43,4 @@ public class SpringWebConfig implements WebMvcConfigurer, ApplicationContextAwar messageSource.addBasenames("name-analysis"); return messageSource; } - - @Bean - public SpringResourceTemplateResolver templateResolver() { - SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver(); - templateResolver.setApplicationContext(this.webApplicationContext); - templateResolver.setPrefix("/WEB-INF/templates/"); - templateResolver.setSuffix(".html"); - - templateResolver.setTemplateMode(TemplateMode.HTML); - templateResolver.setCacheable(true); - return templateResolver; - } - - @Bean - public SpringTemplateEngine templateEngine() { - SpringTemplateEngine templateEngine = new SpringTemplateEngine(); - templateEngine.setMessageSource(webApplicationContext); - templateEngine.setTemplateResolver(templateResolver()); - return templateEngine; - } - - @Bean - public ThymeleafViewResolver viewResolver() { - ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); - viewResolver.setTemplateEngine(templateEngine()); - return viewResolver; - } - - @Bean - public JakartaServletWebApplication jakartaServletWebApplication() { - return JakartaServletWebApplication.buildApplication(webApplicationContext.getServletContext()); - } } diff --git a/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/src/main/java/com/baeldung/accesing_session_attributes/web/controllers/NameAnalysisController.java b/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/src/main/java/com/baeldung/accesing_session_attributes/web/controllers/NameAnalysisController.java index 65aa0686a0..55c1c8fa58 100644 --- a/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/src/main/java/com/baeldung/accesing_session_attributes/web/controllers/NameAnalysisController.java +++ b/spring-web-modules/spring-thymeleaf-attributes/accessing-session-attributes/src/main/java/com/baeldung/accesing_session_attributes/web/controllers/NameAnalysisController.java @@ -20,6 +20,7 @@ import com.baeldung.accesing_session_attributes.business.entities.NameAnalysisEn import com.baeldung.accesing_session_attributes.web.beans.SessionNameRequest; import com.baeldung.accesing_session_attributes.web.factories.SessionNameRequestFactory; +import jakarta.servlet.ServletContext; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -27,19 +28,15 @@ import jakarta.servlet.http.HttpServletResponse; public class NameAnalysisController { private NameAnalysisService nameAnalysisService; - private HttpServletRequest request; private SessionNameRequestFactory sessionNameRequestFactory; - private HttpServletResponse response; - private JakartaServletWebApplication jakartaServletWebApplication; + private JakartaServletWebApplication webApp; @Autowired - public NameAnalysisController(JakartaServletWebApplication jakartaServletWebApplication, HttpServletRequest request, HttpServletResponse response, NameAnalysisService nameAnalysisService, SessionNameRequestFactory sessionNameRequestFactory) { + public NameAnalysisController(NameAnalysisService nameAnalysisService, SessionNameRequestFactory sessionNameRequestFactory, ServletContext servletContext) { super(); - this.jakartaServletWebApplication = jakartaServletWebApplication; - this.request = request; - this.response = response; this.nameAnalysisService = nameAnalysisService; this.sessionNameRequestFactory = sessionNameRequestFactory; + this.webApp = JakartaServletWebApplication.buildApplication(servletContext); } @ModelAttribute("nameRequest") @@ -53,22 +50,25 @@ public class NameAnalysisController { } @RequestMapping(value = "/name-analysis", params = { "search" }) - public String performNameAnalysis(final NameRequest nameRequest, final BindingResult bindingResult) { - performNameRequest(nameRequest); + public String performNameAnalysis(final NameRequest nameRequest, final BindingResult bindingResult, HttpServletRequest request, HttpServletResponse response) { + IWebSession webSession = getIWebSession(request, response); + performNameRequest(nameRequest, webSession); return "name-analysis"; } @RequestMapping(value = "/name-analysis/clear") - public String clearNameAnalysis() { - clearAnalysis(); + public String clearNameAnalysis(HttpServletRequest request, HttpServletResponse response) { + IWebSession webSession = getIWebSession(request, response); + clearAnalysis(webSession); return "redirect:/name-analysis"; } @RequestMapping(value = "/name-analysis/remove-history-request", params = { "id" }) - public String removeRequest() { + public String removeRequest(HttpServletRequest request, HttpServletResponse response) { try { + IWebSession webSession = getIWebSession(request, response); final Integer rowId = Integer.valueOf(request.getParameter("id")); - removeRequest(rowId); + removeRequest(rowId, webSession); } catch (Exception e) { e.printStackTrace(); @@ -76,53 +76,49 @@ public class NameAnalysisController { return "redirect:/name-analysis"; } - private void removeRequest(Integer rowId) { - IWebSession session = getIWebSession(); - Object requests = session.getAttributeValue("requests"); - if (rowId != null && requests != null && (requests instanceof List)) { - ((List) requests).remove(rowId.intValue()); + private void removeRequest(Integer rowId, IWebSession webSession) { + if (rowId != null) { + List requests = getRequestsFromSession(webSession); + if (requests != null) { + requests.remove(rowId.intValue()); + } } } - private void performNameRequest(final NameRequest nameRequest) { + private void performNameRequest(final NameRequest nameRequest, IWebSession webSession) { try { CompletableFuture nameAnalysis = this.nameAnalysisService.searchForName(nameRequest); NameAnalysisEntity nameAnalysisEntity = nameAnalysis.get(30, TimeUnit.SECONDS); - sessionRegisterRequest(nameRequest); - sessionRegisterAnalysis(nameAnalysisEntity); - sessionClearAnalysisError(); + sessionRegisterRequest(nameRequest, webSession); + sessionRegisterAnalysis(nameAnalysisEntity, webSession); + sessionClearAnalysisError(webSession); } catch (Exception e) { e.printStackTrace(); - sessionSetAnalysisError(nameRequest); + sessionSetAnalysisError(nameRequest, webSession); } } - private void sessionClearAnalysisError() { - IWebSession session = getIWebSession(); - session.setAttributeValue("analysisError", null); + private void sessionClearAnalysisError(IWebSession webSession) { + webSession.removeAttribute("analysisError"); } - private void sessionSetAnalysisError(NameRequest nameRequest) { - IWebSession session = getIWebSession(); - session.setAttributeValue("analysisError", nameRequest); + private void sessionSetAnalysisError(NameRequest nameRequest, IWebSession webSession) { + webSession.setAttributeValue("analysisError", nameRequest); } - private void clearAnalysis() { - IWebSession session = getIWebSession(); - session.setAttributeValue("lastAnalysis", null); + private void clearAnalysis(IWebSession webSession) { + webSession.removeAttribute("lastAnalysis"); } - private void sessionRegisterAnalysis(NameAnalysisEntity analysis) { - IWebSession session = getIWebSession(); - session.setAttributeValue("lastAnalysis", analysis); + private void sessionRegisterAnalysis(NameAnalysisEntity analysis, IWebSession webSession) { + webSession.setAttributeValue("lastAnalysis", analysis); } - private void sessionRegisterRequest(NameRequest nameRequest) { - IWebSession session = getIWebSession(); - session.setAttributeValue("lastRequest", nameRequest); + private void sessionRegisterRequest(NameRequest nameRequest, IWebSession webSession) { + webSession.setAttributeValue("lastRequest", nameRequest); SessionNameRequest sessionNameRequest = sessionNameRequestFactory.getInstance(nameRequest); - List requests = getRequestsFromSession(session); + List requests = getRequestsFromSession(webSession); requests.add(0, sessionNameRequest); } @@ -136,8 +132,8 @@ public class NameAnalysisController { return (List) requests; } - private IWebSession getIWebSession() { - IServletWebExchange webExchange = this.jakartaServletWebApplication.buildExchange(request, response); - return webExchange.getSession(); + private IWebSession getIWebSession(HttpServletRequest request, HttpServletResponse response) { + IServletWebExchange exchange = webApp.buildExchange(request, response); + return exchange == null ? null : exchange.getSession(); } } diff --git a/spring-web-modules/spring-thymeleaf/README.md b/spring-web-modules/spring-thymeleaf/README.md index b49095f5b1..7121085ac0 100644 --- a/spring-web-modules/spring-thymeleaf/README.md +++ b/spring-web-modules/spring-thymeleaf/README.md @@ -23,3 +23,20 @@ mvn cargo:run ### Security The user/password required is: user1/user1Pass + +### Endpoints + +All endpoints start with `http://localhost:8082/spring-thymeleaf`: + +- `/dates` +- `/saveStudent` +- `/objects` +- `/fragments` +- `/markup` +- `/params` +- `/other` +- `/function-call` +- `/html` +- `/js` +- `/plain` +- `/layout` \ No newline at end of file diff --git a/testing-modules/jqwik/README.md b/testing-modules/jqwik/README.md new file mode 100644 index 0000000000..f5a2c47534 --- /dev/null +++ b/testing-modules/jqwik/README.md @@ -0,0 +1,2 @@ +## Relevant Articles +- [Property-Based Testing with jqwik](https://www.baeldung.com/java-jqwik-property-based-testing) diff --git a/testing-modules/testing-libraries-2/README.md b/testing-modules/testing-libraries-2/README.md index 6b66649b38..9e17da96a7 100644 --- a/testing-modules/testing-libraries-2/README.md +++ b/testing-modules/testing-libraries-2/README.md @@ -6,3 +6,4 @@ - [Exclusions from Jacoco Report](https://www.baeldung.com/jacoco-report-exclude) - [Gray Box Testing Using the OAT Technique](https://www.baeldung.com/java-gray-box-orthogonal-array-testing) - [Unit Testing of System.in With JUnit](https://www.baeldung.com/java-junit-testing-system-in) +- [Fail Maven Build if JUnit Coverage Falls Below Certain Threshold](https://www.baeldung.com/maven-junit-fail-build-coverage-threshold) diff --git a/web-modules/restx/pom.xml b/web-modules/restx/pom.xml index 3c09c90aa7..0e6cb3fa78 100644 --- a/web-modules/restx/pom.xml +++ b/web-modules/restx/pom.xml @@ -132,16 +132,6 @@ - - ${maven.compiler.source} - restx.apidocs.doclet.ApidocsDoclet - - io.restx - restx-apidocs-doclet - ${restx.version} - - -restx-target-dir ${project.basedir}/target/classes - diff --git a/xml-2/pom.xml b/xml-2/pom.xml index d56fdd7165..7d10f36042 100644 --- a/xml-2/pom.xml +++ b/xml-2/pom.xml @@ -70,7 +70,6 @@ 2.1.3 - 2.14.1 20230227 1.89