Merge pull request #26 from panos-kakos/master

Update from master
This commit is contained in:
panos-kakos 2023-08-27 10:03:44 +03:00 committed by GitHub
commit e48e459c7b
182 changed files with 4279 additions and 1355 deletions

View File

@ -5,7 +5,7 @@ import org.slf4j.LoggerFactory;
public class KadaneAlgorithm {
private Logger logger = LoggerFactory.getLogger(BruteForceAlgorithm.class.getName());
private Logger logger = LoggerFactory.getLogger(KadaneAlgorithm.class.getName());
public int maxSubArraySum(int[] arr) {
@ -14,15 +14,15 @@ public class KadaneAlgorithm {
int end = 0;
int maxSoFar = arr[0], maxEndingHere = arr[0];
for (int i = 1; i < size; i++) {
if (arr[i] > maxEndingHere + arr[i]) {
start = i;
maxEndingHere = maxEndingHere + arr[i];
if (arr[i] > maxEndingHere) {
maxEndingHere = arr[i];
} else {
maxEndingHere = maxEndingHere + arr[i];
if (maxSoFar < maxEndingHere) {
start = i;
}
}
if (maxSoFar < maxEndingHere) {
maxSoFar = maxEndingHere;
end = i;

View File

@ -7,7 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
class KadaneAlgorithmUnitTest {
@Test
void givenArrayWithNegativeNumberWhenMaximumSubarrayThenReturns6() {
void givenArrayWithNegativeNumberWhenMaximumSubarrayThenReturnsExpectedResult() {
//given
int[] arr = new int[] { -3, 1, -8, 4, -1, 2, 1, -5, 5 };
//when
@ -27,7 +27,7 @@ class KadaneAlgorithmUnitTest {
//then
assertEquals(-1, maxSum);
}
@Test
void givenArrayWithAllPosiitveNumbersWhenMaximumSubarrayThenReturnsExpectedResult() {
//given
@ -39,4 +39,15 @@ class KadaneAlgorithmUnitTest {
assertEquals(10, maxSum);
}
@Test
void givenArrayToTestStartIndexWhenMaximumSubarrayThenReturnsExpectedResult() {
//given
int[] arr = new int[] { 1, 2, -1, 3, -6, -2 };
//when
KadaneAlgorithm algorithm = new KadaneAlgorithm();
int maxSum = algorithm.maxSubArraySum(arr);
//then
assertEquals(5, maxSum);
}
}

View File

@ -3,4 +3,5 @@
- [Algorithm to Identify and Validate a Credit Card Number](https://www.baeldung.com/java-validate-cc-number)
- [Find the N Most Frequent Elements in a Java Array](https://www.baeldung.com/java-n-most-frequent-elements-array)
- [Getting Pixel Array From Image in Java](https://www.baeldung.com/java-getting-pixel-array-from-image)
- [Calculate Distance Between Two Coordinates in Java](https://www.baeldung.com/java-find-distance-between-points)
- More articles: [[<-- prev]](/algorithms-miscellaneous-6)

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -1,69 +1,71 @@
package com.baeldung.httpclient.conn;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpClientConnection;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.conn.ConnectionRequest;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpCoreContext;
import org.apache.http.protocol.HttpRequestExecutor;
import org.apache.http.util.EntityUtils;
import org.junit.Ignore;
import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
import org.apache.hc.client5.http.HttpRoute;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.config.ConnectionConfig;
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.BasicHttpClientConnectionManager;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.io.ConnectionEndpoint;
import org.apache.hc.client5.http.io.LeaseRequest;
import org.apache.hc.core5.http.HeaderElement;
import org.apache.hc.core5.http.HeaderElements;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.MessageSupport;
import org.apache.hc.core5.http.message.StatusLine;
import org.apache.hc.core5.http.protocol.BasicHttpContext;
import org.apache.hc.core5.http.protocol.HttpContext;
import org.apache.hc.core5.pool.PoolStats;
import org.apache.hc.core5.util.Args;
import org.apache.hc.core5.util.TimeValue;
import org.apache.hc.core5.util.Timeout;
import org.junit.Assert;
import org.junit.Test;
public class HttpClientConnectionManagementLiveTest {
// Example 2.1. Getting a Connection Request for a Low Level Connection (HttpClientConnection)
@Test
public final void whenLowLevelConnectionIsEstablished_thenNoExceptions() throws ConnectionPoolTimeoutException, InterruptedException, ExecutionException {
try (BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager()) {
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 80));
final ConnectionRequest connRequest = connManager.requestConnection(route, null);
assertNotNull(connRequest.get(1000, TimeUnit.SECONDS));
}
public final void whenLowLevelConnectionIsEstablished_thenNoExceptions() throws ExecutionException, InterruptedException, TimeoutException {
BasicHttpClientConnectionManager connMgr = new BasicHttpClientConnectionManager();
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 443));
final LeaseRequest connRequest = connMgr.lease("some-id", route, null);
assertNotNull(connRequest.get(Timeout.ZERO_MILLISECONDS));
connMgr.close();
}
// Example 3.1. Setting the PoolingHttpClientConnectionManager on a HttpClient
@Test
public final void whenPollingConnectionManagerIsConfiguredOnHttpClient_thenNoExceptions() throws ClientProtocolException, IOException {
public final void whenPollingConnectionManagerIsConfiguredOnHttpClient_thenNoExceptions() throws IOException {
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(poolingConnManager)
.build();
client.execute(new HttpGet("https://www.baeldung.com"));
assertTrue(poolingConnManager.getTotalStats()
.getLeased() == 1);
client.close();
poolingConnManager.close();
}
// Example 3.2. Using Two HttpClients to Connect to One Target Host Each
@Test
public final void whenTwoConnectionsForTwoRequests_thenNoExceptions() throws InterruptedException {
public final void whenTwoConnectionsForTwoRequests_thenNoExceptions() throws InterruptedException, IOException {
HttpGet get1 = new HttpGet("https://www.baeldung.com");
HttpGet get2 = new HttpGet("https://www.google.com");
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
@ -81,38 +83,52 @@ public class HttpClientConnectionManagementLiveTest {
thread1.join();
thread2.join();
assertTrue(connManager.getTotalStats()
Assert.assertTrue(connManager.getTotalStats()
.getLeased() == 0);
client1.close();
client2.close();
connManager.close();
}
// Example 4.1. Increasing the Number of Connections that Can be Open and Managed Beyond the default Limits
@Test
public final void whenIncreasingConnectionPool_thenNoEceptions() {
try (PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager()) {
connManager.setMaxTotal(5);
connManager.setDefaultMaxPerRoute(4);
HttpHost host = new HttpHost("www.baeldung.com", 80);
connManager.setMaxPerRoute(new HttpRoute(host), 5);
}
public final void whenIncreasingConnectionPool_thenNoExceptions() {
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
connManager.setMaxTotal(5);
connManager.setDefaultMaxPerRoute(4);
HttpHost host = new HttpHost("www.baeldung.com", 80);
connManager.setMaxPerRoute(new HttpRoute(host), 5);
connManager.close();
}
// Example 4.2. Using Threads to Execute Connections
@Test
public final void whenExecutingSameRequestsInDifferentThreads_thenExecuteReuqest() throws InterruptedException {
public final void whenExecutingSameRequestsInDifferentThreads_thenExecuteRequest() throws InterruptedException, IOException {
HttpGet get = new HttpGet("http://www.baeldung.com");
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(connManager)
.build();
MultiHttpClientConnThread thread1 = new MultiHttpClientConnThread(client, get);
MultiHttpClientConnThread thread2 = new MultiHttpClientConnThread(client, get);
MultiHttpClientConnThread thread3 = new MultiHttpClientConnThread(client, get);
MultiHttpClientConnThread thread1 = new MultiHttpClientConnThread(client, get, connManager);
MultiHttpClientConnThread thread2 = new MultiHttpClientConnThread(client, get, connManager);
MultiHttpClientConnThread thread3 = new MultiHttpClientConnThread(client, get, connManager);
MultiHttpClientConnThread thread4 = new MultiHttpClientConnThread(client, get, connManager);
MultiHttpClientConnThread thread5 = new MultiHttpClientConnThread(client, get, connManager);
MultiHttpClientConnThread thread6 = new MultiHttpClientConnThread(client, get, connManager);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
thread6.start();
thread1.join();
thread2.join();
thread3.join();
thread4.join();
thread5.join();
thread6.join();
client.close();
connManager.close();
}
// Example 5.1. A Custom Keep Alive Strategy
@ -120,22 +136,19 @@ public class HttpClientConnectionManagementLiveTest {
public final void whenCustomizingKeepAliveStrategy_thenNoExceptions() {
final ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy() {
@Override
public long getKeepAliveDuration(final HttpResponse myResponse, final HttpContext myContext) {
final HeaderElementIterator it = new BasicHeaderElementIterator(myResponse.headerIterator(HTTP.CONN_KEEP_ALIVE));
while (it.hasNext()) {
final HeaderElement he = it.nextElement();
final String param = he.getName();
final String value = he.getValue();
if ((value != null) && param.equalsIgnoreCase("timeout")) {
return Long.parseLong(value) * 1000;
public TimeValue getKeepAliveDuration(HttpResponse response, HttpContext context) {
Args.notNull(response, "HTTP response");
final Iterator<HeaderElement> it = MessageSupport.iterate(response, HeaderElements.KEEP_ALIVE);
final HeaderElement he = it.next();
final String param = he.getName();
final String value = he.getValue();
if (value != null && param.equalsIgnoreCase("timeout")) {
try {
return TimeValue.ofSeconds(Long.parseLong(value));
} catch (final NumberFormatException ignore) {
}
}
final HttpHost target = (HttpHost) myContext.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
if ("localhost".equalsIgnoreCase(target.getHostName())) {
return 10 * 1000;
} else {
return 5 * 1000;
}
return TimeValue.ofSeconds(5);
}
};
@ -144,42 +157,38 @@ public class HttpClientConnectionManagementLiveTest {
.setKeepAliveStrategy(myStrategy)
.setConnectionManager(connManager)
.build();
connManager.close();
}
// Example 6.1. BasicHttpClientConnectionManager Connection Reuse
//Example 6.1. BasicHttpClientConnectionManager Connection Reuse
@Test
public final void givenBasicHttpClientConnManager_whenConnectionReuse_thenNoExceptions() throws IOException, HttpException, InterruptedException, ExecutionException {
BasicHttpClientConnectionManager basicConnManager = new BasicHttpClientConnectionManager();
HttpClientContext context = HttpClientContext.create();
// low level
public final void givenBasicHttpClientConnManager_whenConnectionReuse_thenNoExceptions() throws InterruptedException, ExecutionException, TimeoutException, IOException, URISyntaxException {
BasicHttpClientConnectionManager connMgr = new BasicHttpClientConnectionManager();
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 443));
ConnectionRequest connRequest = basicConnManager.requestConnection(route, null);
HttpClientConnection conn = connRequest.get(10, TimeUnit.SECONDS);
basicConnManager.connect(conn, route, 1000, context);
basicConnManager.routeComplete(conn, route, context);
final HttpContext context = new BasicHttpContext();
HttpRequestExecutor exeRequest = new HttpRequestExecutor();
context.setTargetHost((new HttpHost("www.baeldung.com", 80)));
HttpGet get = new HttpGet("http://www.baeldung.com");
exeRequest.execute(get, conn, context);
final LeaseRequest connRequest = connMgr.lease("some-id", route, null);
final ConnectionEndpoint endpoint = connRequest.get(Timeout.ZERO_MILLISECONDS);
connMgr.connect(endpoint, Timeout.ZERO_MILLISECONDS, context);
basicConnManager.releaseConnection(conn, null, 1, TimeUnit.SECONDS);
connMgr.release(endpoint, null, TimeValue.ZERO_MILLISECONDS);
// high level
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(basicConnManager)
.setConnectionManager(connMgr)
.build();
client.execute(get);
HttpGet httpGet = new HttpGet("https://www.example.com");
client.execute(httpGet, context, response -> response);
client.close();
connMgr.close();
}
// Example 6.2. PoolingHttpClientConnectionManager: Re-Using Connections with Threads
@Test
public final void whenConnectionsNeededGreaterThanMaxTotal_thenLeaseMasTotalandReuse() throws InterruptedException {
HttpGet get = new HttpGet("http://echo.200please.com");
public final void whenConnectionsNeededGreaterThanMaxTotal_thenLeaseMasTotalandReuse() throws InterruptedException, IOException {
HttpGet get = new HttpGet("http://www.baeldung.com");
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
connManager.setDefaultMaxPerRoute(5);
connManager.setMaxTotal(5);
connManager.setDefaultMaxPerRoute(6);
connManager.setMaxTotal(6);
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(connManager)
.build();
@ -193,48 +202,71 @@ public class HttpClientConnectionManagementLiveTest {
for (MultiHttpClientConnThread thread : threads) {
thread.join(1000);
}
client.close();
connManager.close();
}
// Example 7.1. Setting Socket Timeout to 5 Seconds
@Test
public final void whenConfiguringTimeOut_thenNoExceptions() {
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 80));
try (PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager()) {
connManager.setSocketConfig(route.getTargetHost(), SocketConfig.custom()
.setSoTimeout(5000)
.build());
assertTrue(connManager.getSocketConfig(route.getTargetHost())
.getSoTimeout() == 5000);
}
public final void whenConfiguringTimeOut_thenNoExceptions() throws ExecutionException, InterruptedException, TimeoutException, IOException {
final HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 80));
final HttpContext context = new BasicHttpContext();
final PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
final ConnectionConfig connConfig = ConnectionConfig.custom()
.setSocketTimeout(5, TimeUnit.SECONDS)
.build();
connManager.setDefaultConnectionConfig(connConfig);
final LeaseRequest leaseRequest = connManager.lease("id1", route, null);
final ConnectionEndpoint endpoint = leaseRequest.get(Timeout.ZERO_MILLISECONDS);
connManager.connect(endpoint, null, context);
connManager.close();
}
// Example 8.1. Setting the HttpClient to Check for Stale Connections
@Test
public final void whenHttpClientChecksStaleConns_thenNoExceptions() {
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setStaleConnectionCheckEnabled(true)
.build())
public final void whenEvictIdealConn_thenNoExceptions() throws InterruptedException, IOException {
final PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
connManager.setMaxTotal(100);
try (final CloseableHttpClient httpclient = HttpClients.custom()
.setConnectionManager(connManager)
.build();
}
.evictExpiredConnections()
.evictIdleConnections(TimeValue.ofSeconds(2))
.build()) {
// create an array of URIs to perform GETs on
final String[] urisToGet = { "http://hc.apache.org/", "http://hc.apache.org/httpcomponents-core-ga/"};
// Example 8.2. Using a Stale Connection Monitor Thread
@Test
public final void whenCustomizedIdleConnMonitor_thenNoExceptions() throws InterruptedException {
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
HttpClients.custom()
.setConnectionManager(connManager)
.build();
IdleConnectionMonitorThread staleMonitor = new IdleConnectionMonitorThread(connManager);
staleMonitor.start();
staleMonitor.join(1000);
for (final String requestURI : urisToGet) {
final HttpGet request = new HttpGet(requestURI);
System.out.println("Executing request " + request.getMethod() + " " + request.getRequestUri());
httpclient.execute(request, response -> {
System.out.println("----------------------------------------");
System.out.println(request + "->" + new StatusLine(response));
EntityUtils.consume(response.getEntity());
return null;
});
}
final PoolStats stats1 = connManager.getTotalStats();
System.out.println("Connections kept alive: " + stats1.getAvailable());
// Sleep 10 sec and let the connection evict or do its job
Thread.sleep(4000);
final PoolStats stats2 = connManager.getTotalStats();
System.out.println("Connections kept alive: " + stats2.getAvailable());
connManager.close();
}
}
// Example 9.1. Closing Connection and Releasing Resources
@Test(expected = IllegalStateException.class)
public final void whenClosingConnectionsandManager_thenCloseWithNoExceptions1() throws InterruptedException, ExecutionException, IOException, HttpException {
@Test
public final void whenClosingConnectionsandManager_thenCloseWithNoExceptions1() throws IOException {
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(connManager)
@ -246,16 +278,11 @@ public class HttpClientConnectionManagementLiveTest {
response.close();
client.close();
connManager.close();
connManager.shutdown();
client.execute(get);
assertTrue(response.getEntity() == null);
}
@Test
// Example 3.2. TESTER VERSION
public final void whenTwoConnectionsForTwoRequests_thenTwoConnectionsAreLeased() throws InterruptedException {
public final void whenTwoConnectionsForTwoRequests_thenTwoConnectionsAreLeased() throws InterruptedException, IOException {
HttpGet get1 = new HttpGet("https://www.baeldung.com");
HttpGet get2 = new HttpGet("https://www.google.com");
@ -273,77 +300,11 @@ public class HttpClientConnectionManagementLiveTest {
thread2.start();
thread1.join();
thread2.join(1000);
assertTrue(poolingConnManager.getTotalStats()
Assert.assertTrue(poolingConnManager.getTotalStats()
.getLeased() == 2);
}
@Test
// Example 4.2 Tester Version
public final void whenExecutingSameRequestsInDifferentThreads_thenUseDefaultConnLimit() throws InterruptedException {
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(poolingConnManager)
.build();
final TesterVersion_MultiHttpClientConnThread thread1 = new TesterVersion_MultiHttpClientConnThread(client, new HttpGet("http://www.google.com"), poolingConnManager);
final TesterVersion_MultiHttpClientConnThread thread2 = new TesterVersion_MultiHttpClientConnThread(client, new HttpGet("http://www.google.com"), poolingConnManager);
final TesterVersion_MultiHttpClientConnThread thread3 = new TesterVersion_MultiHttpClientConnThread(client, new HttpGet("http://www.google.com"), poolingConnManager);
thread1.start();
thread2.start();
thread3.start();
thread1.join(10000);
thread2.join(10000);
thread3.join(10000);
}
@Test
// 6.2 TESTER VERSION
public final void whenConnectionsNeededGreaterThanMaxTotal_thenReuseConnections() throws InterruptedException {
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
poolingConnManager.setDefaultMaxPerRoute(5);
poolingConnManager.setMaxTotal(5);
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(poolingConnManager)
.build();
final MultiHttpClientConnThread[] threads = new MultiHttpClientConnThread[10];
int countConnMade = 0;
for (int i = 0; i < threads.length; i++) {
threads[i] = new MultiHttpClientConnThread(client, new HttpGet("http://www.baeldung.com/"), poolingConnManager);
}
for (final MultiHttpClientConnThread thread : threads) {
thread.start();
}
for (final MultiHttpClientConnThread thread : threads) {
thread.join(10000);
countConnMade++;
if (countConnMade == 0) {
assertTrue(thread.getLeasedConn() == 5);
}
}
}
@Test
@Ignore("Very Long Running")
// 8.2 TESTER VERSION
public final void whenCustomizedIdleConnMonitor_thenEliminateIdleConns() throws InterruptedException {
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(poolingConnManager)
.build();
final IdleConnectionMonitorThread staleMonitor = new IdleConnectionMonitorThread(poolingConnManager);
final HttpGet get = new HttpGet("http://google.com");
final TesterVersion_MultiHttpClientConnThread thread1 = new TesterVersion_MultiHttpClientConnThread(client, get, poolingConnManager);
final TesterVersion_MultiHttpClientConnThread thread2 = new TesterVersion_MultiHttpClientConnThread(client, get, poolingConnManager);
final TesterVersion_MultiHttpClientConnThread thread3 = new TesterVersion_MultiHttpClientConnThread(client, get, poolingConnManager);
staleMonitor.start();
thread1.start();
thread1.join();
thread2.start();
thread2.join();
thread3.start();
assertTrue(poolingConnManager.getTotalStats()
.getAvailable() == 1);
thread3.join(32000);
assertTrue(poolingConnManager.getTotalStats()
.getAvailable() == 0);
client1.close();
client2.close();
poolingConnManager.close();
}
}

View File

@ -2,12 +2,12 @@ package com.baeldung.httpclient.conn;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -45,22 +45,21 @@ public class MultiHttpClientConnThread extends Thread {
try {
logger.debug("Thread Running: " + getName());
logger.debug("Thread Running: " + getName());
if (connManager != null) {
logger.info("Before - Leased Connections = " + connManager.getTotalStats().getLeased());
logger.info("Before - Available Connections = " + connManager.getTotalStats().getAvailable());
}
final HttpResponse response = client.execute(get);
HttpEntity entity = client.execute(get).getEntity();
if (connManager != null) {
leasedConn = connManager.getTotalStats().getLeased();
logger.info("After - Leased Connections = " + connManager.getTotalStats().getLeased());
logger.info("After - Available Connections = " + connManager.getTotalStats().getAvailable());
}
EntityUtils.consume(entity);
EntityUtils.consume(response.getEntity());
} catch (final IOException ex) {
logger.error("", ex);
}

View File

@ -2,10 +2,9 @@ package com.baeldung.httpclient.conn;
import java.io.IOException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View File

@ -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);
}
}
}

View File

@ -0,0 +1,349 @@
package com.baeldung.httpclient.httpclient.conn;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import org.apache.http.HeaderElement;
import org.apache.http.HeaderElementIterator;
import org.apache.http.HttpClientConnection;
import org.apache.http.HttpException;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ConnectionKeepAliveStrategy;
import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.conn.ConnectionRequest;
import org.apache.http.conn.routing.HttpRoute;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeaderElementIterator;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpCoreContext;
import org.apache.http.protocol.HttpRequestExecutor;
import org.apache.http.util.EntityUtils;
import org.junit.Ignore;
import org.junit.Test;
public class HttpClientConnectionManagementLiveTest {
// Example 2.1. Getting a Connection Request for a Low Level Connection (HttpClientConnection)
@Test
public final void whenLowLevelConnectionIsEstablished_thenNoExceptions() throws ConnectionPoolTimeoutException, InterruptedException, ExecutionException {
try (BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager()) {
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 80));
final ConnectionRequest connRequest = connManager.requestConnection(route, null);
assertNotNull(connRequest.get(1000, TimeUnit.SECONDS));
}
}
// Example 3.1. Setting the PoolingHttpClientConnectionManager on a HttpClient
@Test
public final void whenPollingConnectionManagerIsConfiguredOnHttpClient_thenNoExceptions() throws ClientProtocolException, IOException {
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(poolingConnManager)
.build();
client.execute(new HttpGet("https://www.baeldung.com"));
assertTrue(poolingConnManager.getTotalStats()
.getLeased() == 1);
}
// Example 3.2. Using Two HttpClients to Connect to One Target Host Each
@Test
public final void whenTwoConnectionsForTwoRequests_thenNoExceptions() throws InterruptedException {
HttpGet get1 = new HttpGet("https://www.baeldung.com");
HttpGet get2 = new HttpGet("https://www.google.com");
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
CloseableHttpClient client1 = HttpClients.custom()
.setConnectionManager(connManager)
.build();
CloseableHttpClient client2 = HttpClients.custom()
.setConnectionManager(connManager)
.build();
MultiHttpClientConnThread thread1 = new MultiHttpClientConnThread(client1, get1);
MultiHttpClientConnThread thread2 = new MultiHttpClientConnThread(client2, get2);
thread1.start();
thread2.start();
thread1.join();
thread2.join();
assertTrue(connManager.getTotalStats()
.getLeased() == 0);
}
// Example 4.1. Increasing the Number of Connections that Can be Open and Managed Beyond the default Limits
@Test
public final void whenIncreasingConnectionPool_thenNoEceptions() {
try (PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager()) {
connManager.setMaxTotal(5);
connManager.setDefaultMaxPerRoute(4);
HttpHost host = new HttpHost("www.baeldung.com", 80);
connManager.setMaxPerRoute(new HttpRoute(host), 5);
}
}
// Example 4.2. Using Threads to Execute Connections
@Test
public final void whenExecutingSameRequestsInDifferentThreads_thenExecuteReuqest() throws InterruptedException {
HttpGet get = new HttpGet("http://www.baeldung.com");
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(connManager)
.build();
MultiHttpClientConnThread thread1 = new MultiHttpClientConnThread(client, get);
MultiHttpClientConnThread thread2 = new MultiHttpClientConnThread(client, get);
MultiHttpClientConnThread thread3 = new MultiHttpClientConnThread(client, get);
thread1.start();
thread2.start();
thread3.start();
thread1.join();
thread2.join();
thread3.join();
}
// Example 5.1. A Custom Keep Alive Strategy
@Test
public final void whenCustomizingKeepAliveStrategy_thenNoExceptions() {
final ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy() {
@Override
public long getKeepAliveDuration(final HttpResponse myResponse, final HttpContext myContext) {
final HeaderElementIterator it = new BasicHeaderElementIterator(myResponse.headerIterator(HTTP.CONN_KEEP_ALIVE));
while (it.hasNext()) {
final HeaderElement he = it.nextElement();
final String param = he.getName();
final String value = he.getValue();
if ((value != null) && param.equalsIgnoreCase("timeout")) {
return Long.parseLong(value) * 1000;
}
}
final HttpHost target = (HttpHost) myContext.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
if ("localhost".equalsIgnoreCase(target.getHostName())) {
return 10 * 1000;
} else {
return 5 * 1000;
}
}
};
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
HttpClients.custom()
.setKeepAliveStrategy(myStrategy)
.setConnectionManager(connManager)
.build();
}
// Example 6.1. BasicHttpClientConnectionManager Connection Reuse
@Test
public final void givenBasicHttpClientConnManager_whenConnectionReuse_thenNoExceptions() throws IOException, HttpException, InterruptedException, ExecutionException {
BasicHttpClientConnectionManager basicConnManager = new BasicHttpClientConnectionManager();
HttpClientContext context = HttpClientContext.create();
// low level
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 443));
ConnectionRequest connRequest = basicConnManager.requestConnection(route, null);
HttpClientConnection conn = connRequest.get(10, TimeUnit.SECONDS);
basicConnManager.connect(conn, route, 1000, context);
basicConnManager.routeComplete(conn, route, context);
HttpRequestExecutor exeRequest = new HttpRequestExecutor();
context.setTargetHost((new HttpHost("www.baeldung.com", 80)));
HttpGet get = new HttpGet("http://www.baeldung.com");
exeRequest.execute(get, conn, context);
basicConnManager.releaseConnection(conn, null, 1, TimeUnit.SECONDS);
// high level
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(basicConnManager)
.build();
client.execute(get);
}
// Example 6.2. PoolingHttpClientConnectionManager: Re-Using Connections with Threads
@Test
public final void whenConnectionsNeededGreaterThanMaxTotal_thenLeaseMasTotalandReuse() throws InterruptedException {
HttpGet get = new HttpGet("http://echo.200please.com");
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
connManager.setDefaultMaxPerRoute(5);
connManager.setMaxTotal(5);
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(connManager)
.build();
MultiHttpClientConnThread[] threads = new MultiHttpClientConnThread[10];
for (int i = 0; i < threads.length; i++) {
threads[i] = new MultiHttpClientConnThread(client, get, connManager);
}
for (MultiHttpClientConnThread thread : threads) {
thread.start();
}
for (MultiHttpClientConnThread thread : threads) {
thread.join(1000);
}
}
// Example 7.1. Setting Socket Timeout to 5 Seconds
@Test
public final void whenConfiguringTimeOut_thenNoExceptions() {
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 80));
try (PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager()) {
connManager.setSocketConfig(route.getTargetHost(), SocketConfig.custom()
.setSoTimeout(5000)
.build());
assertTrue(connManager.getSocketConfig(route.getTargetHost())
.getSoTimeout() == 5000);
}
}
// Example 8.1. Setting the HttpClient to Check for Stale Connections
@Test
public final void whenHttpClientChecksStaleConns_thenNoExceptions() {
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
HttpClients.custom()
.setDefaultRequestConfig(RequestConfig.custom()
.setStaleConnectionCheckEnabled(true)
.build())
.setConnectionManager(connManager)
.build();
}
// Example 8.2. Using a Stale Connection Monitor Thread
@Test
public final void whenCustomizedIdleConnMonitor_thenNoExceptions() throws InterruptedException {
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
HttpClients.custom()
.setConnectionManager(connManager)
.build();
IdleConnectionMonitorThread staleMonitor = new IdleConnectionMonitorThread(connManager);
staleMonitor.start();
staleMonitor.join(1000);
}
// Example 9.1. Closing Connection and Releasing Resources
@Test(expected = IllegalStateException.class)
public final void whenClosingConnectionsandManager_thenCloseWithNoExceptions1() throws InterruptedException, ExecutionException, IOException, HttpException {
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(connManager)
.build();
final HttpGet get = new HttpGet("http://google.com");
CloseableHttpResponse response = client.execute(get);
EntityUtils.consume(response.getEntity());
response.close();
client.close();
connManager.close();
connManager.shutdown();
client.execute(get);
assertTrue(response.getEntity() == null);
}
@Test
// Example 3.2. TESTER VERSION
public final void whenTwoConnectionsForTwoRequests_thenTwoConnectionsAreLeased() throws InterruptedException {
HttpGet get1 = new HttpGet("https://www.baeldung.com");
HttpGet get2 = new HttpGet("https://www.google.com");
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
final CloseableHttpClient client1 = HttpClients.custom()
.setConnectionManager(poolingConnManager)
.build();
final CloseableHttpClient client2 = HttpClients.custom()
.setConnectionManager(poolingConnManager)
.build();
final TesterVersion_MultiHttpClientConnThread thread1 = new TesterVersion_MultiHttpClientConnThread(client1, get1, poolingConnManager);
final TesterVersion_MultiHttpClientConnThread thread2 = new TesterVersion_MultiHttpClientConnThread(client2, get2, poolingConnManager);
thread1.start();
thread2.start();
thread1.join();
thread2.join(1000);
assertTrue(poolingConnManager.getTotalStats()
.getLeased() == 2);
}
@Test
// Example 4.2 Tester Version
public final void whenExecutingSameRequestsInDifferentThreads_thenUseDefaultConnLimit() throws InterruptedException {
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(poolingConnManager)
.build();
final TesterVersion_MultiHttpClientConnThread thread1 = new TesterVersion_MultiHttpClientConnThread(client, new HttpGet("http://www.google.com"), poolingConnManager);
final TesterVersion_MultiHttpClientConnThread thread2 = new TesterVersion_MultiHttpClientConnThread(client, new HttpGet("http://www.google.com"), poolingConnManager);
final TesterVersion_MultiHttpClientConnThread thread3 = new TesterVersion_MultiHttpClientConnThread(client, new HttpGet("http://www.google.com"), poolingConnManager);
thread1.start();
thread2.start();
thread3.start();
thread1.join(10000);
thread2.join(10000);
thread3.join(10000);
}
@Test
// 6.2 TESTER VERSION
public final void whenConnectionsNeededGreaterThanMaxTotal_thenReuseConnections() throws InterruptedException {
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
poolingConnManager.setDefaultMaxPerRoute(5);
poolingConnManager.setMaxTotal(5);
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(poolingConnManager)
.build();
final MultiHttpClientConnThread[] threads = new MultiHttpClientConnThread[10];
int countConnMade = 0;
for (int i = 0; i < threads.length; i++) {
threads[i] = new MultiHttpClientConnThread(client, new HttpGet("http://www.baeldung.com/"), poolingConnManager);
}
for (final MultiHttpClientConnThread thread : threads) {
thread.start();
}
for (final MultiHttpClientConnThread thread : threads) {
thread.join(10000);
countConnMade++;
if (countConnMade == 0) {
assertTrue(thread.getLeasedConn() == 5);
}
}
}
@Test
@Ignore("Very Long Running")
// 8.2 TESTER VERSION
public final void whenCustomizedIdleConnMonitor_thenEliminateIdleConns() throws InterruptedException {
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
CloseableHttpClient client = HttpClients.custom()
.setConnectionManager(poolingConnManager)
.build();
final IdleConnectionMonitorThread staleMonitor = new IdleConnectionMonitorThread(poolingConnManager);
final HttpGet get = new HttpGet("http://google.com");
final TesterVersion_MultiHttpClientConnThread thread1 = new TesterVersion_MultiHttpClientConnThread(client, get, poolingConnManager);
final TesterVersion_MultiHttpClientConnThread thread2 = new TesterVersion_MultiHttpClientConnThread(client, get, poolingConnManager);
final TesterVersion_MultiHttpClientConnThread thread3 = new TesterVersion_MultiHttpClientConnThread(client, get, poolingConnManager);
staleMonitor.start();
thread1.start();
thread1.join();
thread2.start();
thread2.join();
thread3.start();
assertTrue(poolingConnManager.getTotalStats()
.getAvailable() == 1);
thread3.join(32000);
assertTrue(poolingConnManager.getTotalStats()
.getAvailable() == 0);
}
}

View File

@ -0,0 +1,41 @@
package com.baeldung.httpclient.httpclient.conn;
import java.util.concurrent.TimeUnit;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
public class IdleConnectionMonitorThread extends Thread {
private final HttpClientConnectionManager connMgr;
private volatile boolean shutdown;
IdleConnectionMonitorThread(final PoolingHttpClientConnectionManager connMgr) {
super();
this.connMgr = connMgr;
}
// API
@Override
public final void run() {
try {
while (!shutdown) {
synchronized (this) {
wait(1000);
connMgr.closeExpiredConnections();
connMgr.closeIdleConnections(30, TimeUnit.SECONDS);
}
}
} catch (final InterruptedException ex) {
shutdown();
}
}
private void shutdown() {
shutdown = true;
synchronized (this) {
notifyAll();
}
}
}

View File

@ -0,0 +1,69 @@
package com.baeldung.httpclient.httpclient.conn;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MultiHttpClientConnThread extends Thread {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final CloseableHttpClient client;
private final HttpGet get;
private PoolingHttpClientConnectionManager connManager;
private int leasedConn;
MultiHttpClientConnThread(final CloseableHttpClient client, final HttpGet get, final PoolingHttpClientConnectionManager connManager) {
this.client = client;
this.get = get;
this.connManager = connManager;
leasedConn = 0;
}
MultiHttpClientConnThread(final CloseableHttpClient client, final HttpGet get) {
this.client = client;
this.get = get;
}
// API
final int getLeasedConn() {
return leasedConn;
}
//
@Override
public final void run() {
try {
logger.debug("Thread Running: " + getName());
logger.debug("Thread Running: " + getName());
if (connManager != null) {
logger.info("Before - Leased Connections = " + connManager.getTotalStats().getLeased());
logger.info("Before - Available Connections = " + connManager.getTotalStats().getAvailable());
}
final HttpResponse response = client.execute(get);
if (connManager != null) {
leasedConn = connManager.getTotalStats().getLeased();
logger.info("After - Leased Connections = " + connManager.getTotalStats().getLeased());
logger.info("After - Available Connections = " + connManager.getTotalStats().getAvailable());
}
EntityUtils.consume(response.getEntity());
} catch (final IOException ex) {
logger.error("", ex);
}
}
}

View File

@ -0,0 +1,46 @@
package com.baeldung.httpclient.httpclient.conn;
import java.io.IOException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
public class TesterVersion_MultiHttpClientConnThread extends Thread {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final CloseableHttpClient client;
private final HttpGet get;
private PoolingHttpClientConnectionManager connManager;
TesterVersion_MultiHttpClientConnThread(final CloseableHttpClient client, final HttpGet get, final PoolingHttpClientConnectionManager connManager) {
this.client = client;
this.get = get;
this.connManager = Preconditions.checkNotNull(connManager);
}
//
@Override
public final void run() {
try {
logger.debug("Thread Running: " + getName());
logger.info("Before - Leased Connections = " + connManager.getTotalStats().getLeased());
logger.info("Before - Available Connections = " + connManager.getTotalStats().getAvailable());
client.execute(get);
logger.info("After - Leased Connections = " + connManager.getTotalStats().getLeased());
logger.info("After - Available Connections = " + connManager.getTotalStats().getAvailable());
} catch (final IOException ex) {
logger.error("", ex);
}
}
}

View File

@ -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)

View File

@ -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)

View File

@ -2,26 +2,21 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.baeldung</groupId>
<artifactId>aws-s3-update-object</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>aws-s3-update-object</name>
<description>Project demonstrating overwriting of S3 objects</description>
<properties>
<java.version>17</java.version>
</properties>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
@ -30,10 +25,9 @@
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.12.523</version>
<version>${aws-java-sdk-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
@ -42,5 +36,7 @@
</plugin>
</plugins>
</build>
<properties>
<aws-java-sdk-version>1.12.523</aws-java-sdk-version>
</properties>
</project>

View File

@ -7,13 +7,13 @@ import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import jakarta.annotation.PostConstruct;
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;

View File

@ -11,6 +11,7 @@ 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;
@ -34,28 +35,28 @@ public class FileControllerUnitTest {
@Test
public void givenValidMultipartFile_whenUploadedViaEndpoint_thenCorrectPathIsReturned() throws Exception {
MockMultipartFile multipartFile = new MockMultipartFile("multipartFile", "test.txt",
"text/plain", "test data".getBytes());
MockMultipartFile multipartFile = new MockMultipartFile("file", "test.txt", "text/plain", "sample file content".getBytes());
String expectedResult = "File Uploaded Successfully";
when(fileService.uploadFile(any(MultipartFile.class))).thenReturn("/documents/test.txt");
when(fileService.uploadFile(multipartFile)).thenReturn(expectedResult);
mockMvc.perform(multipart("/file/upload").file(multipartFile))
mockMvc.perform(multipart("/api/v1/file/upload").file(multipartFile))
.andExpect(status().isOk())
.andExpect(content().string("/documents/test.txt"));
.andExpect(content().string(expectedResult));
}
@Test
public void givenValidMultipartFileAndExistingPath_whenUpdatedViaEndpoint_thenSamePathIsReturned() throws Exception {
MockMultipartFile multipartFile = new MockMultipartFile("multipartFile", "test.txt",
"text/plain", "test update data".getBytes());
String existingFilePath = "/documents/existingFile.txt";
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(any(MultipartFile.class), eq(existingFilePath))).thenReturn(existingFilePath);
when(fileService.updateFile(multipartFile, filePath)).thenReturn(expectedResult);
mockMvc.perform(multipart("/file/update")
mockMvc.perform(multipart("/api/v1/file/update")
.file(multipartFile)
.param("exitingFilePath", existingFilePath))
.param("filePath", filePath))
.andExpect(status().isOk())
.andExpect(content().string(existingFilePath));
.andExpect(content().string(expectedResult));
}
}

View File

@ -41,6 +41,7 @@ public class FileServiceUnitTest {
@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));
@ -57,6 +58,7 @@ public class FileServiceUnitTest {
@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));

View File

@ -8,4 +8,5 @@ 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)
- [Listing All AWS S3 Objects in a Bucket Using Java](https://www.baeldung.com/java-aws-s3-list-bucket-objects)
- [Update an Existing Amazon S3 Object Using Java](https://www.baeldung.com/java-update-amazon-s3-object)

View File

@ -0,0 +1,79 @@
package com.baeldung.s3;
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.services.s3.model.CopyObjectRequest;
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
import software.amazon.awssdk.services.s3.model.S3Object;
public class RenameObjectService {
private S3Client s3Client;
public RenameObjectService(S3Client s3Client) {
this.s3Client = s3Client;
}
public RenameObjectService() {
init();
}
public void init() {
this.s3Client = S3Client.builder()
.region(Region.US_EAST_1)
.credentialsProvider(ProfileCredentialsProvider.create("default"))
.build();
}
public void renameFile(String bucketName, String keyName, String destinationKeyName) {
CopyObjectRequest copyObjRequest = CopyObjectRequest.builder()
.sourceBucket(bucketName)
.sourceKey(keyName)
.destinationBucket(destinationKeyName)
.destinationKey(bucketName)
.build();
s3Client.copyObject(copyObjRequest);
DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
.bucket(bucketName)
.key(keyName)
.build();
s3Client.deleteObject(deleteRequest);
}
public void renameFolder(String bucketName, String sourceFolderKey, String destinationFolderKey) {
ListObjectsV2Request listRequest = ListObjectsV2Request.builder()
.bucket(bucketName)
.prefix(sourceFolderKey)
.build();
ListObjectsV2Response listResponse = s3Client.listObjectsV2(listRequest);
List<S3Object> objects = listResponse.contents();
for (S3Object s3Object : objects) {
String newKey = destinationFolderKey + s3Object.key()
.substring(sourceFolderKey.length());
// Copy object to destination folder
CopyObjectRequest copyRequest = CopyObjectRequest.builder()
.sourceBucket(bucketName)
.sourceKey(s3Object.key())
.destinationBucket(bucketName)
.destinationKey(newKey)
.build();
s3Client.copyObject(copyRequest);
// Delete object from source folder
DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
.bucket(bucketName)
.key(s3Object.key())
.build();
s3Client.deleteObject(deleteRequest);
}
}
}

View File

@ -19,6 +19,7 @@
<module>aws-miscellaneous</module>
<module>aws-reactive</module>
<module>aws-s3</module>
<module>aws-s3-update-object</module>
</modules>
<properties>

View File

@ -0,0 +1,126 @@
package com.baeldung.multipleorwithif;
import static java.time.Month.DECEMBER;
import static java.time.Month.NOVEMBER;
import static java.time.Month.OCTOBER;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.in;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.time.Month;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.function.Predicate;
import org.junit.jupiter.api.Test;
class MultipleOrWithIfUnitTest {
private final Random rand = new Random();
final Set<Month> months = Set.of(OCTOBER, NOVEMBER, DECEMBER);
@Test
public void givenIfStatement_whenMultipleOrOperator_thenAssert() {
assertTrue(multipleOrOperatorIf(monthIn()));
assertFalse(multipleOrOperatorIf(monthNotIn()));
}
boolean multipleOrOperatorIf(Month month) {
if (month == OCTOBER || month == NOVEMBER || month == DECEMBER) {
return true;
}
return false;
}
@Test
public void givenSwitch_whenMultipleCase_thenBreakAndAssert() {
assertTrue(switchMonth(monthIn()));
assertFalse(switchMonth(monthNotIn()));
}
boolean switchMonth(Month month) {
return switch (month) {
case OCTOBER, NOVEMBER, DECEMBER -> true;
default -> false;
};
}
@Test
public void givenAllowedValuesList_whenContains_thenAssert() {
assertTrue(contains(monthIn()));
assertFalse(contains(monthNotIn()));
}
@Test
public void givenPredicates_whenTestMultipleOr_thenAssert() {
assertTrue(predicateWithIf(monthIn()));
assertFalse(predicateWithIf(monthNotIn()));
}
@Test
public void givenInputList_whenFilterWithPredicate_thenAssert() {
List<Month> list = List.of(monthIn(), monthIn(), monthNotIn());
list.stream()
.filter(this::predicateWithIf)
.forEach(m -> assertThat(m, is(in(months))));
}
Predicate<Month> orPredicate() {
Predicate<Month> predicate = x -> x == OCTOBER;
Predicate<Month> predicate1 = x -> x == NOVEMBER;
Predicate<Month> predicate2 = x -> x == DECEMBER;
return predicate.or(predicate1)
.or(predicate2);
}
boolean predicateWithIf(Month month) {
if (orPredicate().test(month)) {
return true;
}
return false;
}
@Test
public void givenContainsInSetPredicate_whenTestPredicate_thenAssert() {
Predicate<Month> collectionPredicate = this::contains;
assertTrue(collectionPredicate.test(monthIn()));
assertFalse(collectionPredicate.test(monthNotIn()));
}
@Test
public void givenInputList_whenFilterWithContains_thenAssert() {
List<Month> monthList = List.of(monthIn(), monthIn(), monthNotIn());
monthList.stream()
.filter(this::contains)
.forEach(m -> assertThat(m, is(in(months))));
}
private boolean contains(Month month) {
if (months.contains(month)) {
return true;
}
return false;
}
private Month monthIn() {
return Month.of(rand.ints(10, 13)
.findFirst()
.orElse(10));
}
private Month monthNotIn() {
return Month.of(rand.ints(1, 10)
.findFirst()
.orElse(1));
}
}

View File

@ -9,3 +9,4 @@ This module contains articles about arrays conversion in Java
- [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)

View File

@ -13,3 +13,4 @@ This module contains articles about advanced operations on arrays in Java. They
- [Performance of System.arraycopy() vs. Arrays.copyOf()](https://www.baeldung.com/java-system-arraycopy-arrays-copyof-performance)
- [Slicing Arrays in Java](https://www.baeldung.com/java-slicing-arrays)
- [Combining Two or More Byte Arrays](https://www.baeldung.com/java-concatenate-byte-arrays)
- [Calculating the Sum of Two Arrays in Java](https://www.baeldung.com/java-sum-arrays-element-wise)

View File

@ -12,4 +12,6 @@ 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)
- [Get the First n Elements of a List Into an Array](https://www.baeldung.com/java-take-start-elements-list-array)
- More articles: [[<-- prev]](../core-java-collections-conversions)

View File

@ -9,4 +9,5 @@ This module contains articles about Map data structures in Java.
- [Collections.synchronizedMap vs. ConcurrentHashMap](https://www.baeldung.com/java-synchronizedmap-vs-concurrenthashmap)
- [Java HashMap Load Factor](https://www.baeldung.com/java-hashmap-load-factor)
- [Converting Java Properties to HashMap](https://www.baeldung.com/java-convert-properties-to-hashmap)
- [Get Values and Keys as ArrayList From a HashMap](https://www.baeldung.com/java-values-keys-arraylists-hashmap)
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-2)

View File

@ -8,3 +8,4 @@
- [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)

View File

@ -20,6 +20,17 @@
<version>${junit-platform.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.7.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.1-jre</version>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,75 @@
package com.baeldung.cartesianproduct;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.google.common.collect.Sets;
public class CartesianProduct {
public List<List<Object>> getCartesianProductIterative(List<List<Object>> sets) {
List<List<Object>> result = new ArrayList<>();
if(sets == null || sets.isEmpty()) {
return result;
}
int totalSets = sets.size();
int totalCombinations = 1 << totalSets;
for(int i = 0; i < totalCombinations; i++) {
List<Object> combination = new ArrayList<>();
for(int j = 0; j < totalSets; j++) {
if (((i >> j) & 1) == 1) {
combination.add(sets.get(j).get(0));
} else {
combination.add(sets.get(j).get(1));
}
}
result.add(combination);
}
return result;
}
public List<List<Object>> getCartesianProductRecursive(List<List<Object>> sets) {
List<List<Object>> result = new ArrayList<>();
getCartesianProductRecursiveHelper(sets, 0, new ArrayList<>(), result);
return result;
}
private void getCartesianProductRecursiveHelper(List<List<Object>> sets, int index, List<Object> current, List<List<Object>> result) {
if(index == sets.size()) {
result.add(new ArrayList<>(current));
return;
}
List<Object> currentSet = sets.get(index);
for(Object element: currentSet) {
current.add(element);
getCartesianProductRecursiveHelper(sets, index+1, current, result);
current.remove(current.size() - 1);
}
}
public List<List<Object>> getCartesianProductUsingStreams(List<List<Object>> sets) {
return cartesianProduct(sets,0).collect(Collectors.toList());
}
public Stream<List<Object>> cartesianProduct(List<List<Object>> sets, int index) {
if(index == sets.size()) {
List<Object> emptyList = new ArrayList<>();
return Stream.of(emptyList);
}
List<Object> currentSet = sets.get(index);
return currentSet.stream().flatMap(element -> cartesianProduct(sets, index+1)
.map(list -> {
List<Object> newList = new ArrayList<>(list);
newList.add(0, element); return newList;
}));
}
public List<List<Object>> getCartesianProductUsingGuava(List<Set<Object>> sets) {
Set<List<Object>> cartesianProduct = Sets.cartesianProduct(sets);
List<List<Object>> cartesianList = new ArrayList<>(cartesianProduct);
return cartesianList;
}
}

View File

@ -0,0 +1,93 @@
package com.baeldung.cartesianproduct;
import static org.testng.Assert.assertEquals;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.testng.annotations.Test;
public class CartesianProductUnitTest {
private CartesianProduct cp = new CartesianProduct();
List<List<Object>> sets = Arrays.asList(
Arrays.asList(10, 20),
Arrays.asList("John", "Jack"),
Arrays.asList('I', 'J')
);
@Test
public void whenUsingStreams_thenCalculateCartesianProduct() {
List<List<Object>> expected = Arrays.asList(
Arrays.asList(10, "John", 'I'),
Arrays.asList(10, "John", 'J'),
Arrays.asList(10, "Jack", 'I'),
Arrays.asList(10, "Jack", 'J'),
Arrays.asList(20, "John", 'I'),
Arrays.asList(20, "John", 'J'),
Arrays.asList(20, "Jack", 'I'),
Arrays.asList(20, "Jack", 'J')
);
List<List<Object>> cartesianProduct = cp.getCartesianProductUsingStreams(sets);
assertEquals(expected, cartesianProduct);
}
@Test
public void whenUsingRecursion_thenCalculateCartesianProduct() {
List<List<Object>> expected = Arrays.asList(
Arrays.asList(10, "John", 'I'),
Arrays.asList(10, "John", 'J'),
Arrays.asList(10, "Jack", 'I'),
Arrays.asList(10, "Jack", 'J'),
Arrays.asList(20, "John", 'I'),
Arrays.asList(20, "John", 'J'),
Arrays.asList(20, "Jack", 'I'),
Arrays.asList(20, "Jack", 'J')
);
List<List<Object>> cartesianProduct = cp.getCartesianProductRecursive(sets);
assertEquals(expected, cartesianProduct);
}
@Test
public void whenUsingIterativeApproach_thenCalculateCartesianProduct() {
List<List<Object>> expected = Arrays.asList(
Arrays.asList(20, "Jack", 'J'),
Arrays.asList(10, "Jack", 'J'),
Arrays.asList(20, "John", 'J'),
Arrays.asList(10, "John", 'J'),
Arrays.asList(20, "Jack", 'I'),
Arrays.asList(10, "Jack", 'I'),
Arrays.asList(20, "John", 'I'),
Arrays.asList(10, "John", 'I')
);
List<List<Object>> cartesianProduct = cp.getCartesianProductIterative(sets);
assertEquals(expected, cartesianProduct);
}
@Test
public void whenUsingGuava_thenCalculateCartesianProduct() {
List<Set<Object>> sets = new ArrayList<>();
sets.add(new HashSet<>(Arrays.asList(10, 20)));
sets.add(new HashSet<>(Arrays.asList("John", "Jack")));
sets.add(new HashSet<>(Arrays.asList('I', 'J')));
List<List<Object>> expected = Arrays.asList(
Arrays.asList(20, "John", 'I'),
Arrays.asList(20, "John", 'J'),
Arrays.asList(20, "Jack", 'I'),
Arrays.asList(20, "Jack", 'J'),
Arrays.asList(10, "John", 'I'),
Arrays.asList(10, "John", 'J'),
Arrays.asList(10, "Jack", 'I'),
Arrays.asList(10, "Jack", 'J')
);
List<List<Object>> cartesianProduct = cp.getCartesianProductUsingGuava(sets);
assertEquals(expected, cartesianProduct);
}
}

View File

@ -7,31 +7,37 @@ import java.util.concurrent.Phaser;
class LongRunningAction implements Runnable {
private static Logger log = LoggerFactory.getLogger(LongRunningAction.class);
private String threadName;
private Phaser ph;
private static final Logger log = LoggerFactory.getLogger(LongRunningAction.class);
private final String threadName;
private final Phaser ph;
LongRunningAction(String threadName, Phaser ph) {
this.threadName = threadName;
this.ph = ph;
this.randomWait();
ph.register();
log.info("Thread {} registered during phase {}", threadName, ph.getPhase());
}
@Override
public void run() {
log.info("This is phase {}", ph.getPhase());
log.info("Thread {} before long running action", threadName);
log.info("Thread {} BEFORE long running action in phase {}", threadName, ph.getPhase());
ph.arriveAndAwaitAdvance();
randomWait();
log.info("Thread {} AFTER long running action in phase {}", threadName, ph.getPhase());
ph.arriveAndDeregister();
}
// Simulating real work
private void randomWait() {
try {
Thread.sleep(2000);
Thread.sleep((long) (Math.random() * 100));
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("Thread {} action completed and waiting for others", threadName);
ph.arriveAndAwaitAdvance();
log.debug("Thread {} proceeding in phase {}", threadName, ph.getPhase());
ph.arriveAndDeregister();
}
}

View File

@ -7,8 +7,6 @@ import org.junit.runners.MethodSorters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Phaser;
import static junit.framework.TestCase.assertEquals;
@ -16,38 +14,32 @@ import static junit.framework.TestCase.assertEquals;
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class PhaserUnitTest {
private static Logger log = LoggerFactory.getLogger(PhaserUnitTest.class);
private static final Logger log = LoggerFactory.getLogger(PhaserUnitTest.class);
@Test
public void givenPhaser_whenCoordinateWorksBetweenThreads_thenShouldCoordinateBetweenMultiplePhases() {
//given
ExecutorService executorService = Executors.newCachedThreadPool();
public void givenPhaser_whenCoordinateWorksBetweenThreads_thenShouldCoordinateBetweenMultiplePhases() throws InterruptedException {
Phaser ph = new Phaser(1);
assertEquals(0, ph.getPhase());
//when
executorService.submit(new LongRunningAction("thread-1", ph));
executorService.submit(new LongRunningAction("thread-2", ph));
executorService.submit(new LongRunningAction("thread-3", ph));
new Thread(new LongRunningAction("thread-1", ph)).start();
new Thread(new LongRunningAction("thread-2", ph)).start();
new Thread(new LongRunningAction("thread-3", ph)).start();
//then
log.debug("Thread {} waiting for others", Thread.currentThread().getName());
log.info("Thread {} waiting for others", Thread.currentThread().getName());
ph.arriveAndAwaitAdvance();
log.debug("Thread {} proceeding in phase {}", Thread.currentThread().getName(), ph.getPhase());
log.info("Thread {} proceeding in phase {}", Thread.currentThread().getName(), ph.getPhase());
assertEquals(1, ph.getPhase());
//and
executorService.submit(new LongRunningAction("thread-4", ph));
executorService.submit(new LongRunningAction("thread-5", ph));
new Thread(new LongRunningAction("thread-4", ph)).start();
new Thread(new LongRunningAction("thread-5", ph)).start();
log.debug("Thread {} waiting for others", Thread.currentThread().getName());
log.info("Thread {} waiting for new phase", Thread.currentThread().getName());
ph.arriveAndAwaitAdvance();
log.debug("Thread {} proceeding in phase {}", Thread.currentThread().getName(), ph.getPhase());
log.info("Thread {} proceeding in phase {}", Thread.currentThread().getName(), ph.getPhase());
assertEquals(2, ph.getPhase());
ph.arriveAndDeregister();
Thread.sleep(1000);
assertEquals(true, ph.isTerminated());
}
}

View File

@ -11,4 +11,5 @@ This module contains articles about basic Java concurrency
- [Runnable vs. Callable in Java](https://www.baeldung.com/java-runnable-callable)
- [What Is Thread-Safety and How to Achieve It?](https://www.baeldung.com/java-thread-safety)
- [How to Get Notified When a Task Completes in Java Executors](https://www.baeldung.com/java-executors-task-completed-notification)
- [Difference Between Future, CompletableFuture, and Rxjavas Observable](https://www.baeldung.com/java-future-completablefuture-rxjavas-observable)
- [[Next -->]](/core-java-modules/core-java-concurrency-basic-2)

View File

@ -3,3 +3,4 @@
This module contains articles about Java Conditionals.
### Relevant articles:
- [Guide to the yield Keyword in Java](https://www.baeldung.com/java-yield-switch)

View File

@ -8,3 +8,5 @@ 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)
- [Convert Epoch Time to LocalDate and LocalDateTime](https://www.baeldung.com/java-convert-epoch-localdate)

View File

@ -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();
}
}
}
}
}

View File

@ -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();
}
}

View File

@ -38,9 +38,9 @@
<version>${fscontext.version}</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1</version>
<groupId>org.eclipse.angus</groupId>
<artifactId>angus-activation</artifactId>
<version>${angus-activation.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
@ -73,10 +73,6 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>${maven-javadoc-plugin.version}</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<!-- Build an executable JAR -->
@ -131,13 +127,15 @@
<properties>
<!-- maven plugins -->
<maven-javadoc-plugin.version>3.0.0-M1</maven-javadoc-plugin.version>
<hsqldb.version>2.4.0</hsqldb.version>
<maven-javadoc-plugin.version>3.5.0</maven-javadoc-plugin.version>
<hsqldb.version>2.7.1</hsqldb.version>
<!-- Mime Type Libraries -->
<tika.version>1.18</tika.version>
<tika.version>2.8.0</tika.version>
<jmime-magic.version>0.1.5</jmime-magic.version>
<maven-jar-plugin.version>3.1.0</maven-jar-plugin.version>
<maven-jar-plugin.version>3.3.0</maven-jar-plugin.version>
<fscontext.version>4.4.2</fscontext.version>
<jakarta-activation-api.version>2.1.2</jakarta-activation-api.version>
<angus-activation.version>2.0.1</angus-activation.version>
</properties>
</project>

View File

@ -10,7 +10,7 @@ import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.activation.MimetypesFileTypeMap;
import jakarta.activation.MimetypesFileTypeMap;
import org.apache.tika.Tika;
import org.junit.Test;

View File

@ -0,0 +1,2 @@
## Relevant Articles
- [Creating a Magic Square in Java](https://www.baeldung.com/java-magic-square)

View File

@ -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<T> Class Do in Java?](https://www.baeldung.com/java-holder-class)

View File

@ -12,3 +12,4 @@ This module contains articles about inheritance in Java
- [Guide to Inheritance in Java](https://www.baeldung.com/java-inheritance)
- [Object Type Casting in Java](https://www.baeldung.com/java-type-casting)
- [Variable and Method Hiding in Java](https://www.baeldung.com/java-variable-method-hiding)
- [Inner Classes Vs. Subclasses in Java](https://www.baeldung.com/java-inner-classes-vs-subclasses)

View File

@ -1,11 +1,12 @@
package com.baeldung.subclassinnerclass;
import java.util.HashMap;
public class EmailNotifier extends Notifier {
@Override
void notify(Message e) {
// Provide email specific implementation here
// connect to the email connector
EmailConnector emailConnector = new EmailConnector();
emailConnector.connect();
// send email
}
// Inner class for email connection
@ -13,5 +14,9 @@ public class EmailNotifier extends Notifier {
private String emailHost;
private int emailPort;
// Getter Setters
private void connect() {
// connect to the smtp server
}
}
}

View File

@ -1,54 +1,77 @@
package com.baeldung.modulo;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import static org.assertj.core.api.Java6Assertions.*;
public class ModuloUnitTest {
@Test
public void whenIntegerDivision_thenLosesRemainder(){
assertThat(11 / 4).isEqualTo(2);
}
@Test
public void whenDoubleDivision_thenKeepsRemainder(){
assertThat(11 / 4.0).isEqualTo(2.75);
}
@Test
public void whenModulo_thenReturnsRemainder(){
assertThat(11 % 4).isEqualTo(3);
}
@Test(expected = ArithmeticException.class)
public void whenDivisionByZero_thenArithmeticException(){
double result = 1 / 0;
}
@Test(expected = ArithmeticException.class)
public void whenModuloByZero_thenArithmeticException(){
double result = 1 % 0;
}
@Test
public void whenDivisorIsOddAndModulusIs2_thenResultIs1(){
assertThat(3 % 2).isEqualTo(1);
}
@Test
public void whenDivisorIsEvenAndModulusIs2_thenResultIs0(){
assertThat(4 % 2).isEqualTo(0);
}
@Test
public void whenItemsIsAddedToCircularQueue_thenNoArrayIndexOutOfBounds(){
int QUEUE_CAPACITY= 10;
int[] circularQueue = new int[QUEUE_CAPACITY];
int itemsInserted = 0;
for (int value = 0; value < 1000; value++) {
int writeIndex = ++itemsInserted % QUEUE_CAPACITY;
circularQueue[writeIndex] = value;
@Test
public void whenIntegerDivision_thenLosesRemainder() {
assertThat(11 / 4).isEqualTo(2);
}
@Test
public void whenDoubleDivision_thenKeepsRemainder() {
assertThat(11 / 4.0).isEqualTo(2.75);
}
@Test
public void whenModulo_thenReturnsRemainder() {
assertThat(11 % 4).isEqualTo(3);
}
@Test(expected = ArithmeticException.class)
public void whenDivisionByZero_thenArithmeticException() {
double result = 1 / 0;
}
@Test(expected = ArithmeticException.class)
public void whenModuloByZero_thenArithmeticException() {
double result = 1 % 0;
}
@Test
public void whenDivisorIsOddAndModulusIs2_thenResultIs1() {
assertThat(3 % 2).isEqualTo(1);
}
@Test
public void whenDivisorIsEvenAndModulusIs2_thenResultIs0() {
assertThat(4 % 2).isEqualTo(0);
}
@Test
public void whenDividendIsNegativeAndModulusIs2_thenResultIsNegative() {
assertEquals(-1, -9 % 2);
}
@Test
public void whenDividendIsNegativeAndRemainderIsCheckedForNegativeValue_thenResultIsPositive() {
int remainder = -9 % 2;
if (remainder < 0) {
remainder += 2;
}
assertEquals(1, remainder);
}
@Test
public void whenDividendIsNegativeAndUsesMathClass_thenResultIsPositive() {
int remainder = Math.floorMod(-9, 2);
assertEquals(1, remainder);
}
@Test
public void whenItemsIsAddedToCircularQueue_thenNoArrayIndexOutOfBounds() {
int QUEUE_CAPACITY = 10;
int[] circularQueue = new int[QUEUE_CAPACITY];
int itemsInserted = 0;
for (int value = 0; value < 1000; value++) {
int writeIndex = ++itemsInserted % QUEUE_CAPACITY;
circularQueue[writeIndex] = value;
}
}
}
}

View File

@ -30,13 +30,13 @@ public class Java8ComparatorUnitTest {
System.out.println("************** Java 8 Comaparator **************");
Comparator<Player> 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<Player> 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<Player> 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);
}
}

View File

@ -0,0 +1,75 @@
package com.baeldung.regex.indexesofmatches;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.jupiter.api.Test;
public class IndexesOfMatchesUnitTest {
private static final String INPUT = "This line contains <the first value>, <the second value>, and <the third value>.";
@Test
void whenUsingNorCharClass_thenGetExpectedTexts() {
Pattern pattern = Pattern.compile("<[^>]*>");
Matcher matcher = pattern.matcher(INPUT);
List<String> result = new ArrayList<>();
while (matcher.find()) {
result.add(matcher.group());
}
assertThat(result).containsExactly("<the first value>", "<the second value>", "<the third value>");
}
@Test
void whenCallingMatcherEnd_thenGetIndexesAfterTheMatchSequence() {
Pattern pattern = Pattern.compile("456");
Matcher matcher = pattern.matcher("0123456789");
String result = null;
int startIdx = -1;
int endIdx = -1;
if (matcher.find()) {
result = matcher.group();
startIdx = matcher.start();
endIdx = matcher.end();
}
assertThat(result).isEqualTo("456");
assertThat(startIdx).isEqualTo(4);
assertThat(endIdx).isEqualTo(7);
}
@Test
void whenUsingMatcherStartAndEnd_thenGetIndexesOfMatches() {
Pattern pattern = Pattern.compile("<[^>]*>");
Matcher matcher = pattern.matcher(INPUT);
List<String> result = new ArrayList<>();
Map<Integer, Integer> indexesOfMatches = new LinkedHashMap<>();
while (matcher.find()) {
result.add(matcher.group());
indexesOfMatches.put(matcher.start(), matcher.end());
}
assertThat(result).containsExactly("<the first value>", "<the second value>", "<the third value>");
assertThat(indexesOfMatches.entrySet()).map(entry -> INPUT.substring(entry.getKey(), entry.getValue()))
.containsExactly("<the first value>", "<the second value>", "<the third value>");
}
@Test
void whenUsingMatcherStartAndEndWithGroupIdx_thenGetIndexesOfMatches() {
Pattern pattern = Pattern.compile("<([^>]*)>");
Matcher matcher = pattern.matcher(INPUT);
List<String> result = new ArrayList<>();
Map<Integer, Integer> indexesOfMatches = new LinkedHashMap<>();
while (matcher.find()) {
result.add(matcher.group(1));
indexesOfMatches.put(matcher.start(1), matcher.end(1));
}
assertThat(result).containsExactly("the first value", "the second value", "the third value");
assertThat(indexesOfMatches.entrySet()).map(entry -> INPUT.substring(entry.getKey(), entry.getValue()))
.containsExactly("the first value", "the second value", "the third value");
}
}

View File

@ -0,0 +1,98 @@
package com.baeldung.regex.squarebrackets;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.junit.jupiter.api.Test;
import com.google.common.collect.Lists;
public class ExtractTextBetweenSquareBracketsUnitTest {
static final String INPUT1 = "some text [THE IMPORTANT MESSAGE] something else";
static final String EXPECTED1 = "THE IMPORTANT MESSAGE";
static final String INPUT2 = "[La La Land], [The last Emperor], and [Life of Pi] are all great movies.";
static final List<String> EXPECTED2 = Lists.newArrayList("La La Land", "The last Emperor", "Life of Pi");
@Test
void whenUsingDotStarOnInput1_thenGetExpectedResult() {
String result = null;
String rePattern = "\\[(.*)]";
Pattern p = Pattern.compile(rePattern);
Matcher m = p.matcher(INPUT1);
if (m.find()) {
result = m.group(1);
}
assertThat(result).isEqualTo(EXPECTED1);
}
@Test
void whenUsingCharClassOnInput1_thenGetExpectedResult() {
String result = null;
String rePattern = "\\[([^]]*)";
Pattern p = Pattern.compile(rePattern);
Matcher m = p.matcher(INPUT1);
if (m.find()) {
result = m.group(1);
}
assertThat(result).isEqualTo(EXPECTED1);
}
@Test
void whenUsingSplitOnInput1_thenGetExpectedResult() {
String[] strArray = INPUT1.split("[\\[\\]]", -1);
String result = strArray.length == 3 ? strArray[1] : null;
assertThat(result).isEqualTo(EXPECTED1);
}
@Test
void whenUsingSplitWithLimit_thenGetExpectedResult() {
String[] strArray = "[THE IMPORTANT MESSAGE]".split("[\\[\\]]");
assertThat(strArray).hasSize(2)
.containsExactly("", "THE IMPORTANT MESSAGE");
strArray = "[THE IMPORTANT MESSAGE]".split("[\\[\\]]", -1);
assertThat(strArray).hasSize(3)
.containsExactly("", "THE IMPORTANT MESSAGE", "");
}
@Test
void whenUsingNonGreedyOnInput2_thenGetExpectedResult() {
List<String> result = new ArrayList<>();
String rePattern = "\\[(.*?)]";
Pattern p = Pattern.compile(rePattern);
Matcher m = p.matcher(INPUT2);
while (m.find()) {
result.add(m.group(1));
}
assertThat(result).isEqualTo(EXPECTED2);
}
@Test
void whenUsingCharClassOnInput2_thenGetExpectedResult() {
List<String> result = new ArrayList<>();
String rePattern = "\\[([^]]*)";
Pattern p = Pattern.compile(rePattern);
Matcher m = p.matcher(INPUT2);
while (m.find()) {
result.add(m.group(1));
}
assertThat(result).isEqualTo(EXPECTED2);
}
@Test
void whenUsingSplitInput2_thenGetExpectedResult() {
List<String> result = new ArrayList<>();
String[] strArray = INPUT2.split("[\\[\\]]", -1);
for (int i = 1; i < strArray.length; i += 2) {
result.add(strArray[i]);
}
assertThat(result).isEqualTo(EXPECTED2);
}
}

View File

@ -33,7 +33,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${google-guava.version}</version>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
@ -47,7 +47,6 @@
<commons-codec.version>1.15</commons-codec.version>
<jaxb-api.version>2.3.1</jaxb-api.version>
<spring-security-crypto.version>6.0.3</spring-security-crypto.version>
<google-guava.version>31.0.1-jre</google-guava.version>
</properties>
</project>

View File

@ -39,7 +39,7 @@
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.23.1</version>
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
<dependency>
@ -55,7 +55,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
<version>${commons-lang3.version}</version>
<scope>test</scope>
</dependency>
<dependency>
@ -81,7 +81,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${google.guava.version}</version>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>com.oath.cyclops</groupId>
@ -114,6 +114,7 @@
<properties>
<!-- testing -->
<assertj.version>3.23.1</assertj.version>
<maven-compiler-plugin.version>3.1</maven-compiler-plugin.version>
<maven.compiler.source>12</maven.compiler.source>
<maven.compiler.target>12</maven.compiler.target>
@ -123,7 +124,6 @@
<io.varv.version>1.0.0-alpha-4</io.varv.version>
<io.reactor3.version>3.5.1</io.reactor3.version>
<apache.commons.collection4.version>4.4</apache.commons.collection4.version>
<google.guava.version>31.1-jre</google.guava.version>
<cyclops.version>10.4.1</cyclops.version>
</properties>

View File

@ -14,33 +14,6 @@
</parent>
<dependencies>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>${jmh-core.version}</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${jmh-generator.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.codepoetics</groupId>
<artifactId>protonpack</artifactId>
@ -57,17 +30,7 @@
<version>${streamex.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${asspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${asspectj.version}</version>
</dependency>
<dependency>
<groupId>pl.touk</groupId>
<groupId>com.pivovarit</groupId>
<artifactId>throwing-function</artifactId>
<version>${throwing-function.version}</version>
</dependency>
@ -96,15 +59,13 @@
</build>
<properties>
<vavr.version>0.9.0</vavr.version>
<protonpack.version>1.15</protonpack.version>
<streamex.version>0.6.5</streamex.version>
<joda.version>2.10</joda.version>
<throwing-function.version>1.3</throwing-function.version>
<asspectj.version>1.8.9</asspectj.version>
<maven-compiler-plugin.version>3.1</maven-compiler-plugin.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<vavr.version>0.10.4</vavr.version>
<protonpack.version>1.16</protonpack.version>
<streamex.version>0.8.1</streamex.version>
<throwing-function.version>1.5.1</throwing-function.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
</project>

View File

@ -1,8 +1,8 @@
package com.baeldung.stream.filter;
import org.junit.jupiter.api.Test;
import pl.touk.throwing.ThrowingPredicate;
import pl.touk.throwing.exception.WrappedException;
import com.pivovarit.function.ThrowingPredicate;
import com.pivovarit.function.exception.WrappedException;
import java.io.IOException;
import java.util.Arrays;
@ -156,5 +156,4 @@ public class StreamFilterUnitTest {
})
.collect(Collectors.toList())).isInstanceOf(RuntimeException.class);
}
}
}

View File

@ -22,7 +22,7 @@
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>com.ibm.icu</groupId>
@ -42,8 +42,6 @@
</build>
<properties>
<commons.lang3.version>3.12.0</commons.lang3.version>
<guava.version>31.1-jre</guava.version>
<icu4j.version>61.1</icu4j.version>
</properties>

View File

@ -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)

View File

@ -4,4 +4,4 @@ This module contains articles about Avaje
### Relevant articles:
- [Introduction to Avaje Inject](https://www.baeldung.com/avaje-inject/intro)
- [Introduction to Avaje Inject](https://www.baeldung.com/avaje-inject)

View File

@ -27,7 +27,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
<guava.version>31.1-jre</guava.version>
<guava.version>32.1.2-jre</guava.version>
</properties>
</project>

View File

@ -49,7 +49,7 @@
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<guava.version>31.1-jre</guava.version>
<guava.version>32.1.2-jre</guava.version>
</properties>
</project>

View File

@ -20,6 +20,7 @@ import org.joda.time.DateTimeZone;
import org.junit.Test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.util.StdDateFormat;
@ -67,6 +68,8 @@ public class JacksonDateUnitTest {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.findAndRegisterModules();
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.enable(SerializationFeature.WRITE_DATES_WITH_ZONE_ID);
objectMapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("UTC"));
String converted = objectMapper.writeValueAsString(now);

View File

@ -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)

View File

@ -3,7 +3,7 @@
This module contains articles about Bean Validation.
### Relevant Articles:
- [Java Bean Validation Basics](https://www.baeldung.com/javax-validation)
- [Java Bean Validation Basics](https://www.baeldung.com/java-validation)
- [Validating Container Elements with Jakarta Bean Validation 3.0](https://www.baeldung.com/bean-validation-container-elements)
- [Validations for Enum Types](https://www.baeldung.com/javax-validations-enums)
- [Javax BigDecimal Validation](https://www.baeldung.com/javax-bigdecimal-validation)

View File

@ -13,5 +13,6 @@ This module contains articles about JSON.
- [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)
- [Programmatic Generation of JSON Schemas in Java](https://www.baeldung.com/java-json-schema-create-automatically)
- More Articles: [[<-- prev]](/json-modules/json)

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>json-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
@ -123,6 +123,26 @@
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>com.github.victools</groupId>
<artifactId>jsonschema-generator</artifactId>
<version>${jsonschema-generator.version}</version>
</dependency>
<dependency>
<groupId>com.github.victools</groupId>
<artifactId>jsonschema-module-jackson</artifactId>
<version>${jsonschema-generator.version}</version>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>${jakarta.validation.version}</version>
</dependency>
<dependency>
<groupId>com.github.victools</groupId>
<artifactId>jsonschema-module-jakarta-validation</artifactId>
<version>${jsonschema-generator.version}</version>
</dependency>
</dependencies>
<build>
@ -162,6 +182,55 @@
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>com.github.victools</groupId>
<artifactId>jsonschema-maven-plugin</artifactId>
<version>${jsonschema-generator.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<packageNames>
<packageName>com.baeldung.jsonschemageneration.plugin</packageName>
</packageNames>
<classNames>
<className>com.baeldung.jsonschemageneration.plugin.Person</className>
</classNames>
<schemaVersion>DRAFT_2020_12</schemaVersion>
<schemaFilePath>src/main/resources/schemas</schemaFilePath>
<schemaFileName>{1}/{0}.json</schemaFileName>
<failIfNoClassesMatch>true</failIfNoClassesMatch>
<options>
<preset>PLAIN_JSON</preset>
<enabled>
<option>DEFINITIONS_FOR_ALL_OBJECTS</option>
<option>FORBIDDEN_ADDITIONAL_PROPERTIES_BY_DEFAULT</option>
</enabled>
<disabled>SCHEMA_VERSION_INDICATOR</disabled>
</options>
<modules>
<module>
<name>Jackson</name>
<options>
<option>RESPECT_JSONPROPERTY_REQUIRED</option>
</options>
</module>
<module>
<name>JakartaValidation</name>
<options>
<option>NOT_NULLABLE_FIELD_IS_REQUIRED</option>
<option>INCLUDE_PATTERN_EXPRESSIONS</option>
</options>
</module>
</modules>
</configuration>
</plugin>
</plugins>
</build>
<properties>
@ -173,6 +242,8 @@
<jackson-jsonld.version>0.1.1</jackson-jsonld.version>
<hydra-jsonld.version>0.4.2</hydra-jsonld.version>
<jsonld-java.version>0.13.0</jsonld-java.version>
<jsonschema-generator.version>4.31.1</jsonschema-generator.version>
<jakarta.validation.version>3.0.2</jakarta.validation.version>
</properties>
</project>

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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();
}

View File

@ -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());
}
}

View File

@ -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<Person> friends;
}
static class Address {
@JsonProperty()
String street;
@JsonProperty(required = true)
String city;
@JsonProperty(required = true)
String country;
}
}

View File

@ -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<Person> friends;
}
static class Address {
@Null String street;
@NotNull String city;
@NotNull String country;
}
}

View File

@ -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<Person> friends;
}
class Address {
@Null
@JsonProperty
String street;
@NotNull
@JsonProperty(required = true)
String city;
@NotNull
@JsonProperty(required = true)
String country;
}

View File

@ -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<AuthoredArticle> articles;
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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
}

View File

@ -0,0 +1,2 @@
## Relevant Articles
- [How to Check if a Value Exists in a JSON Array for a Particular Key](https://www.baeldung.com/java-json-array-check-key-value-pair)

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.baeldung</groupId>
<artifactId>json-arrays</artifactId>
<name>json-arrays</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>json-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>${json.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>javax.json.bind</groupId>
<artifactId>javax.json.bind-api</artifactId>
<version>${jsonb-api.version}</version>
</dependency>
</dependencies>
<properties>
<jsonb-api.version>1.0</jsonb-api.version>
<json.version>20230227</json.version>
<gson.version>2.8.5</gson.version>
<javax.version>1.1.2</javax.version>
<json-unit-assertj.version>2.28.0</json-unit-assertj.version>
</properties>
</project>

View File

@ -0,0 +1,47 @@
package com.baeldung.checkforkey;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Objects;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.junit.jupiter.api.Test;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
public class CheckForKeyUnitTest {
private final String exampleJson = "[{\"colour\":\"red\"},{\"colour\":\"blue\"},{\"colour\":\"green\"}]";
@Test
public void givenJsonArray_whenUsingJackson_thenDetectKeyInArray() throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
JsonNode tree = objectMapper.readTree(exampleJson);
Stream<JsonNode> s = StreamSupport.stream(tree.spliterator(), false);
boolean result = s.map(entry -> entry.get("colour"))
.filter(Objects::nonNull)
.anyMatch(colour -> "green".equals(colour.asText()));
assertTrue(result);
}
@Test
public void givenJsonArray_whenUsingGson_thenDetectKeyInArray() {
Gson gson = new Gson();
JsonArray parsed = gson.fromJson(exampleJson, JsonArray.class);
Stream<JsonElement> s = StreamSupport.stream(parsed.spliterator(), false);
boolean result = s.map(entry -> entry.getAsJsonObject()
.get("colour"))
.filter(Objects::nonNull)
.anyMatch(colour -> "green".equals(colour.getAsString()));
assertTrue(result);
}
}

View File

@ -16,6 +16,7 @@
<modules>
<module>json</module>
<module>json-2</module>
<module>json-arrays</module>
<module>json-conversion</module>
<module>json-path</module>
<module>gson</module>

View File

@ -0,0 +1,2 @@
## Relevant Articles
- [Guide to Eclipse JKube](https://www.baeldung.com/ops/eclipse-jkube)

View File

@ -25,10 +25,58 @@
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>${javax.annotation}</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger.annotation}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>${openapi.version}</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${project.basedir}/src/main/resources/bookapi.yml</inputSpec>
<generatorName>java</generatorName>
<modelPackage>com.baeldung.openapi.model</modelPackage>
<configOptions>
<additionalModelTypeAnnotations>@lombok.Data @lombok.NoArgsConstructor @lombok.AllArgsConstructor</additionalModelTypeAnnotations>
</configOptions>
<generateApis>false</generateApis>
<generateSupportingFiles>false</generateSupportingFiles>
<generateApiDocumentation>false</generateApiDocumentation>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<openapi.version>4.2.3</openapi.version>
<gson.version>2.10.1</gson.version>
<javax.annotation>1.3.2</javax.annotation>
<swagger.annotation>1.6.2</swagger.annotation>
</properties>
</project>

View File

@ -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;
}

View File

@ -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

View File

@ -43,7 +43,6 @@
</build>
<properties>
<lombok.version>edge-SNAPSHOT</lombok.version>
<hibernate-jpa-2.1-api.version>1.0.0.Final</hibernate-jpa-2.1-api.version>
<delombok-maven-plugin.version>1.18.20.0</delombok-maven-plugin.version>
<annotations.version>23.0.0</annotations.version>

View File

@ -16,7 +16,7 @@
</parent>
<modules>
<!--<module>lombok</module>--> <!-- Fixing in JAVA-24006 -->
<module>lombok</module>
<module>lombok-2</module>
<!-- <module>lombok-custom</module>--> <!-- this module uses legacy jdk-8 features (tools.jar), so can't upgrade to jdk9 or above-->
</modules>

View File

@ -0,0 +1,21 @@
package com.baeldung.expression.dto;
import java.time.LocalDateTime;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
@AllArgsConstructor
@Data
@Builder
public class LicenseDto {
private UUID id;
private LocalDateTime startDate;
private LocalDateTime endDate;
}

View File

@ -0,0 +1,43 @@
package com.baeldung.expression.mapper;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import com.baeldung.expression.dto.LicenseDto;
import com.baeldung.expression.model.License;
@Mapper
public interface LicenseMapper {
@Mapping(target = "startDate", expression = "java(mapStartDate(licenseDto))")
@Mapping(target = "endDate", ignore = true)
@Mapping(target = "active", constant = "true")
@Mapping(target = "renewalRequired", conditionExpression = "java(isEndDateInTwoWeeks(licenseDto))", source = ".")
License toLicense(LicenseDto licenseDto);
@AfterMapping
default void afterMapping(LicenseDto licenseDto, @MappingTarget License license) {
OffsetDateTime endDate = licenseDto.getEndDate() != null ? licenseDto.getEndDate()
.atOffset(ZoneOffset.UTC) : OffsetDateTime.now()
.plusYears(1);
license.setEndDate(endDate);
}
default OffsetDateTime mapStartDate(LicenseDto licenseDto) {
return licenseDto.getStartDate() != null ? licenseDto.getStartDate()
.atOffset(ZoneOffset.UTC) : OffsetDateTime.now();
}
default boolean isEndDateInTwoWeeks(LicenseDto licenseDto) {
return licenseDto.getEndDate() != null && Duration.between(licenseDto.getEndDate(), LocalDateTime.now())
.toDays() <= 14;
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.expression.model;
import java.time.OffsetDateTime;
import java.util.UUID;
import lombok.Data;
@Data
public class License {
private UUID id;
private OffsetDateTime startDate;
private OffsetDateTime endDate;
private boolean active;
private boolean renewalRequired;
}

View File

@ -0,0 +1,64 @@
package com.baeldung.expression.mapper;
import static org.assertj.core.api.Assertions.assertThat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import org.junit.jupiter.api.Test;
import org.mapstruct.factory.Mappers;
import com.baeldung.expression.dto.LicenseDto;
import com.baeldung.expression.model.License;
class LicenseMapperUnitTest {
LicenseMapper licenseMapper = Mappers.getMapper(LicenseMapper.class);
@Test
void givenLicenseDtoWithStartDateAndWithoutEndDate_WhenMapperMethodIsInvoked_ThenLicenseShouldBePopulatedWithDefaultEndDate() {
License license = licenseMapper.toLicense(LicenseDto.builder()
.startDate(LocalDateTime.now())
.build());
assertThat(license).isNotNull();
assertThat(license.getEndDate()
.toLocalDate()).isEqualTo(LocalDate.now()
.plusYears(1));
}
@Test
void givenLicenseDtoWithEndDateAndWithoutStartDate_WhenMapperMethodIsInvoked_ThenLicenseShouldBePopulatedWithDefaultStartDate() {
License license = licenseMapper.toLicense(LicenseDto.builder()
.endDate(LocalDateTime.now()
.plusYears(2))
.build());
assertThat(license).isNotNull();
assertThat(license.getStartDate()
.toLocalDate()).isEqualTo(LocalDate.now());
}
@Test
void givenLicenseDtoWithoutStartDateAndEndDate_WhenMapperMethodIsInvoked_ThenLicenseShouldBePopulatedWithDefaultDetails() {
License license = licenseMapper.toLicense(LicenseDto.builder()
.build());
assertThat(license).isNotNull();
assertThat(license.getStartDate()
.toLocalDate()).isEqualTo(LocalDate.now());
assertThat(license.getEndDate()
.toLocalDate()).isEqualTo(LocalDate.now()
.plusYears(1));
assertThat(license.isActive()).isTrue();
assertThat(license.isRenewalRequired()).isFalse();
}
@Test
void givenLicenseDtoWithEndDateInTwoWeeks_WhenMapperMethodIsInvoked_ThenLicenseShouldBePopulatedWithRenewalRequiredSetToTrue() {
License license = licenseMapper.toLicense(LicenseDto.builder()
.endDate(LocalDateTime.now()
.plusDays(10))
.build());
assertThat(license).isNotNull();
assertThat(license.isRenewalRequired()).isTrue();
}
}

View File

@ -0,0 +1,2 @@
## Relevant Articles
- [How to Speed Up Maven Build](https://www.baeldung.com/maven-fast-build)

2
pants/README.md Normal file
View File

@ -0,0 +1,2 @@
## Relevant Articles
- [Introduction to the Pants Build Tool](https://www.baeldung.com/ops/pants-build-tool-guide)

View File

@ -9,3 +9,4 @@
- [Get the Number of Rows in a ResultSet](https://www.baeldung.com/java-resultset-number-of-rows)
- [Converting a JDBC ResultSet to JSON in Java](https://www.baeldung.com/java-jdbc-convert-resultset-to-json)
- [Guide to MicroStream](https://www.baeldung.com/microstream-intro)
- [Executing SQL Script File in Java](https://www.baeldung.com/java-run-sql-script)

View File

@ -70,6 +70,16 @@
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring-jdbc.version}</version>
</dependency>
</dependencies>
<properties>
@ -80,6 +90,8 @@
<json.version>20220320</json.version>
<microstream.storage.version>07.00.00-MS-GA</microstream.storage.version>
<h2.version>2.1.214</h2.version>
<spring-jdbc.version>5.3.29</spring-jdbc.version>
<mybatis.version>3.5.7</mybatis.version>
</properties>
</project>

View File

@ -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));
}
}

View File

@ -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
);
}
}

View File

@ -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<String> sqlStatements = parseSQLScript(scriptFilePath);
executeSQLBatches(connection, sqlStatements, batchSize);
}
private static List<String> parseSQLScript(String scriptFilePath) throws IOException {
List<String> 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<String> 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();
}
}

View File

@ -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);
}
}
}

Some files were not shown because too many files have changed in this diff Show More