Compare commits
362 Commits
disable-su
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83209e30f9 | ||
|
|
9fd719365b | ||
|
|
4eb7bef34b | ||
|
|
dcccf2eda7 | ||
|
|
97dd38eb79 | ||
|
|
7907282829 | ||
|
|
9ad7d24c9e | ||
|
|
a5eb9418c8 | ||
|
|
65e31eaf04 | ||
|
|
20e135aea1 | ||
|
|
1691ad32b6 | ||
|
|
0c87b2a3bf | ||
|
|
23681f9e1e | ||
|
|
5fe1c28e51 | ||
|
|
25c0f9b685 | ||
|
|
41829046c5 | ||
|
|
fb99901305 | ||
|
|
b6f4803197 | ||
|
|
1d3fa127f4 | ||
|
|
c9b87071ab | ||
|
|
09f2a5c584 | ||
|
|
951856e2cc | ||
|
|
a9f54033d5 | ||
|
|
55ba37d848 | ||
|
|
b724c59c38 | ||
|
|
e02964ff81 | ||
|
|
2b6ee3104d | ||
|
|
3e450193dd | ||
|
|
7217ee5e0c | ||
|
|
7588462856 | ||
|
|
b0998fd931 | ||
|
|
273a20e8e5 | ||
|
|
8f5965b7e8 | ||
|
|
ff430e69d5 | ||
|
|
b3fdbcb76f | ||
|
|
5311e96930 | ||
|
|
5b2dd26fa3 | ||
|
|
293206c419 | ||
|
|
ff7e5bad9b | ||
|
|
f1feec3922 | ||
|
|
300f1f3816 | ||
|
|
f4bb7bf36f | ||
|
|
936fad8c02 | ||
|
|
5983194d95 | ||
|
|
2e70b5cd87 | ||
|
|
e8bce0690e | ||
|
|
2b422a9ba1 | ||
|
|
6f9cda355d | ||
|
|
3dc7772f1f | ||
|
|
942e8f4932 | ||
|
|
ba2854ef9e | ||
|
|
078a09393a | ||
|
|
573f511bb3 | ||
|
|
0dba825b34 | ||
|
|
31046a3ae2 | ||
|
|
18e5ca49de | ||
|
|
6cadb7c902 | ||
|
|
8897d1a81d | ||
|
|
4bd2e1eedb | ||
|
|
911ff75935 | ||
|
|
862e85c92c | ||
|
|
527c797381 | ||
|
|
e4d766b808 | ||
|
|
9363253c81 | ||
|
|
d4a7abdd49 | ||
|
|
dac91ce751 | ||
|
|
b077616346 | ||
|
|
0d2c280b7f | ||
|
|
0529c7f612 | ||
|
|
a879aceef7 | ||
|
|
07e0abff43 | ||
|
|
bc8d43ce09 | ||
|
|
9e9182125d | ||
|
|
0685a8702c | ||
|
|
ee4b4ce003 | ||
|
|
664e9d1932 | ||
|
|
bb1d29302b | ||
|
|
1298e1d4f7 | ||
|
|
b738c458ac | ||
|
|
2423f086f6 | ||
|
|
6fe37fca81 | ||
|
|
53572725ad | ||
|
|
9d0a18e30c | ||
|
|
f725c8f592 | ||
|
|
7fbae56aa6 | ||
|
|
a3127e5f36 | ||
|
|
15a6467a90 | ||
|
|
592f8f325a | ||
|
|
48510fb972 | ||
|
|
d94e994649 | ||
|
|
df4a024ed9 | ||
|
|
91a32ed0c3 | ||
|
|
f4f979b6f8 | ||
|
|
652804a1a9 | ||
|
|
a1239f9a87 | ||
|
|
8dfae82f04 | ||
|
|
67ecc95a5b | ||
|
|
6e7b87c158 | ||
|
|
3bb7d4b8e6 | ||
|
|
dbbf86a134 | ||
|
|
00a7141670 | ||
|
|
081bfeac8d | ||
|
|
64d62681fb | ||
|
|
1283ec5e3a | ||
|
|
ca1cf088fa | ||
|
|
bf5580ac1f | ||
|
|
c3a5bbfb50 | ||
|
|
0b2081f192 | ||
|
|
cd86b428e3 | ||
|
|
045603a42c | ||
|
|
2fbbc8c8dd | ||
|
|
56ea493c7a | ||
|
|
6ae8b47fde | ||
|
|
b4776ae6e8 | ||
|
|
b3d8c2be30 | ||
|
|
77b4f3fd6b | ||
|
|
fa71ab1c2c | ||
|
|
a83ac4e518 | ||
|
|
51384cfe5b | ||
|
|
4d93508004 | ||
|
|
67750f826c | ||
|
|
39579dac85 | ||
|
|
0e90b0bab5 | ||
|
|
a7a32cf941 | ||
|
|
11c829407b | ||
|
|
e5ac465318 | ||
|
|
80d9ba94cc | ||
|
|
dc549ea8e1 | ||
|
|
4f29709fcb | ||
|
|
4d50eb5fac | ||
|
|
6420a38e4c | ||
|
|
4bcffd739e | ||
|
|
238131f7dc | ||
|
|
337d84af04 | ||
|
|
2a1e2ccc97 | ||
|
|
1a6a175eea | ||
|
|
7e6159a614 | ||
|
|
902d9c4211 | ||
|
|
0c64afdc3c | ||
|
|
feeeda5790 | ||
|
|
3749d715db | ||
|
|
5b78209475 | ||
|
|
67d46acf4f | ||
|
|
28af304222 | ||
|
|
90e7dbc436 | ||
|
|
de266d4ce9 | ||
|
|
7ffc7509ac | ||
|
|
4632f48371 | ||
|
|
1e42a14da5 | ||
|
|
704623997b | ||
|
|
06c65d31f2 | ||
|
|
3ab0227b44 | ||
|
|
0c9fb3e4c8 | ||
|
|
d0b8e00616 | ||
|
|
31cdd64a6d | ||
|
|
135dc03404 | ||
|
|
1ce8b575ca | ||
|
|
f35a6731fe | ||
|
|
68886c7eec | ||
|
|
18368ddc78 | ||
|
|
6646b4aacf | ||
|
|
6044c33bbf | ||
|
|
a1cda19109 | ||
|
|
8f4b6f3958 | ||
|
|
617c4aa853 | ||
|
|
938c139dab | ||
|
|
43f4244c5f | ||
|
|
c967c495ba | ||
|
|
099d31fb31 | ||
|
|
0a87bede16 | ||
|
|
9689957cef | ||
|
|
08948357a7 | ||
|
|
890528d586 | ||
|
|
ea01bfb93b | ||
|
|
d6f8a28cfb | ||
|
|
e91b1d207d | ||
|
|
3ad2b35740 | ||
|
|
f172b88348 | ||
|
|
0b6b689ebe | ||
|
|
270b951436 | ||
|
|
c9cf8c4826 | ||
|
|
1cabb213c2 | ||
|
|
32bf0a3e96 | ||
|
|
ce66399788 | ||
|
|
db7e73adbd | ||
|
|
02fc18f339 | ||
|
|
a827a1e4ce | ||
|
|
971f92a31e | ||
|
|
a542f67d05 | ||
|
|
ca72f2751e | ||
|
|
1ffaa1d6ec | ||
|
|
0425206335 | ||
|
|
f923aefb36 | ||
|
|
e6d5b50b63 | ||
|
|
141b63458b | ||
|
|
d7587cb7bd | ||
|
|
918cc4e78f | ||
|
|
63687814a6 | ||
|
|
ec690507e3 | ||
|
|
61a164c223 | ||
|
|
98b1d9a02a | ||
|
|
7f3b053de1 | ||
|
|
e6d5f167f1 | ||
|
|
56cba80a26 | ||
|
|
c67dbbae8f | ||
|
|
949fd14f3a | ||
|
|
b7f78ad015 | ||
|
|
c775ada172 | ||
|
|
b3642a4dfb | ||
|
|
6e44436d2a | ||
|
|
11f5467ad8 | ||
|
|
f2034aac6a | ||
|
|
7af33fd363 | ||
|
|
2bf147a9c9 | ||
|
|
986f0e013c | ||
|
|
5c0774b179 | ||
|
|
00046ed219 | ||
|
|
24d5ed2590 | ||
|
|
ccf801d988 | ||
|
|
adece4963d | ||
|
|
670e8997a8 | ||
|
|
9efede2dfb | ||
|
|
fccc35f81d | ||
|
|
0c4c39b59d | ||
|
|
81c323006e | ||
|
|
ef1afdf7c1 | ||
|
|
9622f8cd3a | ||
|
|
3641ea6703 | ||
|
|
060c025412 | ||
|
|
f285f79eda | ||
|
|
a02237ac03 | ||
|
|
b6ae2b0c9b | ||
|
|
f181edd5c0 | ||
|
|
e0fa825655 | ||
|
|
6768672f67 | ||
|
|
4761ca8b95 | ||
|
|
cd0e69b639 | ||
|
|
76fbe5f9d7 | ||
|
|
181002c85f | ||
|
|
fc19db6466 | ||
|
|
376ae54a3c | ||
|
|
e492a336c4 | ||
|
|
671b53094f | ||
|
|
40acdedbdb | ||
|
|
28ee6916c5 | ||
|
|
35d91b24cd | ||
|
|
ead5dae1c8 | ||
|
|
186b2b1bde | ||
|
|
06828fc665 | ||
|
|
3e398814a0 | ||
|
|
7f69ecac8c | ||
|
|
94587194a0 | ||
|
|
bec037581d | ||
|
|
537b00df32 | ||
|
|
950b72b945 | ||
|
|
64574dc508 | ||
|
|
eda35f874f | ||
|
|
ae0d468b8c | ||
|
|
9f8e3f2d12 | ||
|
|
dfc24e55f2 | ||
|
|
f1a0a54652 | ||
|
|
a7a7875e3c | ||
|
|
ff838d515d | ||
|
|
8c838267ff | ||
|
|
62a8ae6fcf | ||
|
|
6aad3df50a | ||
|
|
15bcf02b33 | ||
|
|
f9f4a59037 | ||
|
|
7874709740 | ||
|
|
59355d1516 | ||
|
|
6236dfc5a3 | ||
|
|
813bb92dbd | ||
|
|
cbe39fb7b9 | ||
|
|
c3a88ad2bc | ||
|
|
ed5feb0173 | ||
|
|
a3ba5cc0c5 | ||
|
|
74c5b6fee7 | ||
|
|
998bd1b8f1 | ||
|
|
a79e163efd | ||
|
|
4ea3b59240 | ||
|
|
93a058e398 | ||
|
|
4c89855cae | ||
|
|
5644c2eeb3 | ||
|
|
62064f509c | ||
|
|
01c05d3141 | ||
|
|
13f6fe2729 | ||
|
|
8ffca600fc | ||
|
|
28d1260f39 | ||
|
|
0c1a7bf5d1 | ||
|
|
4321edfd38 | ||
|
|
95161a0f36 | ||
|
|
4a174c632d | ||
|
|
1bb301488b | ||
|
|
a1ef4ba4c1 | ||
|
|
719f6c02d1 | ||
|
|
3e88ff856a | ||
|
|
e568cee6e1 | ||
|
|
cbde128cd4 | ||
|
|
e89a549b17 | ||
|
|
a9fbd0abd9 | ||
|
|
1a59338b4b | ||
|
|
e0ff30f586 | ||
|
|
4f9178ca3c | ||
|
|
99ac8fb3d4 | ||
|
|
44a53d60f5 | ||
|
|
7cb5c91624 | ||
|
|
1a6f36a5c8 | ||
|
|
84b4b57ea8 | ||
|
|
68d4b90f44 | ||
|
|
f5c5c07258 | ||
|
|
2968fef94c | ||
|
|
8e342e1fb8 | ||
|
|
8faa5aae08 | ||
|
|
52bae947db | ||
|
|
a874d06a93 | ||
|
|
a319915703 | ||
|
|
b7022b8bea | ||
|
|
cbe76b01dd | ||
|
|
190b049d87 | ||
|
|
dd3cc86721 | ||
|
|
5016a64ef9 | ||
|
|
aa8a817f31 | ||
|
|
6ebc7adb1c | ||
|
|
970c03dc94 | ||
|
|
b884f4cba5 | ||
|
|
54d0a7b0a3 | ||
|
|
4c1041da9c | ||
|
|
e2662a415d | ||
|
|
b1784c483b | ||
|
|
31619d936a | ||
|
|
577bcb9cae | ||
|
|
fc8207115b | ||
|
|
e6fcd7fe65 | ||
|
|
74e7b1abe4 | ||
|
|
e8e4ae8ce3 | ||
|
|
194c7f0f24 | ||
|
|
e113fe4035 | ||
|
|
ffef2f7e00 | ||
|
|
f549ac8bbe | ||
|
|
d5cdaa2965 | ||
|
|
ce538a6250 | ||
|
|
5ce87e0104 | ||
|
|
81ef29d764 | ||
|
|
1a4d59a3ab | ||
|
|
1423fcaa31 | ||
|
|
d6af55c8f7 | ||
|
|
7c32029120 | ||
|
|
d06645ee6e | ||
|
|
8f791d5117 | ||
|
|
565f743307 | ||
|
|
2bb0e319fb | ||
|
|
57aa0edf16 | ||
|
|
cbc9c23a9b | ||
|
|
257a5b4171 | ||
|
|
76f2e48458 | ||
|
|
285bec2531 | ||
|
|
8841a720a9 | ||
|
|
30009184e6 | ||
|
|
c966588a95 | ||
|
|
b426490cb3 | ||
|
|
f562c27a04 | ||
|
|
c96199e4a5 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -124,4 +124,7 @@ devDb*.db
|
||||
*.xjb
|
||||
|
||||
#neo4j
|
||||
persistence-modules/neo4j/data/**
|
||||
persistence-modules/neo4j/data/**
|
||||
/deep-shallow-copy/.mvn/wrapper
|
||||
/deep-shallow-copy/mvnw
|
||||
/deep-shallow-copy/mvnw.cmd
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -43,19 +43,19 @@
|
||||
<dependency>
|
||||
<groupId>com.sun.xml.ws</groupId>
|
||||
<artifactId>jaxws-ri</artifactId>
|
||||
<version>2.3.3</version>
|
||||
<version>${jaxws-ri.version}</version>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>4.0.1</version>
|
||||
<version>${javax.servlet-api.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
<version>1.2</version>
|
||||
<version>${jstl.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -117,7 +117,9 @@
|
||||
<properties>
|
||||
<spring.version>5.3.25</spring.version>
|
||||
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
|
||||
<maven-war-plugin.version>3.3.2</maven-war-plugin.version>
|
||||
<jstl.version>1.2</jstl.version>
|
||||
<javax.servlet-api.version>4.0.1</javax.servlet-api.version>
|
||||
<jaxws-ri.version>2.3.3</jaxws-ri.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -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);
|
||||
|
||||
@@ -1,29 +1,5 @@
|
||||
package com.baeldung.httpclient.advancedconfig;
|
||||
|
||||
|
||||
import com.github.tomakehurst.wiremock.junit.WireMockRule;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.AuthCache;
|
||||
import org.apache.http.client.CredentialsProvider;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.auth.BasicScheme;
|
||||
import org.apache.http.impl.client.BasicAuthCache;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.containing;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
|
||||
@@ -34,6 +10,30 @@ import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.hc.client5.http.auth.AuthCache;
|
||||
import org.apache.hc.client5.http.auth.AuthScope;
|
||||
import org.apache.hc.client5.http.auth.CredentialsProvider;
|
||||
import org.apache.hc.client5.http.auth.StandardAuthScheme;
|
||||
import org.apache.hc.client5.http.classic.HttpClient;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpPost;
|
||||
import org.apache.hc.client5.http.impl.auth.BasicAuthCache;
|
||||
import org.apache.hc.client5.http.impl.auth.BasicScheme;
|
||||
import org.apache.hc.client5.http.impl.auth.CredentialsProviderBuilder;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||
import org.apache.hc.client5.http.impl.routing.DefaultProxyRoutePlanner;
|
||||
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
||||
import org.apache.hc.core5.http.HttpHeaders;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
import org.apache.hc.core5.http.HttpResponse;
|
||||
import org.apache.hc.core5.http.io.entity.StringEntity;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.github.tomakehurst.wiremock.junit.WireMockRule;
|
||||
|
||||
public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||
|
||||
@Rule
|
||||
@@ -59,7 +59,7 @@ public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||
HttpResponse response = httpClient.execute(httpGet);
|
||||
|
||||
//then
|
||||
assertEquals(response.getStatusLine().getStatusCode(), 200);
|
||||
assertEquals(response.getCode(), 200);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -82,7 +82,7 @@ public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||
HttpResponse response = httpClient.execute(httpPost);
|
||||
|
||||
//then
|
||||
assertEquals(response.getStatusLine().getStatusCode(), 200);
|
||||
assertEquals(response.getCode(), 200);
|
||||
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||
HttpResponse response = httpclient.execute(httpGet);
|
||||
|
||||
//then
|
||||
assertEquals(response.getStatusLine().getStatusCode(), 200);
|
||||
assertEquals(response.getCode(), 200);
|
||||
proxyMock.verify(getRequestedFor(urlEqualTo("/private")));
|
||||
serviceMock.verify(getRequestedFor(urlEqualTo("/private")));
|
||||
}
|
||||
@@ -125,14 +125,12 @@ public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
|
||||
|
||||
// Client credentials
|
||||
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
credentialsProvider.setCredentials(new AuthScope(proxy),
|
||||
new UsernamePasswordCredentials("username_admin", "secret_password"));
|
||||
|
||||
CredentialsProvider credentialsProvider = CredentialsProviderBuilder.create()
|
||||
.add(new AuthScope(proxy), "username_admin", "secret_password".toCharArray())
|
||||
.build();
|
||||
|
||||
// Create AuthCache instance
|
||||
AuthCache authCache = new BasicAuthCache();
|
||||
|
||||
// Generate BASIC scheme object and add it to the local auth cache
|
||||
BasicScheme basicAuth = new BasicScheme();
|
||||
authCache.put(proxy, basicAuth);
|
||||
@@ -149,10 +147,11 @@ public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||
|
||||
//when
|
||||
final HttpGet httpGet = new HttpGet("http://localhost:8089/private");
|
||||
httpGet.setHeader("Authorization", StandardAuthScheme.BASIC);
|
||||
HttpResponse response = httpclient.execute(httpGet, context);
|
||||
|
||||
//then
|
||||
assertEquals(response.getStatusLine().getStatusCode(), 200);
|
||||
assertEquals(response.getCode(), 200);
|
||||
proxyMock.verify(getRequestedFor(urlEqualTo("/private")).withHeader("Authorization", containing("Basic")));
|
||||
serviceMock.verify(getRequestedFor(urlEqualTo("/private")));
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -241,8 +241,6 @@
|
||||
<httpcore.version>4.4.16</httpcore.version>
|
||||
<httpclient.version>4.5.14</httpclient.version>
|
||||
<mockserver.version>5.11.2</mockserver.version>
|
||||
<!-- maven plugins -->
|
||||
<maven-war-plugin.version>3.3.2</maven-war-plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
package com.baeldung.httpclient.advancedconfig;
|
||||
|
||||
|
||||
import com.github.tomakehurst.wiremock.junit.WireMockRule;
|
||||
import org.apache.http.HttpHeaders;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.auth.AuthScope;
|
||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.http.client.AuthCache;
|
||||
import org.apache.http.client.CredentialsProvider;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.auth.BasicScheme;
|
||||
import org.apache.http.impl.client.BasicAuthCache;
|
||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.containing;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.get;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.post;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||
|
||||
@Rule
|
||||
public WireMockRule serviceMock = new WireMockRule(8089);
|
||||
|
||||
@Rule
|
||||
public WireMockRule proxyMock = new WireMockRule(8090);
|
||||
|
||||
@Test
|
||||
public void givenClientWithCustomUserAgentHeader_whenExecuteRequest_shouldReturn200() throws IOException {
|
||||
//given
|
||||
String userAgent = "BaeldungAgent/1.0";
|
||||
serviceMock.stubFor(get(urlEqualTo("/detail"))
|
||||
.withHeader("User-Agent", equalTo(userAgent))
|
||||
.willReturn(aResponse()
|
||||
.withStatus(200)));
|
||||
|
||||
HttpClient httpClient = HttpClients.createDefault();
|
||||
HttpGet httpGet = new HttpGet("http://localhost:8089/detail");
|
||||
httpGet.setHeader(HttpHeaders.USER_AGENT, userAgent);
|
||||
|
||||
//when
|
||||
HttpResponse response = httpClient.execute(httpGet);
|
||||
|
||||
//then
|
||||
assertEquals(response.getStatusLine().getStatusCode(), 200);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenClientThatSendDataInBody_whenSendXmlInBody_shouldReturn200() throws IOException {
|
||||
//given
|
||||
String xmlBody = "<xml><id>1</id></xml>";
|
||||
serviceMock.stubFor(post(urlEqualTo("/person"))
|
||||
.withHeader("Content-Type", equalTo("application/xml"))
|
||||
.withRequestBody(equalTo(xmlBody))
|
||||
.willReturn(aResponse()
|
||||
.withStatus(200)));
|
||||
|
||||
HttpClient httpClient = HttpClients.createDefault();
|
||||
HttpPost httpPost = new HttpPost("http://localhost:8089/person");
|
||||
httpPost.setHeader("Content-Type", "application/xml");
|
||||
StringEntity xmlEntity = new StringEntity(xmlBody);
|
||||
httpPost.setEntity(xmlEntity);
|
||||
|
||||
//when
|
||||
HttpResponse response = httpClient.execute(httpPost);
|
||||
|
||||
//then
|
||||
assertEquals(response.getStatusLine().getStatusCode(), 200);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenServerThatIsBehindProxy_whenClientIsConfiguredToSendRequestViaProxy_shouldReturn200() throws IOException {
|
||||
//given
|
||||
proxyMock.stubFor(get(urlMatching(".*"))
|
||||
.willReturn(aResponse().proxiedFrom("http://localhost:8089/")));
|
||||
|
||||
serviceMock.stubFor(get(urlEqualTo("/private"))
|
||||
.willReturn(aResponse().withStatus(200)));
|
||||
|
||||
|
||||
HttpHost proxy = new HttpHost("localhost", 8090);
|
||||
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
|
||||
HttpClient httpclient = HttpClients.custom()
|
||||
.setRoutePlanner(routePlanner)
|
||||
.build();
|
||||
|
||||
//when
|
||||
final HttpGet httpGet = new HttpGet("http://localhost:8089/private");
|
||||
HttpResponse response = httpclient.execute(httpGet);
|
||||
|
||||
//then
|
||||
assertEquals(response.getStatusLine().getStatusCode(), 200);
|
||||
proxyMock.verify(getRequestedFor(urlEqualTo("/private")));
|
||||
serviceMock.verify(getRequestedFor(urlEqualTo("/private")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenServerThatIsBehindAuthorizationProxy_whenClientSendRequest_shouldAuthorizeProperly() throws IOException {
|
||||
//given
|
||||
proxyMock.stubFor(get(urlMatching("/private"))
|
||||
.willReturn(aResponse().proxiedFrom("http://localhost:8089/")));
|
||||
serviceMock.stubFor(get(urlEqualTo("/private"))
|
||||
.willReturn(aResponse().withStatus(200)));
|
||||
|
||||
|
||||
HttpHost proxy = new HttpHost("localhost", 8090);
|
||||
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
|
||||
|
||||
// Client credentials
|
||||
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||
credentialsProvider.setCredentials(new AuthScope(proxy),
|
||||
new UsernamePasswordCredentials("username_admin", "secret_password"));
|
||||
|
||||
|
||||
// Create AuthCache instance
|
||||
AuthCache authCache = new BasicAuthCache();
|
||||
|
||||
// Generate BASIC scheme object and add it to the local auth cache
|
||||
BasicScheme basicAuth = new BasicScheme();
|
||||
authCache.put(proxy, basicAuth);
|
||||
HttpClientContext context = HttpClientContext.create();
|
||||
context.setCredentialsProvider(credentialsProvider);
|
||||
context.setAuthCache(authCache);
|
||||
|
||||
|
||||
HttpClient httpclient = HttpClients.custom()
|
||||
.setRoutePlanner(routePlanner)
|
||||
.setDefaultCredentialsProvider(credentialsProvider)
|
||||
.build();
|
||||
|
||||
|
||||
//when
|
||||
final HttpGet httpGet = new HttpGet("http://localhost:8089/private");
|
||||
HttpResponse response = httpclient.execute(httpGet, context);
|
||||
|
||||
//then
|
||||
assertEquals(response.getStatusLine().getStatusCode(), 200);
|
||||
proxyMock.verify(getRequestedFor(urlEqualTo("/private")).withHeader("Authorization", containing("Basic")));
|
||||
serviceMock.verify(getRequestedFor(urlEqualTo("/private")));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.baeldung.kafka.consumer;
|
||||
|
||||
import org.apache.kafka.clients.consumer.*;
|
||||
import org.apache.kafka.common.serialization.LongDeserializer;
|
||||
import org.apache.kafka.common.serialization.StringDeserializer;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Properties;
|
||||
|
||||
public class SimpleConsumerWithBootStrapServers {
|
||||
|
||||
public static void main(String[] args) {
|
||||
try(final Consumer<Long, String> consumer = createConsumer()) {
|
||||
ConsumerRecords<Long, String> records = consumer.poll(Duration.ofMinutes(1));
|
||||
for(ConsumerRecord<Long, String> record : records) {
|
||||
System.out.println(record.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Consumer<Long, String> createConsumer() {
|
||||
final Properties props = new Properties();
|
||||
props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,
|
||||
"localhost:9092,another-host.com:29092");
|
||||
props.put(ConsumerConfig.GROUP_ID_CONFIG,
|
||||
"MySampleConsumer");
|
||||
props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
|
||||
LongDeserializer.class.getName());
|
||||
props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
|
||||
StringDeserializer.class.getName());
|
||||
// Create the consumer using props.
|
||||
final Consumer<Long, String> consumer = new KafkaConsumer<Long, String>(props);
|
||||
// Subscribe to the topic.
|
||||
consumer.subscribe(Arrays.asList("samples"));
|
||||
return consumer;
|
||||
}
|
||||
|
||||
}
|
||||
2
apache-libraries-2/README.md
Normal file
2
apache-libraries-2/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
## Relevant Articles
|
||||
- [Understanding XSLT Processing in Java](https://www.baeldung.com/java-extensible-stylesheet-language-transformations)
|
||||
@@ -3,28 +3,26 @@
|
||||
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>memory-leaks</artifactId>
|
||||
<artifactId>apache-libraries-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>memory-leaks</name>
|
||||
<name>apache-libraries-2</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../</relativePath>
|
||||
</parent>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources/</directory>
|
||||
<excludes>
|
||||
<exclude>**/*.java</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/test/resources/</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
<version>${javax.validation.validation-api.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<javax.validation.validation-api.version>2.0.1.Final</javax.validation.validation-api.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.baeldung.xslt;
|
||||
|
||||
import javax.xml.transform.*;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.File;
|
||||
|
||||
public class XSLTProcessor {
|
||||
public static void transformXMLUsingXSLT(String inputXMLPath, String xsltPath, String outputHTMLPath) throws TransformerException {
|
||||
Source xmlSource = new StreamSource(new File(inputXMLPath));
|
||||
Source xsltSource = new StreamSource(new File(xsltPath));
|
||||
Result output = new StreamResult(new File(outputHTMLPath));
|
||||
|
||||
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||
Transformer transformer = transformerFactory.newTransformer(xsltSource);
|
||||
transformer.transform(xmlSource, output);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.baeldung.xsltProcessing;
|
||||
|
||||
import javax.xml.transform.*;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.File;
|
||||
|
||||
public class XSLTProcessorWithParametersAndOption {
|
||||
public static void transformXMLWithParametersAndOption(
|
||||
String inputXMLPath,
|
||||
String xsltPath,
|
||||
String outputHTMLPath,
|
||||
String companyName,
|
||||
boolean enableIndentation
|
||||
) throws TransformerException {
|
||||
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||
Source xsltSource = new StreamSource(new File(xsltPath));
|
||||
Transformer transformer = transformerFactory.newTransformer(xsltSource);
|
||||
|
||||
transformer.setParameter("companyName", companyName);
|
||||
|
||||
if (enableIndentation) {
|
||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
}
|
||||
|
||||
Source xmlSource = new StreamSource(new File(inputXMLPath));
|
||||
Result outputResult = new StreamResult(new File(outputHTMLPath));
|
||||
|
||||
transformer.transform(xmlSource, outputResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.baeldung.xsltProcessing;
|
||||
|
||||
import javax.xml.transform.*;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.File;
|
||||
|
||||
public class XSLTProcessorWithTemplate {
|
||||
public static void transformXMLUsingTemplate(String inputXMLPath, String xsltPath, String outputHTMLPath) throws TransformerException {
|
||||
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||
Source xsltSource = new StreamSource(new File(xsltPath));
|
||||
Templates templates = transformerFactory.newTemplates(xsltSource);
|
||||
|
||||
Transformer transformer = templates.newTransformer();
|
||||
|
||||
Source xmlSource = new StreamSource(new File(inputXMLPath));
|
||||
Result outputResult = new StreamResult(new File(outputHTMLPath));
|
||||
|
||||
transformer.transform(xmlSource, outputResult);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"type":"record",
|
||||
"name":"AvroHttpRequest",
|
||||
"namespace":"com.baeldung.avro.model",
|
||||
"fields":[
|
||||
{
|
||||
"name":"requestTime",
|
||||
"type":"long"
|
||||
},
|
||||
{
|
||||
"name":"clientIdentifier",
|
||||
"type":{
|
||||
"type":"record",
|
||||
"name":"ClientIdentifier",
|
||||
"fields":[
|
||||
{
|
||||
"name":"hostName",
|
||||
"type":"string"
|
||||
},
|
||||
{
|
||||
"name":"ipAddress",
|
||||
"type":"string"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name":"employeeNames",
|
||||
"type":{
|
||||
"type":"array",
|
||||
"items":"string"
|
||||
},
|
||||
"default":null
|
||||
},
|
||||
{
|
||||
"name":"active",
|
||||
"type":{
|
||||
"type":"enum",
|
||||
"name":"Active",
|
||||
"symbols":[
|
||||
"YES",
|
||||
"NO"
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
18
apache-libraries-2/src/main/resources/log4j2.xml
Normal file
18
apache-libraries-2/src/main/resources/log4j2.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<Configuration status="WARN">
|
||||
<Appenders>
|
||||
<Console name="Console" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
|
||||
</Console>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Logger name="org.apache.meecrowave" level="warn">
|
||||
<AppenderRef ref="Console"/>
|
||||
</Logger>
|
||||
|
||||
<Root level="info">
|
||||
<AppenderRef ref="Console"/>
|
||||
</Root>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.baeldung.xslt;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.xml.transform.TransformerException;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
public class XSLTProcessorUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenValidInputAndStylesheet_whenTransformingXML_thenOutputHTMLCreated() throws TransformerException, IOException {
|
||||
// Given
|
||||
String inputXMLPath = "src/test/resources/input.xml";
|
||||
String xsltPath = "src/test/resources/stylesheet.xslt";
|
||||
String outputHTMLPath = "src/test/resources/output.html";
|
||||
|
||||
|
||||
XSLTProcessor.transformXMLUsingXSLT(inputXMLPath, xsltPath, outputHTMLPath);
|
||||
|
||||
|
||||
Path outputFile = Paths.get(outputHTMLPath);
|
||||
assertTrue(Files.exists(outputFile));
|
||||
}
|
||||
}
|
||||
11
apache-libraries-2/src/test/resources/input.xml
Normal file
11
apache-libraries-2/src/test/resources/input.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<root>
|
||||
<person gender="male">
|
||||
<name>John Doe</name>
|
||||
<age>30</age>
|
||||
</person>
|
||||
<person gender="female">
|
||||
<name>Jane Smith</name>
|
||||
<age>25</age>
|
||||
</person>
|
||||
</root>
|
||||
3
apache-libraries-2/src/test/resources/output.html
Normal file
3
apache-libraries-2/src/test/resources/output.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<p>Male person: John Doe, Age: 30</p>
|
||||
<p>Female person: Jane Smith, Age: 25</p>
|
||||
22
apache-libraries-2/src/test/resources/stylesheet.xslt
Normal file
22
apache-libraries-2/src/test/resources/stylesheet.xslt
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
|
||||
<xsl:template match="person[@gender='male']">
|
||||
<xsl:element name="p">
|
||||
<xsl:text>Male person: </xsl:text>
|
||||
<xsl:value-of select="name"/>
|
||||
<xsl:text>, Age: </xsl:text>
|
||||
<xsl:value-of select="age"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="person[@gender='female']">
|
||||
<xsl:element name="p">
|
||||
<xsl:text>Female person: </xsl:text>
|
||||
<xsl:value-of select="name"/>
|
||||
<xsl:text>, Age: </xsl:text>
|
||||
<xsl:value-of select="age"/>
|
||||
</xsl:element>
|
||||
</xsl:template>
|
||||
|
||||
</xsl:stylesheet>
|
||||
@@ -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)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.baeldung.poi.excel.locksheet;
|
||||
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
|
||||
public class LockSheet {
|
||||
|
||||
public void lockFirstRow(Sheet sheet) {
|
||||
sheet.createFreezePane(0, 1);
|
||||
}
|
||||
|
||||
public void lockTwoRows(Sheet sheet) {
|
||||
sheet.createFreezePane(0, 2);
|
||||
}
|
||||
|
||||
public void lockFirstColumn(Sheet sheet) {
|
||||
sheet.createFreezePane(1, 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.baeldung.poi.excel.locksheet;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.junit.jupiter.api.*;
|
||||
|
||||
class LockSheetUnitTest {
|
||||
|
||||
private LockSheet lockSheet;
|
||||
private Workbook workbook;
|
||||
private Sheet sheet;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
workbook = new XSSFWorkbook();
|
||||
sheet = workbook.createSheet();
|
||||
Row row = sheet.createRow(0);
|
||||
row.createCell(0).setCellValue("row 1 col 1");
|
||||
row.createCell(1).setCellValue("row 1 col 2");
|
||||
row = sheet.createRow(1);
|
||||
row.createCell(0).setCellValue("row 2 col 1");
|
||||
row.createCell(1).setCellValue("row 2 col 2");
|
||||
lockSheet = new LockSheet();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanup() throws IOException {
|
||||
workbook.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenLockFirstRow_thenFirstRowIsLocked() {
|
||||
lockSheet.lockFirstRow(sheet);
|
||||
assertEquals(sheet.getPaneInformation().getHorizontalSplitPosition(), 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenLockTwoRows_thenTwoRowsAreLocked() {
|
||||
lockSheet.lockTwoRows(sheet);
|
||||
assertEquals(sheet.getPaneInformation().getHorizontalSplitPosition(), 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenLockFirstColumn_thenFirstColumnIsLocked() {
|
||||
lockSheet.lockFirstColumn(sheet);
|
||||
assertEquals(sheet.getPaneInformation().getVerticalSplitPosition(), 1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -63,7 +63,6 @@
|
||||
<org.apache.httpcomponents.version>4.5.2</org.apache.httpcomponents.version>
|
||||
<velocity-version>1.7</velocity-version>
|
||||
<velocity-tools-version>2.0</velocity-tools-version>
|
||||
<maven-war-plugin.version>3.3.2</maven-war-plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -49,7 +49,6 @@
|
||||
|
||||
<properties>
|
||||
<asm.version>5.2</asm.version>
|
||||
<maven-jar-plugin.version>2.4</maven-jar-plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
43
aws-modules/aws-s3-update-object/pom.xml
Normal file
43
aws-modules/aws-s3-update-object/pom.xml
Normal file
@@ -0,0 +1,43 @@
|
||||
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<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>
|
||||
<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>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk</artifactId>
|
||||
<version>${aws-java-sdk-version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<properties>
|
||||
<aws-java-sdk-version>1.12.523</aws-java-sdk-version>
|
||||
</properties>
|
||||
</project>
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.baeldung.awss3updateobject;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class AwsS3UpdateObjectApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AwsS3UpdateObjectApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.baeldung.awss3updateobject.controller;
|
||||
|
||||
import com.baeldung.awss3updateobject.service.FileService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("api/v1/file")
|
||||
public class FileController {
|
||||
|
||||
@Autowired
|
||||
FileService fileService;
|
||||
|
||||
@PostMapping("/upload")
|
||||
public String uploadFile(@RequestParam("file") MultipartFile multipartFile) throws Exception {
|
||||
return this.fileService.uploadFile(multipartFile);
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
public String updateFile(@RequestParam("file") MultipartFile multipartFile, @RequestParam("filePath") String exitingFilePath) throws Exception {
|
||||
return this.fileService.updateFile(multipartFile, exitingFilePath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.baeldung.awss3updateobject.service;
|
||||
|
||||
import com.amazonaws.auth.AWSCredentials;
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.regions.Regions;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
||||
import com.amazonaws.services.s3.model.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class FileService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(FileService.class);
|
||||
|
||||
public AmazonS3 amazonS3;
|
||||
|
||||
@Value("${aws.s3bucket}")
|
||||
public String awsS3Bucket;
|
||||
|
||||
@PostConstruct
|
||||
private void init(){
|
||||
AWSCredentials credentials = new BasicAWSCredentials(
|
||||
"AWS AccessKey",
|
||||
"AWS secretKey"
|
||||
);
|
||||
this.amazonS3 = AmazonS3ClientBuilder.standard()
|
||||
.withRegion(Regions.fromName("us-east-1"))
|
||||
.withCredentials(new AWSStaticCredentialsProvider(credentials))
|
||||
.build();
|
||||
}
|
||||
|
||||
public String uploadFile(MultipartFile multipartFile) throws Exception {
|
||||
String key = "/documents/" + multipartFile.getOriginalFilename();
|
||||
return this.uploadDocument(this.awsS3Bucket, key, multipartFile);
|
||||
}
|
||||
|
||||
public String updateFile(MultipartFile multipartFile, String key) throws Exception {
|
||||
return this.uploadDocument(this.awsS3Bucket, key, multipartFile);
|
||||
}
|
||||
|
||||
private String uploadDocument(String s3bucket, String key, MultipartFile multipartFile) throws Exception {
|
||||
try {
|
||||
ObjectMetadata metadata = new ObjectMetadata();
|
||||
metadata.setContentType(multipartFile.getContentType());
|
||||
Map<String, String> attributes = new HashMap<>();
|
||||
attributes.put("document-content-size", String.valueOf(multipartFile.getSize()));
|
||||
metadata.setUserMetadata(attributes);
|
||||
InputStream documentStream = multipartFile.getInputStream();
|
||||
PutObjectResult putObjectResult = this.amazonS3.putObject(new PutObjectRequest(s3bucket, key, documentStream, metadata));
|
||||
|
||||
S3Object s3Object = this.amazonS3.getObject(s3bucket, key);
|
||||
logger.info("Last Modified: " + s3Object.getObjectMetadata().getLastModified());
|
||||
return key;
|
||||
} catch (AmazonS3Exception ex) {
|
||||
if (ex.getErrorCode().equalsIgnoreCase("NoSuchBucket")) {
|
||||
String msg = String.format("No bucket found with name %s", s3bucket);
|
||||
throw new Exception(msg);
|
||||
} else if (ex.getErrorCode().equalsIgnoreCase("AccessDenied")) {
|
||||
String msg = String.format("Access denied to S3 bucket %s", s3bucket);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
throw ex;
|
||||
} catch (IOException ex) {
|
||||
String msg = String.format("Error saving file %s to AWS S3 bucket %s", key, s3bucket);
|
||||
throw new Exception(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
aws.s3bucket=baeldung-documents;
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.baeldung.awss3updateobject.controller;
|
||||
|
||||
import com.baeldung.awss3updateobject.service.FileService;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
|
||||
public class FileControllerUnitTest {
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Mock
|
||||
private FileService fileService;
|
||||
|
||||
@InjectMocks
|
||||
private FileController fileController;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
this.mockMvc = MockMvcBuilders.standaloneSetup(fileController).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenValidMultipartFile_whenUploadedViaEndpoint_thenCorrectPathIsReturned() throws Exception {
|
||||
MockMultipartFile multipartFile = new MockMultipartFile("file", "test.txt", "text/plain", "sample file content".getBytes());
|
||||
String expectedResult = "File Uploaded Successfully";
|
||||
|
||||
when(fileService.uploadFile(multipartFile)).thenReturn(expectedResult);
|
||||
|
||||
mockMvc.perform(multipart("/api/v1/file/upload").file(multipartFile))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(expectedResult));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenValidMultipartFileAndExistingPath_whenUpdatedViaEndpoint_thenSamePathIsReturned() throws Exception {
|
||||
MockMultipartFile multipartFile = new MockMultipartFile("file", "test.txt", "text/plain", "updated file content".getBytes());
|
||||
String filePath = "some/path/to/file";
|
||||
String expectedResult = "File Updated Successfully";
|
||||
|
||||
when(fileService.updateFile(multipartFile, filePath)).thenReturn(expectedResult);
|
||||
|
||||
mockMvc.perform(multipart("/api/v1/file/update")
|
||||
.file(multipartFile)
|
||||
.param("filePath", filePath))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(expectedResult));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.baeldung.awss3updateobject.service;
|
||||
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.model.AmazonS3Exception;
|
||||
import com.amazonaws.services.s3.model.PutObjectRequest;
|
||||
import com.amazonaws.services.s3.model.S3Object;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
public class FileServiceUnitTest {
|
||||
|
||||
@Mock
|
||||
private AmazonS3 amazonS3;
|
||||
|
||||
@Mock
|
||||
private MultipartFile multipartFile;
|
||||
|
||||
@InjectMocks
|
||||
private FileService fileService;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
fileService = new FileService();
|
||||
fileService.awsS3Bucket = "test-bucket";
|
||||
fileService.amazonS3 = amazonS3;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenValidFile_whenUploaded_thenKeyMatchesDocumentPath() throws Exception {
|
||||
when(multipartFile.getName()).thenReturn("testFile");
|
||||
when(multipartFile.getOriginalFilename()).thenReturn("testFile");
|
||||
when(multipartFile.getContentType()).thenReturn("application/pdf");
|
||||
when(multipartFile.getSize()).thenReturn(1024L);
|
||||
when(multipartFile.getInputStream()).thenReturn(mock(InputStream.class));
|
||||
|
||||
S3Object s3Object = new S3Object();
|
||||
when(amazonS3.putObject(any())).thenReturn(null);
|
||||
when(amazonS3.getObject(anyString(), anyString())).thenReturn(s3Object);
|
||||
|
||||
String key = fileService.uploadFile(multipartFile);
|
||||
|
||||
assertEquals("/documents/testFile", key);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenValidFile_whenUploadFailsDueToNoBucket_thenExceptionIsThrown() throws Exception {
|
||||
when(multipartFile.getName()).thenReturn("testFile");
|
||||
when(multipartFile.getOriginalFilename()).thenReturn("testFile");
|
||||
when(multipartFile.getContentType()).thenReturn("application/pdf");
|
||||
when(multipartFile.getSize()).thenReturn(1024L);
|
||||
when(multipartFile.getInputStream()).thenReturn(mock(InputStream.class));
|
||||
|
||||
AmazonS3Exception exception = new AmazonS3Exception("Test exception");
|
||||
exception.setErrorCode("NoSuchBucket");
|
||||
when(amazonS3.putObject(any(PutObjectRequest.class))).thenThrow(exception);
|
||||
|
||||
assertThrows(Exception.class, () -> fileService.uploadFile(multipartFile));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenExistingFile_whenUpdated_thenSameKeyIsReturned() throws Exception {
|
||||
when(multipartFile.getName()).thenReturn("testFile");
|
||||
when(multipartFile.getContentType()).thenReturn("application/pdf");
|
||||
when(multipartFile.getSize()).thenReturn(1024L);
|
||||
when(multipartFile.getInputStream()).thenReturn(mock(InputStream.class));
|
||||
|
||||
S3Object s3Object = new S3Object();
|
||||
when(amazonS3.putObject(any(PutObjectRequest.class))).thenReturn(null);
|
||||
when(amazonS3.getObject(anyString(), anyString())).thenReturn(s3Object);
|
||||
|
||||
String key = "/documents/existingFile";
|
||||
String resultKey = fileService.updateFile(multipartFile, key);
|
||||
|
||||
assertEquals(key, resultKey);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenFileWithIOException_whenUpdated_thenExceptionIsThrown() throws Exception {
|
||||
when(multipartFile.getName()).thenReturn("testFile");
|
||||
when(multipartFile.getContentType()).thenReturn("application/pdf");
|
||||
when(multipartFile.getSize()).thenReturn(1024L);
|
||||
when(multipartFile.getInputStream()).thenThrow(new IOException("Test IO Exception"));
|
||||
|
||||
assertThrows(Exception.class, () -> fileService.updateFile(multipartFile, "/documents/existingFile"));
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
## Relevant Articles
|
||||
- [Listing All AWS S3 Objects in a Bucket Using Java](https://www.baeldung.com/java-aws-s3-list-bucket-objects)
|
||||
@@ -1,50 +0,0 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.baeldung.s3</groupId>
|
||||
<artifactId>aws-s3-v2</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<name>aws-s3-v2</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>aws-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<aws.java.sdk.version>2.20.52</aws.java.sdk.version>
|
||||
<maven.compiler.plugin.version>3.6.1</maven.compiler.plugin.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>software.amazon.awssdk</groupId>
|
||||
<artifactId>s3</artifactId>
|
||||
<version>${aws.java.sdk.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>${maven-shade-plugin.version}</version>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.baeldung.s3.listobjects;
|
||||
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
|
||||
public class Main {
|
||||
|
||||
private static String AWS_BUCKET = "baeldung-tutorial-s3";
|
||||
public static Region AWS_REGION = Region.EU_CENTRAL_1;
|
||||
|
||||
public static void main(String[] args) {
|
||||
S3Service s3Service = new S3Service(AWS_REGION);
|
||||
|
||||
s3Service.putObject(AWS_BUCKET, FileGenerator.generateFiles(1000, 1));
|
||||
s3Service.listBuckets();
|
||||
s3Service.listObjectsInBucket(AWS_BUCKET);
|
||||
s3Service.listAllObjectsInBucket(AWS_BUCKET);
|
||||
s3Service.listAllObjectsInBucketPaginated(AWS_BUCKET, 500);
|
||||
s3Service.listAllObjectsInBucketPaginatedWithPrefix(AWS_BUCKET, 500, "backup/");
|
||||
|
||||
s3Service.cleanup();
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
package com.baeldung.s3.listobjects;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
|
||||
import software.amazon.awssdk.core.sync.RequestBody;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
import software.amazon.awssdk.services.s3.S3Client;
|
||||
import software.amazon.awssdk.services.s3.model.*;
|
||||
import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable;
|
||||
|
||||
class S3Service {
|
||||
|
||||
private S3Client s3Client;
|
||||
|
||||
public S3Service(Region awsRegion) {
|
||||
init(awsRegion);
|
||||
}
|
||||
|
||||
public S3Service(S3Client s3Client) {
|
||||
this.s3Client = s3Client;
|
||||
}
|
||||
|
||||
public void init(Region awsRegion) {
|
||||
this.s3Client = S3Client.builder()
|
||||
.region(awsRegion)
|
||||
.credentialsProvider(ProfileCredentialsProvider.create("default"))
|
||||
.build();
|
||||
}
|
||||
|
||||
public void listObjectsInBucket(String bucketName) {
|
||||
ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder()
|
||||
.bucket(bucketName)
|
||||
.build();
|
||||
ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request);
|
||||
|
||||
List<S3Object> contents = listObjectsV2Response.contents();
|
||||
|
||||
System.out.println("Number of objects in the bucket: " + contents.stream().count());
|
||||
contents.stream().forEach(System.out::println);
|
||||
}
|
||||
|
||||
public void listAllObjectsInBucket(String bucketName) {
|
||||
String nextContinuationToken = null;
|
||||
long totalObjects = 0;
|
||||
|
||||
do {
|
||||
ListObjectsV2Request.Builder requestBuilder = ListObjectsV2Request.builder()
|
||||
.bucket(bucketName)
|
||||
.continuationToken(nextContinuationToken);
|
||||
|
||||
ListObjectsV2Response response = s3Client.listObjectsV2(requestBuilder.build());
|
||||
nextContinuationToken = response.nextContinuationToken();
|
||||
|
||||
totalObjects += response.contents().stream()
|
||||
.peek(System.out::println)
|
||||
.reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum);
|
||||
} while (nextContinuationToken != null);
|
||||
System.out.println("Number of objects in the bucket: " + totalObjects);
|
||||
}
|
||||
|
||||
public void listAllObjectsInBucketPaginated(String bucketName, int pageSize) {
|
||||
ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder()
|
||||
.bucket(bucketName)
|
||||
.maxKeys(pageSize) // Set the maxKeys parameter to control the page size
|
||||
.build();
|
||||
|
||||
ListObjectsV2Iterable listObjectsV2Iterable = s3Client.listObjectsV2Paginator(listObjectsV2Request);
|
||||
long totalObjects = 0;
|
||||
|
||||
for (ListObjectsV2Response page : listObjectsV2Iterable) {
|
||||
long retrievedPageSize = page.contents().stream()
|
||||
.peek(System.out::println)
|
||||
.reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum);
|
||||
totalObjects += retrievedPageSize;
|
||||
System.out.println("Page size: " + retrievedPageSize);
|
||||
}
|
||||
System.out.println("Total objects in the bucket: " + totalObjects);
|
||||
}
|
||||
|
||||
public void listAllObjectsInBucketPaginatedWithPrefix(String bucketName, int pageSize, String prefix) {
|
||||
ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder()
|
||||
.bucket(bucketName)
|
||||
.maxKeys(pageSize) // Set the maxKeys parameter to control the page size
|
||||
.prefix(prefix)
|
||||
.build();
|
||||
|
||||
ListObjectsV2Iterable listObjectsV2Iterable = s3Client.listObjectsV2Paginator(listObjectsV2Request);
|
||||
long totalObjects = 0;
|
||||
|
||||
for (ListObjectsV2Response page : listObjectsV2Iterable) {
|
||||
long retrievedPageSize = page.contents().stream()
|
||||
.peek(System.out::println)
|
||||
.reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum);
|
||||
totalObjects += retrievedPageSize;
|
||||
System.out.println("Page size: " + retrievedPageSize);
|
||||
}
|
||||
System.out.println("Total objects in the bucket: " + totalObjects);
|
||||
}
|
||||
|
||||
public void listBuckets() {
|
||||
// List all buckets
|
||||
ListBucketsResponse listBucketsResponse = s3Client.listBuckets();
|
||||
|
||||
// Display the bucket names
|
||||
List<Bucket> buckets = listBucketsResponse.buckets();
|
||||
System.out.println("Buckets:");
|
||||
for (Bucket bucket : buckets) {
|
||||
System.out.println(bucket.name());
|
||||
}
|
||||
}
|
||||
|
||||
public void putObject(String bucketName, List<File> files) {
|
||||
try {
|
||||
files.stream().forEach(file -> {
|
||||
s3Client.putObject(PutObjectRequest.builder().bucket(bucketName).key(file.getName()).build(),
|
||||
RequestBody.fromByteBuffer(file.getContent()));
|
||||
System.out.println("Uploaded file: " + file.getName());
|
||||
});
|
||||
} catch (S3Exception e) {
|
||||
System.err.println("Upload failed");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
this.s3Client.close();
|
||||
}
|
||||
}
|
||||
@@ -8,3 +8,6 @@ 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)
|
||||
- [Update an Existing Amazon S3 Object Using Java](https://www.baeldung.com/java-update-amazon-s3-object)
|
||||
- [How To Rename Files and Folders in Amazon S3](https://www.baeldung.com/java-amazon-s3-rename-files-folders)
|
||||
|
||||
@@ -16,10 +16,11 @@
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk</artifactId>
|
||||
<version>${aws-java-sdk.version}</version>
|
||||
<groupId>software.amazon.awssdk</groupId>
|
||||
<artifactId>s3</artifactId>
|
||||
<version>${aws.java.sdk.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
@@ -60,6 +61,7 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<aws.java.sdk.version>2.20.52</aws.java.sdk.version>
|
||||
<commons-codec-version>1.10.L001</commons-codec-version>
|
||||
<jets3t-version>0.9.4.0006L</jets3t-version>
|
||||
</properties>
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
package com.baeldung.s3;
|
||||
|
||||
import org.apache.http.HttpStatus;
|
||||
|
||||
import com.amazonaws.AmazonServiceException;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
|
||||
public class AWSS3ObjectUtils {
|
||||
|
||||
private AmazonS3 s3Client;
|
||||
|
||||
public AWSS3ObjectUtils(AmazonS3 s3client) {
|
||||
this.s3Client = s3client;
|
||||
}
|
||||
|
||||
public boolean doesObjectExistByDefaultMethod(String bucket, String key) {
|
||||
return s3Client.doesObjectExist(bucket, key);
|
||||
}
|
||||
|
||||
public boolean doesObjectExistByListObjects(String bucket, String key) {
|
||||
return s3Client.listObjects(bucket)
|
||||
.getObjectSummaries()
|
||||
.stream()
|
||||
.filter(s3ObjectSummary -> s3ObjectSummary.getKey()
|
||||
.equals(key))
|
||||
.findFirst()
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
public boolean doesObjectExistByMetaData(String bucket, String key) {
|
||||
try {
|
||||
s3Client.getObjectMetadata(bucket, key);
|
||||
return true;
|
||||
} catch (AmazonServiceException e) {
|
||||
if (e.getStatusCode() == HttpStatus.SC_NOT_FOUND) {
|
||||
return false;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
package com.baeldung.s3;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.AmazonS3Client;
|
||||
import com.amazonaws.services.s3.model.Bucket;
|
||||
import com.amazonaws.services.s3.model.CopyObjectResult;
|
||||
import com.amazonaws.services.s3.model.DeleteObjectsRequest;
|
||||
import com.amazonaws.services.s3.model.DeleteObjectsResult;
|
||||
import com.amazonaws.services.s3.model.ObjectListing;
|
||||
import com.amazonaws.services.s3.model.PutObjectResult;
|
||||
import com.amazonaws.services.s3.model.S3Object;
|
||||
|
||||
public class AWSS3Service {
|
||||
private final AmazonS3 s3client;
|
||||
|
||||
public AWSS3Service() {
|
||||
this(new AmazonS3Client() {
|
||||
});
|
||||
}
|
||||
|
||||
public AWSS3Service(AmazonS3 s3client) {
|
||||
this.s3client = s3client;
|
||||
}
|
||||
|
||||
//is bucket exist?
|
||||
public boolean doesBucketExist(String bucketName) {
|
||||
return s3client.doesBucketExist(bucketName);
|
||||
}
|
||||
|
||||
//create a bucket
|
||||
public Bucket createBucket(String bucketName) {
|
||||
return s3client.createBucket(bucketName);
|
||||
}
|
||||
|
||||
//list all buckets
|
||||
public List<Bucket> listBuckets() {
|
||||
return s3client.listBuckets();
|
||||
}
|
||||
|
||||
//delete a bucket
|
||||
public void deleteBucket(String bucketName) {
|
||||
s3client.deleteBucket(bucketName);
|
||||
}
|
||||
|
||||
//uploading object
|
||||
public PutObjectResult putObject(String bucketName, String key, File file) {
|
||||
return s3client.putObject(bucketName, key, file);
|
||||
}
|
||||
//uploading object and getting url
|
||||
public URL getObjectURL(String bucketName, String key, File file) {
|
||||
s3client.putObject(bucketName, key, file);
|
||||
return s3client.getUrl(bucketName, key);
|
||||
}
|
||||
|
||||
//listing objects
|
||||
public ObjectListing listObjects(String bucketName) {
|
||||
return s3client.listObjects(bucketName);
|
||||
}
|
||||
|
||||
//get an object
|
||||
public S3Object getObject(String bucketName, String objectKey) {
|
||||
return s3client.getObject(bucketName, objectKey);
|
||||
}
|
||||
|
||||
//copying an object
|
||||
public CopyObjectResult copyObject(
|
||||
String sourceBucketName,
|
||||
String sourceKey,
|
||||
String destinationBucketName,
|
||||
String destinationKey
|
||||
) {
|
||||
return s3client.copyObject(
|
||||
sourceBucketName,
|
||||
sourceKey,
|
||||
destinationBucketName,
|
||||
destinationKey
|
||||
);
|
||||
}
|
||||
|
||||
//deleting an object
|
||||
public void deleteObject(String bucketName, String objectKey) {
|
||||
s3client.deleteObject(bucketName, objectKey);
|
||||
}
|
||||
|
||||
//deleting multiple Objects
|
||||
public DeleteObjectsResult deleteObjects(DeleteObjectsRequest delObjReq) {
|
||||
return s3client.deleteObjects(delObjReq);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
package com.baeldung.s3.listobjects;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class File {
|
||||
private String name;
|
||||
private ByteBuffer content;
|
||||
|
||||
public File(String name, ByteBuffer content) {
|
||||
this.name = name;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ByteBuffer getContent() {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
package com.baeldung.s3;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class File {
|
||||
private String name;
|
||||
private ByteBuffer content;
|
||||
|
||||
public File(String name, ByteBuffer content) {
|
||||
this.name = name;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ByteBuffer getContent() {
|
||||
return content;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,27 @@
|
||||
package com.baeldung.s3.listobjects;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class FileGenerator {
|
||||
|
||||
public static List<File> generateFiles(int fileCount, int fileSize) {
|
||||
List<File> files = new ArrayList<>();
|
||||
for (int i = 0; i < fileCount; i++) {
|
||||
String fileName = "file_" + i + ".txt";
|
||||
ByteBuffer fileContent = generateRandomBytes(fileSize);
|
||||
files.add(new File(fileName, fileContent));
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
private static ByteBuffer generateRandomBytes(int size) {
|
||||
byte[] array = new byte[size];
|
||||
new Random().nextBytes(array);
|
||||
return ByteBuffer.wrap(array);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
package com.baeldung.s3;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class FileGenerator {
|
||||
|
||||
public static List<File> generateFiles(int fileCount, int fileSize) {
|
||||
List<File> files = new ArrayList<>();
|
||||
for (int i = 0; i < fileCount; i++) {
|
||||
String fileName = "file_" + i + ".txt";
|
||||
ByteBuffer fileContent = generateRandomBytes(fileSize);
|
||||
files.add(new File(fileName, fileContent));
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
private static ByteBuffer generateRandomBytes(int size) {
|
||||
byte[] array = new byte[size];
|
||||
new Random().nextBytes(array);
|
||||
return ByteBuffer.wrap(array);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,56 +1,101 @@
|
||||
package com.baeldung.s3;
|
||||
|
||||
import com.amazonaws.AmazonClientException;
|
||||
import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
|
||||
import com.amazonaws.event.ProgressListener;
|
||||
import com.amazonaws.regions.Regions;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
||||
import com.amazonaws.services.s3.model.PutObjectRequest;
|
||||
import com.amazonaws.services.s3.transfer.TransferManager;
|
||||
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
|
||||
import com.amazonaws.services.s3.transfer.Upload;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
import software.amazon.awssdk.services.s3.S3Client;
|
||||
import software.amazon.awssdk.core.sync.RequestBody;
|
||||
import software.amazon.awssdk.services.s3.model.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class MultipartUpload {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
public static void main(String[] args) {
|
||||
String existingBucketName = "baeldung-bucket";
|
||||
String keyName = "my-picture.jpg";
|
||||
String filePath = "documents/my-picture.jpg";
|
||||
|
||||
AmazonS3 amazonS3 = AmazonS3ClientBuilder
|
||||
.standard()
|
||||
.withCredentials(new DefaultAWSCredentialsProviderChain())
|
||||
.withRegion(Regions.DEFAULT_REGION)
|
||||
.build();
|
||||
ProfileCredentialsProvider credentialsProvider = ProfileCredentialsProvider.create();
|
||||
Region region = Region.US_EAST_1;
|
||||
S3Client s3 = S3Client.builder()
|
||||
.region(region)
|
||||
.credentialsProvider(credentialsProvider)
|
||||
.build();
|
||||
|
||||
int maxUploadThreads = 5;
|
||||
// Initiate a multipart upload
|
||||
CreateMultipartUploadRequest createRequest = CreateMultipartUploadRequest.builder()
|
||||
.bucket(existingBucketName)
|
||||
.key(keyName)
|
||||
.build();
|
||||
|
||||
TransferManager tm = TransferManagerBuilder
|
||||
.standard()
|
||||
.withS3Client(amazonS3)
|
||||
.withMultipartUploadThreshold((long) (5 * 1024 * 1024))
|
||||
.withExecutorFactory(() -> Executors.newFixedThreadPool(maxUploadThreads))
|
||||
.build();
|
||||
CreateMultipartUploadResponse createResponse = s3.createMultipartUpload(createRequest);
|
||||
|
||||
ProgressListener progressListener =
|
||||
progressEvent -> System.out.println("Transferred bytes: " + progressEvent.getBytesTransferred());
|
||||
String uploadId = createResponse.uploadId();
|
||||
|
||||
PutObjectRequest request = new PutObjectRequest(existingBucketName, keyName, new File(filePath));
|
||||
// Prepare the parts to be uploaded
|
||||
List<CompletedPart> completedParts = new ArrayList<>();
|
||||
int partNumber = 1;
|
||||
ByteBuffer buffer = ByteBuffer.allocate(5 * 1024 * 1024); // Set your preferred part size (5 MB in this example)
|
||||
|
||||
request.setGeneralProgressListener(progressListener);
|
||||
// Read the file and upload each part
|
||||
try (RandomAccessFile file = new RandomAccessFile(filePath, "r")) {
|
||||
long fileSize = file.length();
|
||||
long position = 0;
|
||||
|
||||
Upload upload = tm.upload(request);
|
||||
while (position < fileSize) {
|
||||
file.seek(position);
|
||||
int bytesRead = file.getChannel().read(buffer);
|
||||
|
||||
try {
|
||||
upload.waitForCompletion();
|
||||
System.out.println("Upload complete.");
|
||||
} catch (AmazonClientException e) {
|
||||
System.out.println("Error occurred while uploading file");
|
||||
buffer.flip();
|
||||
UploadPartRequest uploadPartRequest = UploadPartRequest.builder()
|
||||
.bucket(existingBucketName)
|
||||
.key(keyName)
|
||||
.uploadId(uploadId)
|
||||
.partNumber(partNumber)
|
||||
.contentLength((long) bytesRead)
|
||||
.build();
|
||||
|
||||
UploadPartResponse response = s3.uploadPart(uploadPartRequest, RequestBody.fromByteBuffer(buffer));
|
||||
|
||||
completedParts.add(CompletedPart.builder()
|
||||
.partNumber(partNumber)
|
||||
.eTag(response.eTag())
|
||||
.build());
|
||||
|
||||
buffer.clear();
|
||||
position += bytesRead;
|
||||
partNumber++;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Complete the multipart upload
|
||||
CompletedMultipartUpload completedUpload = CompletedMultipartUpload.builder()
|
||||
.parts(completedParts)
|
||||
.build();
|
||||
|
||||
CompleteMultipartUploadRequest completeRequest = CompleteMultipartUploadRequest.builder()
|
||||
.bucket(existingBucketName)
|
||||
.key(keyName)
|
||||
.uploadId(uploadId)
|
||||
.multipartUpload(completedUpload)
|
||||
.build();
|
||||
|
||||
CompleteMultipartUploadResponse completeResponse = s3.completeMultipartUpload(completeRequest);
|
||||
|
||||
// Print the object's URL
|
||||
String objectUrl = s3.utilities().getUrl(GetUrlRequest.builder()
|
||||
.bucket(existingBucketName)
|
||||
.key(keyName)
|
||||
.build())
|
||||
.toExternalForm();
|
||||
|
||||
System.out.println("Uploaded object URL: " + objectUrl);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,104 +1,69 @@
|
||||
package com.baeldung.s3;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import com.amazonaws.auth.AWSCredentials;
|
||||
import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
||||
import com.amazonaws.auth.BasicAWSCredentials;
|
||||
import com.amazonaws.regions.Regions;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
||||
import com.amazonaws.services.s3.model.Bucket;
|
||||
import com.amazonaws.services.s3.model.DeleteObjectsRequest;
|
||||
import com.amazonaws.services.s3.model.ObjectListing;
|
||||
import com.amazonaws.services.s3.model.S3Object;
|
||||
import com.amazonaws.services.s3.model.S3ObjectInputStream;
|
||||
import com.amazonaws.services.s3.model.S3ObjectSummary;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
|
||||
public class S3Application {
|
||||
|
||||
private static final AWSCredentials credentials;
|
||||
private static String bucketName;
|
||||
private static String AWS_BUCKET = "baeldung-tutorial-s3";
|
||||
public static Region AWS_REGION = Region.EU_CENTRAL_1;
|
||||
|
||||
static {
|
||||
//put your accesskey and secretkey here
|
||||
credentials = new BasicAWSCredentials(
|
||||
"<AWS accesskey>",
|
||||
"<AWS secretkey>"
|
||||
);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
//set-up the client
|
||||
AmazonS3 s3client = AmazonS3ClientBuilder
|
||||
.standard()
|
||||
.withCredentials(new AWSStaticCredentialsProvider(credentials))
|
||||
.withRegion(Regions.US_EAST_2)
|
||||
.build();
|
||||
|
||||
AWSS3Service awsService = new AWSS3Service(s3client);
|
||||
|
||||
bucketName = "baeldung-bucket";
|
||||
public static void main(String[] args) {
|
||||
S3Service s3Service = new S3Service(AWS_REGION);
|
||||
|
||||
//creating a bucket
|
||||
if(awsService.doesBucketExist(bucketName)) {
|
||||
s3Service.createBucket(AWS_BUCKET);
|
||||
|
||||
//check if a bucket exists
|
||||
if(s3Service.doesBucketExist(AWS_BUCKET)) {
|
||||
System.out.println("Bucket name is not available."
|
||||
+ " Try again with a different Bucket name.");
|
||||
+ " Try again with a different Bucket name.");
|
||||
return;
|
||||
}
|
||||
awsService.createBucket(bucketName);
|
||||
|
||||
//list all the buckets
|
||||
for(Bucket s : awsService.listBuckets() ) {
|
||||
System.out.println(s.getName());
|
||||
}
|
||||
|
||||
//deleting bucket
|
||||
awsService.deleteBucket("baeldung-bucket-test2");
|
||||
|
||||
//uploading object
|
||||
awsService.putObject(
|
||||
bucketName,
|
||||
"Document/hello.txt",
|
||||
new File("/Users/user/Document/hello.txt")
|
||||
);
|
||||
|
||||
//uploading object and getting url
|
||||
awsService.getObjectURL(bucketName, "Document/hello.txt", new File("/Users/user/Document/hello.txt"));
|
||||
|
||||
s3Service.putObjects(AWS_BUCKET, FileGenerator.generateFiles(1000, 1));
|
||||
|
||||
//list all the buckets
|
||||
s3Service.listBuckets();
|
||||
s3Service.listObjectsInBucket(AWS_BUCKET);
|
||||
s3Service.listAllObjectsInBucket(AWS_BUCKET);
|
||||
s3Service.listAllObjectsInBucketPaginated(AWS_BUCKET, 500);
|
||||
s3Service.listAllObjectsInBucketPaginatedWithPrefix(AWS_BUCKET, 500, "backup/");
|
||||
|
||||
|
||||
|
||||
//deleting bucket
|
||||
s3Service.deleteBucket("baeldung-bucket-test2");
|
||||
|
||||
//uploading object
|
||||
s3Service.putObject(
|
||||
AWS_BUCKET,
|
||||
"Document/hello.txt",
|
||||
new File("/Users/user/Document/hello.txt")
|
||||
);
|
||||
|
||||
//listing objects
|
||||
ObjectListing objectListing = awsService.listObjects(bucketName);
|
||||
for(S3ObjectSummary os : objectListing.getObjectSummaries()) {
|
||||
System.out.println(os.getKey());
|
||||
}
|
||||
s3Service.listObjects(AWS_BUCKET);
|
||||
|
||||
//downloading an object
|
||||
S3Object s3object = awsService.getObject(bucketName, "Document/hello.txt");
|
||||
S3ObjectInputStream inputStream = s3object.getObjectContent();
|
||||
FileUtils.copyInputStreamToFile(inputStream, new File("/Users/user/Desktop/hello.txt"));
|
||||
|
||||
s3Service.getObject(AWS_BUCKET, "Document/hello.txt");
|
||||
|
||||
//copying an object
|
||||
awsService.copyObject(
|
||||
"baeldung-bucket",
|
||||
"picture/pic.png",
|
||||
"baeldung-bucket2",
|
||||
"Document/picture.png"
|
||||
s3Service.copyObject(
|
||||
"baeldung-bucket",
|
||||
"picture/pic.png",
|
||||
"baeldung-bucket2",
|
||||
"Document/picture.png"
|
||||
);
|
||||
|
||||
|
||||
//deleting an object
|
||||
awsService.deleteObject(bucketName, "Document/hello.txt");
|
||||
s3Service.deleteObject(AWS_BUCKET, "Document/hello.txt");
|
||||
|
||||
//deleting multiple objects
|
||||
String objkeyArr[] = {
|
||||
"Document/hello2.txt",
|
||||
"Document/picture.png"
|
||||
};
|
||||
|
||||
DeleteObjectsRequest delObjReq = new DeleteObjectsRequest("baeldung-bucket")
|
||||
.withKeys(objkeyArr);
|
||||
awsService.deleteObjects(delObjReq);
|
||||
List<String> objKeyList = List.of("Document/hello2.txt", "Document/picture.png");
|
||||
s3Service.deleteObjects(AWS_BUCKET, objKeyList);
|
||||
}
|
||||
}
|
||||
|
||||
323
aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java
Normal file
323
aws-modules/aws-s3/src/main/java/com/baeldung/s3/S3Service.java
Normal file
@@ -0,0 +1,323 @@
|
||||
package com.baeldung.s3;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
|
||||
import software.amazon.awssdk.core.ResponseBytes;
|
||||
import software.amazon.awssdk.core.sync.RequestBody;
|
||||
import software.amazon.awssdk.regions.Region;
|
||||
import software.amazon.awssdk.services.s3.S3Client;
|
||||
import software.amazon.awssdk.services.s3.model.Bucket;
|
||||
import software.amazon.awssdk.services.s3.model.CopyObjectRequest;
|
||||
import software.amazon.awssdk.services.s3.model.CopyObjectResponse;
|
||||
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
|
||||
import software.amazon.awssdk.services.s3.model.Delete;
|
||||
import software.amazon.awssdk.services.s3.model.DeleteBucketRequest;
|
||||
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
|
||||
import software.amazon.awssdk.services.s3.model.DeleteObjectsRequest;
|
||||
import software.amazon.awssdk.services.s3.model.GetObjectRequest;
|
||||
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
|
||||
import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
|
||||
import software.amazon.awssdk.services.s3.model.HeadObjectRequest;
|
||||
import software.amazon.awssdk.services.s3.model.ListBucketsResponse;
|
||||
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
|
||||
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
|
||||
import software.amazon.awssdk.services.s3.model.NoSuchBucketException;
|
||||
import software.amazon.awssdk.services.s3.model.ObjectIdentifier;
|
||||
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
|
||||
import software.amazon.awssdk.services.s3.model.PutObjectResponse;
|
||||
import software.amazon.awssdk.services.s3.model.S3Exception;
|
||||
import software.amazon.awssdk.services.s3.model.S3Object;
|
||||
import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable;
|
||||
|
||||
class S3Service {
|
||||
|
||||
private S3Client s3Client;
|
||||
|
||||
public S3Service(Region awsRegion) {
|
||||
init(awsRegion);
|
||||
}
|
||||
|
||||
public S3Service(S3Client s3Client) {
|
||||
this.s3Client = s3Client;
|
||||
}
|
||||
|
||||
public void init(Region awsRegion) {
|
||||
this.s3Client = S3Client.builder()
|
||||
.region(awsRegion)
|
||||
.credentialsProvider(ProfileCredentialsProvider.create("default"))
|
||||
.build();
|
||||
}
|
||||
|
||||
//is bucket exist?
|
||||
public boolean doesBucketExist(String bucketName) {
|
||||
HeadBucketRequest headBucketRequest = HeadBucketRequest.builder()
|
||||
.bucket(bucketName)
|
||||
.build();
|
||||
|
||||
try {
|
||||
s3Client.headBucket(headBucketRequest);
|
||||
return true;
|
||||
} catch (NoSuchBucketException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//create a bucket
|
||||
public void createBucket(String bucketName) {
|
||||
CreateBucketRequest bucketRequest = CreateBucketRequest.builder()
|
||||
.bucket(bucketName)
|
||||
.build();
|
||||
|
||||
s3Client.createBucket(bucketRequest);
|
||||
}
|
||||
|
||||
//delete a bucket
|
||||
public void deleteBucket(String bucketName) {
|
||||
try {
|
||||
DeleteBucketRequest deleteBucketRequest = DeleteBucketRequest.builder()
|
||||
.bucket(bucketName)
|
||||
.build();
|
||||
|
||||
s3Client.deleteBucket(deleteBucketRequest);
|
||||
System.out.println("Successfully deleted bucket : " + bucketName);
|
||||
} catch (S3Exception e) {
|
||||
System.err.println(e.getMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
//uploading object
|
||||
public PutObjectResponse putObject(String bucketName, String key, java.io.File file) {
|
||||
PutObjectRequest request = PutObjectRequest.builder()
|
||||
.bucket(bucketName)
|
||||
.key(key)
|
||||
.build();
|
||||
|
||||
return s3Client.putObject(request, Path.of(file.toURI()) );
|
||||
}
|
||||
|
||||
//listing objects
|
||||
public void listObjects(String bucketName) {
|
||||
ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder()
|
||||
.bucket(bucketName)
|
||||
.build();
|
||||
ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request);
|
||||
|
||||
for(S3Object os : listObjectsV2Response.contents()) {
|
||||
System.out.println(os.key());
|
||||
}
|
||||
}
|
||||
|
||||
//get an object
|
||||
public void getObject(String bucketName, String objectKey) {
|
||||
try {
|
||||
GetObjectRequest objectRequest = GetObjectRequest.builder()
|
||||
.bucket(bucketName)
|
||||
.key(objectKey)
|
||||
.build();
|
||||
|
||||
ResponseBytes<GetObjectResponse> responseResponseBytes = s3Client.getObjectAsBytes(objectRequest);
|
||||
|
||||
byte[] data = responseResponseBytes.asByteArray();
|
||||
|
||||
// Write the data to a local file.
|
||||
java.io.File myFile = new java.io.File("/Users/user/Desktop/hello.txt" );
|
||||
OutputStream os = new FileOutputStream(myFile);
|
||||
os.write(data);
|
||||
System.out.println("Successfully obtained bytes from an S3 object");
|
||||
os.close();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
} catch (S3Exception e) {
|
||||
System.err.println(e.awsErrorDetails().errorMessage());
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
//copying an object
|
||||
public CopyObjectResponse copyObject(
|
||||
String sourceBucketName,
|
||||
String sourceKey,
|
||||
String destinationBucketName,
|
||||
String destinationKey
|
||||
) {
|
||||
CopyObjectRequest copyObjectRequest = CopyObjectRequest.builder()
|
||||
.sourceBucket(sourceBucketName)
|
||||
.sourceKey(sourceKey)
|
||||
.destinationBucket(destinationBucketName)
|
||||
.destinationKey(destinationKey)
|
||||
.build();
|
||||
|
||||
return s3Client.copyObject(copyObjectRequest);
|
||||
}
|
||||
|
||||
//deleting an object
|
||||
public void deleteObject(String bucketName, String objectKey) {
|
||||
DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder()
|
||||
.bucket(bucketName)
|
||||
.key(objectKey)
|
||||
.build();
|
||||
|
||||
s3Client.deleteObject(deleteObjectRequest);
|
||||
}
|
||||
|
||||
//deleting multiple Objects
|
||||
public void deleteObjects(String bucketName, List<String> keys ) {
|
||||
|
||||
ArrayList<ObjectIdentifier> toDelete = new ArrayList<>();
|
||||
for(String objKey : keys) {
|
||||
toDelete.add(ObjectIdentifier.builder()
|
||||
.key(objKey)
|
||||
.build());
|
||||
}
|
||||
|
||||
DeleteObjectsRequest deleteObjectRequest = DeleteObjectsRequest.builder()
|
||||
.bucket(bucketName)
|
||||
.delete(Delete.builder()
|
||||
.objects(toDelete).build())
|
||||
.build();
|
||||
|
||||
s3Client.deleteObjects(deleteObjectRequest);
|
||||
}
|
||||
|
||||
public boolean doesObjectExistByListObjects(String bucketName, String key) {
|
||||
|
||||
ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder()
|
||||
.bucket(bucketName)
|
||||
.build();
|
||||
ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request);
|
||||
|
||||
return listObjectsV2Response.contents()
|
||||
.stream()
|
||||
.filter(s3ObjectSummary -> s3ObjectSummary.getValueForField("key", String.class)
|
||||
.equals(key))
|
||||
.findFirst()
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
public boolean doesObjectExistByDefaultMethod(String bucket, String key) {
|
||||
try {
|
||||
HeadObjectRequest headObjectRequest = HeadObjectRequest.builder()
|
||||
.bucket(bucket)
|
||||
.key(key)
|
||||
.build();
|
||||
|
||||
s3Client.headObject(headObjectRequest);
|
||||
|
||||
System.out.println("Object exists");
|
||||
return true;
|
||||
} catch (S3Exception e) {
|
||||
if (e.statusCode() == 404) {
|
||||
System.out.println("Object does not exist");
|
||||
return false;
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void listBuckets() {
|
||||
// List all buckets
|
||||
ListBucketsResponse listBucketsResponse = s3Client.listBuckets();
|
||||
|
||||
// Display the bucket names
|
||||
List<Bucket> buckets = listBucketsResponse.buckets();
|
||||
System.out.println("Buckets:");
|
||||
for (Bucket bucket : buckets) {
|
||||
System.out.println(bucket.name());
|
||||
}
|
||||
}
|
||||
|
||||
public void listObjectsInBucket(String bucketName) {
|
||||
ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder()
|
||||
.bucket(bucketName)
|
||||
.build();
|
||||
ListObjectsV2Response listObjectsV2Response = s3Client.listObjectsV2(listObjectsV2Request);
|
||||
|
||||
List<S3Object> contents = listObjectsV2Response.contents();
|
||||
|
||||
System.out.println("Number of objects in the bucket: " + contents.stream().count());
|
||||
contents.stream().forEach(System.out::println);
|
||||
}
|
||||
|
||||
public void listAllObjectsInBucket(String bucketName) {
|
||||
String nextContinuationToken = null;
|
||||
long totalObjects = 0;
|
||||
|
||||
do {
|
||||
ListObjectsV2Request.Builder requestBuilder = ListObjectsV2Request.builder()
|
||||
.bucket(bucketName)
|
||||
.continuationToken(nextContinuationToken);
|
||||
|
||||
ListObjectsV2Response response = s3Client.listObjectsV2(requestBuilder.build());
|
||||
nextContinuationToken = response.nextContinuationToken();
|
||||
|
||||
totalObjects += response.contents().stream()
|
||||
.peek(System.out::println)
|
||||
.reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum);
|
||||
} while (nextContinuationToken != null);
|
||||
System.out.println("Number of objects in the bucket: " + totalObjects);
|
||||
}
|
||||
|
||||
public void listAllObjectsInBucketPaginated(String bucketName, int pageSize) {
|
||||
ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder()
|
||||
.bucket(bucketName)
|
||||
.maxKeys(pageSize) // Set the maxKeys parameter to control the page size
|
||||
.build();
|
||||
|
||||
ListObjectsV2Iterable listObjectsV2Iterable = s3Client.listObjectsV2Paginator(listObjectsV2Request);
|
||||
long totalObjects = 0;
|
||||
|
||||
for (ListObjectsV2Response page : listObjectsV2Iterable) {
|
||||
long retrievedPageSize = page.contents().stream()
|
||||
.peek(System.out::println)
|
||||
.reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum);
|
||||
totalObjects += retrievedPageSize;
|
||||
System.out.println("Page size: " + retrievedPageSize);
|
||||
}
|
||||
System.out.println("Total objects in the bucket: " + totalObjects);
|
||||
}
|
||||
|
||||
public void listAllObjectsInBucketPaginatedWithPrefix(String bucketName, int pageSize, String prefix) {
|
||||
ListObjectsV2Request listObjectsV2Request = ListObjectsV2Request.builder()
|
||||
.bucket(bucketName)
|
||||
.maxKeys(pageSize) // Set the maxKeys parameter to control the page size
|
||||
.prefix(prefix)
|
||||
.build();
|
||||
|
||||
ListObjectsV2Iterable listObjectsV2Iterable = s3Client.listObjectsV2Paginator(listObjectsV2Request);
|
||||
long totalObjects = 0;
|
||||
|
||||
for (ListObjectsV2Response page : listObjectsV2Iterable) {
|
||||
long retrievedPageSize = page.contents().stream()
|
||||
.peek(System.out::println)
|
||||
.reduce(0, (subtotal, element) -> subtotal + 1, Integer::sum);
|
||||
totalObjects += retrievedPageSize;
|
||||
System.out.println("Page size: " + retrievedPageSize);
|
||||
}
|
||||
System.out.println("Total objects in the bucket: " + totalObjects);
|
||||
}
|
||||
|
||||
public void putObjects(String bucketName, List<File> files) {
|
||||
try {
|
||||
files.stream().forEach(file -> {
|
||||
s3Client.putObject(PutObjectRequest.builder().bucket(bucketName).key(file.getName()).build(),
|
||||
RequestBody.fromByteBuffer(file.getContent()));
|
||||
System.out.println("Uploaded file: " + file.getName());
|
||||
});
|
||||
} catch (S3Exception e) {
|
||||
System.err.println("Upload failed");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public void cleanup() {
|
||||
this.s3Client.close();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,4 +10,7 @@
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
<!-- Change the log level for software.amazon.awssdk -->
|
||||
<logger name="software.amazon.awssdk" level="info" />
|
||||
</configuration>
|
||||
@@ -1,5 +1,13 @@
|
||||
package com.baeldung.jets3t;
|
||||
|
||||
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -10,8 +18,8 @@ import org.jets3t.service.model.S3Bucket;
|
||||
import org.jets3t.service.model.S3Object;
|
||||
import org.jets3t.service.model.StorageObject;
|
||||
import org.jets3t.service.security.AWSCredentials;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
@@ -19,14 +27,13 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
|
||||
|
||||
|
||||
public class JetS3tLiveTest {
|
||||
|
||||
private Log log = LogFactory.getLog(JetS3tLiveTest.class);
|
||||
private final Log log = LogFactory.getLog(JetS3tLiveTest.class);
|
||||
|
||||
private static final String BucketName = "baeldung-barfoo";
|
||||
private static final String TestString = "test string";
|
||||
@@ -35,7 +42,7 @@ public class JetS3tLiveTest {
|
||||
|
||||
private static S3Service s3Service;
|
||||
|
||||
@BeforeClass
|
||||
@BeforeAll
|
||||
public static void connectS3() throws Exception {
|
||||
|
||||
// Replace with your keys
|
||||
@@ -50,7 +57,7 @@ public class JetS3tLiveTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenCreate_AndDeleteBucket_CountGoesUpThenDown() throws Exception {
|
||||
void givenCreate_AndDeleteBucket_CountGoesUpThenDown() throws Exception {
|
||||
|
||||
// List buckets, get a count
|
||||
S3Bucket[] myBuckets = s3Service.listAllBuckets();
|
||||
@@ -89,7 +96,7 @@ public class JetS3tLiveTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenString_Uploaded_StringInfoIsAvailable() throws Exception {
|
||||
void givenString_Uploaded_StringInfoIsAvailable() throws Exception {
|
||||
|
||||
// Create a bucket
|
||||
S3Bucket bucket = createBucket();
|
||||
@@ -120,7 +127,7 @@ public class JetS3tLiveTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenStringUploaded_StringIsDownloaded() throws Exception {
|
||||
void givenStringUploaded_StringIsDownloaded() throws Exception {
|
||||
|
||||
// Get a bucket
|
||||
S3Bucket bucket = createBucket();
|
||||
@@ -135,7 +142,7 @@ public class JetS3tLiveTest {
|
||||
String downloadedString = new BufferedReader(new InputStreamReader(stringObject.getDataInputStream())).lines().collect(Collectors.joining("\n"));
|
||||
|
||||
// Verify
|
||||
assertTrue(TestString.equals(downloadedString));
|
||||
assertEquals(TestString, downloadedString);
|
||||
|
||||
|
||||
// Clean up for next test
|
||||
@@ -144,7 +151,7 @@ public class JetS3tLiveTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBinaryFileUploaded_FileIsDownloaded() throws Exception {
|
||||
void givenBinaryFileUploaded_FileIsDownloaded() throws Exception {
|
||||
|
||||
// get a bucket
|
||||
S3Bucket bucket = createBucket();
|
||||
@@ -169,7 +176,7 @@ public class JetS3tLiveTest {
|
||||
// Get hashes and compare
|
||||
String origMD5 = getFileMD5("src/test/resources/test.jpg");
|
||||
String newMD5 = getFileMD5("src/test/resources/newtest.jpg");
|
||||
assertTrue(origMD5.equals(newMD5));
|
||||
assertEquals(origMD5, newMD5);
|
||||
|
||||
// Clean up
|
||||
deleteObject("test.jpg");
|
||||
@@ -186,7 +193,7 @@ public class JetS3tLiveTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void givenStreamDataUploaded_StreamDataIsDownloaded() throws Exception {
|
||||
void givenStreamDataUploaded_StreamDataIsDownloaded() throws Exception {
|
||||
|
||||
// get a bucket
|
||||
S3Bucket bucket = createBucket();
|
||||
@@ -233,7 +240,7 @@ public class JetS3tLiveTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenFileCopied_CopyIsSame() throws Exception {
|
||||
void whenFileCopied_CopyIsSame() throws Exception {
|
||||
|
||||
// get a bucket
|
||||
S3Bucket bucket = createBucket();
|
||||
@@ -260,7 +267,7 @@ public class JetS3tLiveTest {
|
||||
// Get hashes and compare
|
||||
String origMD5 = getFileMD5("src/test/resources/test.jpg");
|
||||
String newMD5 = getFileMD5("src/test/resources/testcopy.jpg");
|
||||
assertTrue(origMD5.equals(newMD5));
|
||||
assertEquals(origMD5, newMD5);
|
||||
|
||||
// Clean up
|
||||
deleteObject("test.jpg");
|
||||
@@ -271,7 +278,7 @@ public class JetS3tLiveTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void whenFileRenamed_NewNameIsSame() throws Exception {
|
||||
void whenFileRenamed_NewNameIsSame() throws Exception {
|
||||
|
||||
// get a bucket
|
||||
S3Bucket bucket = createBucket();
|
||||
@@ -297,7 +304,7 @@ public class JetS3tLiveTest {
|
||||
// Get hashes and compare
|
||||
String origMD5 = getFileMD5("src/test/resources/test.jpg");
|
||||
String newMD5 = getFileMD5("src/test/resources/spidey.jpg");
|
||||
assertTrue(origMD5.equals(newMD5));
|
||||
assertEquals(origMD5, newMD5);
|
||||
|
||||
// Clean up
|
||||
deleteObject("test.jpg");
|
||||
@@ -307,7 +314,7 @@ public class JetS3tLiveTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenFileMoved_NewInstanceIsSame() throws Exception {
|
||||
void whenFileMoved_NewInstanceIsSame() throws Exception {
|
||||
|
||||
// get a bucket
|
||||
S3Bucket bucket = createBucket();
|
||||
@@ -338,7 +345,7 @@ public class JetS3tLiveTest {
|
||||
// Get hashes and compare
|
||||
String origMD5 = getFileMD5("src/test/resources/test.jpg");
|
||||
String newMD5 = getFileMD5("src/test/resources/spidey.jpg");
|
||||
assertTrue(origMD5.equals(newMD5));
|
||||
assertEquals(origMD5, newMD5);
|
||||
|
||||
// Clean up
|
||||
deleteBucket();
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.baeldung.s3;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.amazonaws.auth.EnvironmentVariableCredentialsProvider;
|
||||
import com.amazonaws.regions.Regions;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
||||
|
||||
/**
|
||||
* Required defined environment variables AWS_ACCESS_KEY_ID & AWS_ACCESS_KEY to access S3.
|
||||
* Required S3 bucket and key that exist.
|
||||
*/
|
||||
|
||||
public class AWSS3ObjectManualTest {
|
||||
|
||||
private static final String BUCKET = "your-bucket";
|
||||
private static final String KEY_THAT_EXIST = "your-key-that-exist";
|
||||
private AWSS3ObjectUtils s3ObjectUtils;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
AmazonS3 client = AmazonS3ClientBuilder.standard()
|
||||
.withRegion(Regions.DEFAULT_REGION)
|
||||
.withCredentials(new EnvironmentVariableCredentialsProvider())
|
||||
.build();
|
||||
|
||||
s3ObjectUtils = new AWSS3ObjectUtils(client);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenVerifyIfObjectExistByDefaultMethod_thenCorrect() {
|
||||
assertTrue(s3ObjectUtils.doesObjectExistByDefaultMethod(BUCKET, KEY_THAT_EXIST), "Key: " + KEY_THAT_EXIST + " doesn't exist");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenVerifyIfObjectExistByListObjects_thenCorrect() {
|
||||
assertTrue(s3ObjectUtils.doesObjectExistByListObjects(BUCKET, KEY_THAT_EXIST), "Key: " + KEY_THAT_EXIST + " doesn't exist");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenVerifyIfObjectExistByMetaData_thenCorrect() {
|
||||
assertTrue(s3ObjectUtils.doesObjectExistByMetaData(BUCKET, KEY_THAT_EXIST), "Key: " + KEY_THAT_EXIST + " doesn't exist");
|
||||
}
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
package com.baeldung.s3;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.model.CopyObjectResult;
|
||||
import com.amazonaws.services.s3.model.DeleteObjectsRequest;
|
||||
import com.amazonaws.services.s3.model.DeleteObjectsResult;
|
||||
import com.amazonaws.services.s3.model.PutObjectResult;
|
||||
|
||||
public class AWSS3ServiceIntegrationTest {
|
||||
|
||||
private static final String BUCKET_NAME = "bucket_name";
|
||||
private static final String KEY_NAME = "key_name";
|
||||
private static final String BUCKET_NAME2 = "bucket_name2";
|
||||
private static final String KEY_NAME2 = "key_name2";
|
||||
|
||||
private AmazonS3 s3;
|
||||
private AWSS3Service service;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
s3 = mock(AmazonS3.class);
|
||||
service = new AWSS3Service(s3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInitializingAWSS3Service_thenNotNull() {
|
||||
assertThat(new AWSS3Service()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenVerifyingIfS3BucketExist_thenCorrect() {
|
||||
service.doesBucketExist(BUCKET_NAME);
|
||||
verify(s3).doesBucketExist(BUCKET_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenVerifyingCreationOfS3Bucket_thenCorrect() {
|
||||
service.createBucket(BUCKET_NAME);
|
||||
verify(s3).createBucket(BUCKET_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenVerifyingListBuckets_thenCorrect() {
|
||||
service.listBuckets();
|
||||
verify(s3).listBuckets();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenDeletingBucket_thenCorrect() {
|
||||
service.deleteBucket(BUCKET_NAME);
|
||||
verify(s3).deleteBucket(BUCKET_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenVerifyingPutObject_thenCorrect() {
|
||||
File file = mock(File.class);
|
||||
PutObjectResult result = mock(PutObjectResult.class);
|
||||
when(s3.putObject(anyString(), anyString(), (File) any())).thenReturn(result);
|
||||
|
||||
assertThat(service.putObject(BUCKET_NAME, KEY_NAME, file)).isEqualTo(result);
|
||||
verify(s3).putObject(BUCKET_NAME, KEY_NAME, file);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenVerifyingListObjects_thenCorrect() {
|
||||
service.listObjects(BUCKET_NAME);
|
||||
verify(s3).listObjects(BUCKET_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenVerifyingGetObject_thenCorrect() {
|
||||
service.getObject(BUCKET_NAME, KEY_NAME);
|
||||
verify(s3).getObject(BUCKET_NAME, KEY_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenVerifyingCopyObject_thenCorrect() {
|
||||
CopyObjectResult result = mock(CopyObjectResult.class);
|
||||
when(s3.copyObject(anyString(), anyString(), anyString(), anyString())).thenReturn(result);
|
||||
|
||||
assertThat(service.copyObject(BUCKET_NAME, KEY_NAME, BUCKET_NAME2, KEY_NAME2)).isEqualTo(result);
|
||||
verify(s3).copyObject(BUCKET_NAME, KEY_NAME, BUCKET_NAME2, KEY_NAME2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenVerifyingDeleteObject_thenCorrect() {
|
||||
service.deleteObject(BUCKET_NAME, KEY_NAME);
|
||||
verify(s3).deleteObject(BUCKET_NAME, KEY_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenVerifyingDeleteObjects_thenCorrect() {
|
||||
DeleteObjectsRequest request = mock(DeleteObjectsRequest.class);
|
||||
DeleteObjectsResult result = mock(DeleteObjectsResult.class);
|
||||
when(s3.deleteObjects((DeleteObjectsRequest)any())).thenReturn(result);
|
||||
|
||||
assertThat(service.deleteObjects(request)).isEqualTo(result);
|
||||
verify(s3).deleteObjects(request);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
package com.baeldung.s3;
|
||||
|
||||
import com.amazonaws.event.ProgressListener;
|
||||
import com.amazonaws.services.s3.AmazonS3;
|
||||
import com.amazonaws.services.s3.model.PutObjectRequest;
|
||||
import com.amazonaws.services.s3.model.PutObjectResult;
|
||||
import com.amazonaws.services.s3.transfer.TransferManager;
|
||||
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
|
||||
import com.amazonaws.services.s3.transfer.Upload;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class MultipartUploadLiveTest {
|
||||
|
||||
private static final String BUCKET_NAME = "bucket_name";
|
||||
private static final String KEY_NAME = "picture.jpg";
|
||||
|
||||
private AmazonS3 amazonS3;
|
||||
private TransferManager tm;
|
||||
private ProgressListener progressListener;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
amazonS3 = mock(AmazonS3.class);
|
||||
tm = TransferManagerBuilder
|
||||
.standard()
|
||||
.withS3Client(amazonS3)
|
||||
.withMultipartUploadThreshold((long) (5 * 1024 * 1025))
|
||||
.withExecutorFactory(() -> Executors.newFixedThreadPool(5))
|
||||
.build();
|
||||
progressListener =
|
||||
progressEvent -> System.out.println("Transferred bytes: " + progressEvent.getBytesTransferred());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenUploadingFileWithTransferManager_thenVerifyUploadRequested() {
|
||||
File file = mock(File.class);
|
||||
PutObjectResult s3Result = mock(PutObjectResult.class);
|
||||
|
||||
when(amazonS3.putObject(anyString(), anyString(), (File) any())).thenReturn(s3Result);
|
||||
when(file.getName()).thenReturn(KEY_NAME);
|
||||
|
||||
PutObjectRequest request = new PutObjectRequest(BUCKET_NAME, KEY_NAME, file);
|
||||
request.setGeneralProgressListener(progressListener);
|
||||
|
||||
Upload upload = tm.upload(request);
|
||||
|
||||
assertThat(upload).isNotNull();
|
||||
verify(amazonS3).putObject(request);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package com.baeldung.s3;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import software.amazon.awssdk.services.s3.S3Client;
|
||||
import software.amazon.awssdk.services.s3.model.CopyObjectRequest;
|
||||
import software.amazon.awssdk.services.s3.model.CopyObjectResponse;
|
||||
import software.amazon.awssdk.services.s3.model.CreateBucketRequest;
|
||||
import software.amazon.awssdk.services.s3.model.DeleteBucketRequest;
|
||||
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
|
||||
import software.amazon.awssdk.services.s3.model.HeadBucketRequest;
|
||||
import software.amazon.awssdk.services.s3.model.ListBucketsResponse;
|
||||
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
|
||||
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
|
||||
|
||||
class S3ServiceIntegrationTest {
|
||||
|
||||
private static final String BUCKET_NAME = "bucket_name";
|
||||
private static final String KEY_NAME = "key_name";
|
||||
private static final String BUCKET_NAME2 = "bucket_name2";
|
||||
private static final String KEY_NAME2 = "key_name2";
|
||||
|
||||
@Mock
|
||||
private S3Client s3Client;
|
||||
|
||||
private S3Service s3Service;
|
||||
|
||||
private final String AWS_BUCKET = "baeldung-tutorial-s3";
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
s3Service = new S3Service(s3Client);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void cleanup() {
|
||||
s3Service.cleanup();
|
||||
Mockito.verify(s3Client).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenInitializingAWSS3Service_thenNotNull() {
|
||||
assertThat(new S3Service(s3Client)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenVerifyingIfS3BucketExist_thenCorrect() {
|
||||
HeadBucketRequest headBucketRequest = HeadBucketRequest.builder()
|
||||
.bucket(BUCKET_NAME)
|
||||
.build();
|
||||
|
||||
s3Service.doesBucketExist(BUCKET_NAME);
|
||||
verify(s3Client).headBucket(headBucketRequest);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenVerifyingCreationOfS3Bucket_thenCorrect() {
|
||||
CreateBucketRequest bucketRequest = CreateBucketRequest.builder()
|
||||
.bucket(BUCKET_NAME)
|
||||
.build();
|
||||
|
||||
s3Service.createBucket(BUCKET_NAME);
|
||||
verify(s3Client).createBucket(bucketRequest);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenVerifyingListBuckets_thenCorrect() {
|
||||
when(s3Client.listBuckets()).thenReturn(ListBucketsResponse.builder().buckets(Collections.emptyList()).build());
|
||||
|
||||
s3Service.listBuckets();
|
||||
Mockito.verify(s3Client).listBuckets();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenDeletingBucket_thenCorrect() {
|
||||
DeleteBucketRequest deleteBucketRequest = DeleteBucketRequest.builder()
|
||||
.bucket(BUCKET_NAME)
|
||||
.build();
|
||||
|
||||
s3Service.deleteBucket(BUCKET_NAME);
|
||||
verify(s3Client).deleteBucket(deleteBucketRequest);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
void whenVerifyingListObjects_thenCorrect() {
|
||||
ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build();
|
||||
ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build();
|
||||
|
||||
when(s3Client.listObjectsV2(request)).thenReturn(response);
|
||||
|
||||
s3Service.listObjects(AWS_BUCKET);
|
||||
verify(s3Client).listObjectsV2(request);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void whenVerifyingCopyObject_thenCorrect() {
|
||||
CopyObjectRequest request = CopyObjectRequest.builder()
|
||||
.sourceBucket(BUCKET_NAME)
|
||||
.sourceKey(KEY_NAME)
|
||||
.destinationBucket(BUCKET_NAME2)
|
||||
.destinationKey(KEY_NAME2)
|
||||
.build();
|
||||
|
||||
CopyObjectResponse result = CopyObjectResponse.builder().build();
|
||||
|
||||
when(s3Client.copyObject(request)).thenReturn(result);
|
||||
|
||||
assertThat(s3Service.copyObject(BUCKET_NAME, KEY_NAME, BUCKET_NAME2, KEY_NAME2)).isEqualTo(result);
|
||||
verify(s3Client).copyObject(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenVerifyingDeleteObject_thenCorrect() {
|
||||
DeleteObjectRequest deleteObjectRequest = DeleteObjectRequest.builder()
|
||||
.bucket(BUCKET_NAME)
|
||||
.key(KEY_NAME)
|
||||
.build();
|
||||
|
||||
s3Service.deleteObject(BUCKET_NAME, KEY_NAME);
|
||||
verify(s3Client).deleteObject(deleteObjectRequest);
|
||||
}
|
||||
}
|
||||
@@ -1,109 +1,109 @@
|
||||
package com.baeldung.s3.listobjects;
|
||||
|
||||
import com.baeldung.s3.listobjects.S3Service;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import software.amazon.awssdk.services.s3.S3Client;
|
||||
import software.amazon.awssdk.services.s3.model.ListBucketsResponse;
|
||||
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
|
||||
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
|
||||
import software.amazon.awssdk.services.s3.model.S3Object;
|
||||
import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
class S3ServiceLiveTest {
|
||||
|
||||
@Mock
|
||||
private S3Client s3Client;
|
||||
|
||||
private S3Service s3Service;
|
||||
|
||||
private String AWS_BUCKET = "baeldung-tutorial-s3";
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
s3Service = new S3Service(s3Client);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void cleanup() {
|
||||
s3Service.cleanup();
|
||||
Mockito.verify(s3Client).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBucketName_whenListObjectsInBucket_thenReturnList() {
|
||||
ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build();
|
||||
ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build();
|
||||
|
||||
when(s3Client.listObjectsV2(request)).thenReturn(response);
|
||||
|
||||
s3Service.listObjectsInBucket(AWS_BUCKET);
|
||||
Mockito.verify(s3Client).listObjectsV2(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBucketName_whenListAllObjectsInBucket_thenReturnList() {
|
||||
ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build();
|
||||
ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build();
|
||||
|
||||
when(s3Client.listObjectsV2(request)).thenReturn(response);
|
||||
|
||||
s3Service.listAllObjectsInBucket(AWS_BUCKET);
|
||||
Mockito.verify(s3Client).listObjectsV2(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBucketNameAndPageSize_whenListAllObjectsInBucketPaginated_thenReturnPaginatedList() {
|
||||
int pageSize = 10;
|
||||
ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).maxKeys(pageSize).build();
|
||||
|
||||
ListObjectsV2Iterable mockIterable = Mockito.mock(ListObjectsV2Iterable.class);
|
||||
|
||||
S3Object s3Object1 = S3Object.builder().key("object1").build();
|
||||
S3Object s3Object2 = S3Object.builder().key("object2").build();
|
||||
ListObjectsV2Response response = ListObjectsV2Response.builder().contents(s3Object1, s3Object2).build();
|
||||
|
||||
when(s3Client.listObjectsV2Paginator(request)).thenReturn(mockIterable);
|
||||
when(mockIterable.iterator()).thenReturn(Arrays.asList(response).iterator());
|
||||
|
||||
s3Service.listAllObjectsInBucketPaginated(AWS_BUCKET, pageSize);
|
||||
Mockito.verify(s3Client).listObjectsV2Paginator(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenBucketNamePageSizeAndPrefix_whenListAllObjectsInBucketPaginatedWithPrefix_thenReturnPaginatedList() {
|
||||
int pageSize = 1;
|
||||
String prefix = "folder/";
|
||||
ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).maxKeys(pageSize).prefix(prefix).build();
|
||||
|
||||
ListObjectsV2Iterable mockIterable = Mockito.mock(ListObjectsV2Iterable.class);
|
||||
|
||||
S3Object s3Object1 = S3Object.builder().key("folder/object1").build();
|
||||
S3Object s3Object2 = S3Object.builder().key("folder/object2").build();
|
||||
ListObjectsV2Response response = ListObjectsV2Response.builder().contents(s3Object1, s3Object2).build();
|
||||
|
||||
when(s3Client.listObjectsV2Paginator(request)).thenReturn(mockIterable);
|
||||
when(mockIterable.iterator()).thenReturn(Arrays.asList(response).iterator());
|
||||
|
||||
s3Service.listAllObjectsInBucketPaginatedWithPrefix(AWS_BUCKET, pageSize, prefix);
|
||||
Mockito.verify(s3Client).listObjectsV2Paginator(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenListBuckets_thenReturnBucketList() {
|
||||
when(s3Client.listBuckets()).thenReturn(ListBucketsResponse.builder().buckets(Collections.emptyList()).build());
|
||||
|
||||
s3Service.listBuckets();
|
||||
Mockito.verify(s3Client).listBuckets();
|
||||
}
|
||||
}
|
||||
package com.baeldung.s3;
|
||||
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import software.amazon.awssdk.services.s3.S3Client;
|
||||
import software.amazon.awssdk.services.s3.model.ListBucketsResponse;
|
||||
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
|
||||
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
|
||||
import software.amazon.awssdk.services.s3.model.S3Object;
|
||||
import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
class S3ServiceLiveTest {
|
||||
|
||||
@Mock
|
||||
private S3Client s3Client;
|
||||
|
||||
private S3Service s3Service;
|
||||
|
||||
private String AWS_BUCKET = "baeldung-tutorial-s3";
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
s3Service = new S3Service(s3Client);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void cleanup() {
|
||||
s3Service.cleanup();
|
||||
Mockito.verify(s3Client).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenBucketName_whenListObjectsInBucket_thenReturnList() {
|
||||
ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build();
|
||||
ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build();
|
||||
|
||||
when(s3Client.listObjectsV2(request)).thenReturn(response);
|
||||
|
||||
s3Service.listObjectsInBucket(AWS_BUCKET);
|
||||
Mockito.verify(s3Client).listObjectsV2(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenBucketName_whenListAllObjectsInBucket_thenReturnList() {
|
||||
ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).build();
|
||||
ListObjectsV2Response response = ListObjectsV2Response.builder().contents(Collections.emptyList()).build();
|
||||
|
||||
when(s3Client.listObjectsV2(request)).thenReturn(response);
|
||||
|
||||
s3Service.listAllObjectsInBucket(AWS_BUCKET);
|
||||
Mockito.verify(s3Client).listObjectsV2(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenBucketNameAndPageSize_whenListAllObjectsInBucketPaginated_thenReturnPaginatedList() {
|
||||
int pageSize = 10;
|
||||
ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).maxKeys(pageSize).build();
|
||||
|
||||
ListObjectsV2Iterable mockIterable = Mockito.mock(ListObjectsV2Iterable.class);
|
||||
|
||||
S3Object s3Object1 = S3Object.builder().key("object1").build();
|
||||
S3Object s3Object2 = S3Object.builder().key("object2").build();
|
||||
ListObjectsV2Response response = ListObjectsV2Response.builder().contents(s3Object1, s3Object2).build();
|
||||
|
||||
when(s3Client.listObjectsV2Paginator(request)).thenReturn(mockIterable);
|
||||
when(mockIterable.iterator()).thenReturn(Arrays.asList(response).iterator());
|
||||
|
||||
s3Service.listAllObjectsInBucketPaginated(AWS_BUCKET, pageSize);
|
||||
Mockito.verify(s3Client).listObjectsV2Paginator(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
void givenBucketNamePageSizeAndPrefix_whenListAllObjectsInBucketPaginatedWithPrefix_thenReturnPaginatedList() {
|
||||
int pageSize = 1;
|
||||
String prefix = "folder/";
|
||||
ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(AWS_BUCKET).maxKeys(pageSize).prefix(prefix).build();
|
||||
|
||||
ListObjectsV2Iterable mockIterable = Mockito.mock(ListObjectsV2Iterable.class);
|
||||
|
||||
S3Object s3Object1 = S3Object.builder().key("folder/object1").build();
|
||||
S3Object s3Object2 = S3Object.builder().key("folder/object2").build();
|
||||
ListObjectsV2Response response = ListObjectsV2Response.builder().contents(s3Object1, s3Object2).build();
|
||||
|
||||
when(s3Client.listObjectsV2Paginator(request)).thenReturn(mockIterable);
|
||||
when(mockIterable.iterator()).thenReturn(Arrays.asList(response).iterator());
|
||||
|
||||
s3Service.listAllObjectsInBucketPaginatedWithPrefix(AWS_BUCKET, pageSize, prefix);
|
||||
Mockito.verify(s3Client).listObjectsV2Paginator(request);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenListBuckets_thenReturnBucketList() {
|
||||
when(s3Client.listBuckets()).thenReturn(ListBucketsResponse.builder().buckets(Collections.emptyList()).build());
|
||||
|
||||
s3Service.listBuckets();
|
||||
Mockito.verify(s3Client).listBuckets();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.baeldung.s3;
|
||||
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import software.amazon.awssdk.services.s3.S3Client;
|
||||
|
||||
/**
|
||||
* Required defined environment variables AWS_ACCESS_KEY_ID & AWS_ACCESS_KEY to access S3.
|
||||
* Required S3 bucket and key that exist.
|
||||
*/
|
||||
|
||||
class S3ServiceManualTest {
|
||||
|
||||
private static final String BUCKET_NAME = "bucket_name";
|
||||
private static final String KEY_NAME = "key_name";
|
||||
@Mock
|
||||
private S3Client s3Client;
|
||||
|
||||
private S3Service s3Service;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
MockitoAnnotations.openMocks(this);
|
||||
s3Service = new S3Service(s3Client);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void cleanup() {
|
||||
s3Service.cleanup();
|
||||
Mockito.verify(s3Client).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenVerifyIfObjectExistByDefaultMethod_thenCorrect() {
|
||||
assertTrue(s3Service.doesObjectExistByDefaultMethod(BUCKET_NAME, KEY_NAME), "Key: " + KEY_NAME + " doesn't exist");
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenVerifyIfObjectExistByListObjects_thenCorrect() {
|
||||
assertTrue(s3Service.doesObjectExistByListObjects(BUCKET_NAME, KEY_NAME), "Key: " + KEY_NAME + " doesn't exist");
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@
|
||||
<module>aws-miscellaneous</module>
|
||||
<module>aws-reactive</module>
|
||||
<module>aws-s3</module>
|
||||
<module>aws-s3-v2</module>
|
||||
<module>aws-s3-update-object</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
||||
@@ -122,7 +122,6 @@
|
||||
<docker.image.prefix>${azure.containerRegistry}.azurecr.io</docker.image.prefix>
|
||||
<docker-maven-plugin.version>1.1.0</docker-maven-plugin.version>
|
||||
<azure-webapp-maven-plugin.version>1.1.0</azure-webapp-maven-plugin.version>
|
||||
<maven-war-plugin.version>3.3.2</maven-war-plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -27,6 +27,7 @@
|
||||
<hsqldb.version>2.7.1</hsqldb.version>
|
||||
<spock-core.version>2.3-groovy-3.0</spock-core.version>
|
||||
<gmavenplus-plugin.version>2.1.0</gmavenplus-plugin.version>
|
||||
<maven-failsafe-plugin.version>2.21.0</maven-failsafe-plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
package reminderapplication;
|
||||
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.Insets;
|
||||
|
||||
public class ConstraintsBuilder {
|
||||
|
||||
static GridBagConstraints constraint(int x, int y) {
|
||||
final GridBagConstraints gridBagConstraints = new GridBagConstraints();
|
||||
gridBagConstraints.gridx = x;
|
||||
gridBagConstraints.gridy = y;
|
||||
gridBagConstraints.insets = new Insets(5, 5, 5, 5);
|
||||
return gridBagConstraints;
|
||||
}
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
package reminderapplication;
|
||||
|
||||
import static reminderapplication.ConstraintsBuilder.*;
|
||||
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.HeadlessException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
public class EditReminderFrame extends JFrame {
|
||||
|
||||
private static Timer TIMER = new Timer();
|
||||
|
||||
private final TimeReminderApplication reminderApplication;
|
||||
private final JLabel reminderTextLabel;
|
||||
private final JLabel repeatPeriodLabel;
|
||||
private final JLabel setDelayLabel;
|
||||
private final JComboBox<Integer> delay;
|
||||
private final JComboBox<Integer> period;
|
||||
private final JButton cancelButton;
|
||||
private final JButton okButton;
|
||||
private final JTextField textField;
|
||||
private final JLabel delaysLabel;
|
||||
private final JLabel periodLabel;
|
||||
|
||||
private final int reminderIndex;
|
||||
|
||||
public EditReminderFrame(TimeReminderApplication reminderApp, String reminderText, int delayInSeconds, int periodInSeconds, int index) throws HeadlessException {
|
||||
this.reminderApplication = reminderApp;
|
||||
reminderIndex = index;
|
||||
textField = createTextField(reminderText);
|
||||
delay = createDelayComboBox(delayInSeconds);
|
||||
period = createPeriodComboBox(periodInSeconds);
|
||||
cancelButton = createCancelButton();
|
||||
okButton = createOkButton();
|
||||
reminderTextLabel = createReminderTextLabel();
|
||||
repeatPeriodLabel = createRepeatPeriodLabel();
|
||||
setDelayLabel = createSetDelayLabel();
|
||||
delaysLabel = createDelaysLabel();
|
||||
periodLabel = createPeriodLabel();
|
||||
configureVisualRepresentation();
|
||||
configureActions();
|
||||
}
|
||||
|
||||
private void configureActions() {
|
||||
updateReminder();
|
||||
}
|
||||
|
||||
private void configureVisualRepresentation() {
|
||||
configureFrame();
|
||||
setLocationRelativeTo(null);
|
||||
setLayout(new GridBagLayout());
|
||||
add(reminderTextLabel, constraint(0,0));
|
||||
add(repeatPeriodLabel, constraint(1,0));
|
||||
add(setDelayLabel, constraint(2,0));
|
||||
add(textField, constraint(0, 1));
|
||||
add(delay, constraint(1, 1));
|
||||
add(period, constraint(2, 1));
|
||||
add(delaysLabel, constraint(1,3));
|
||||
add(periodLabel, constraint(2,3));
|
||||
add(okButton, constraint(1, 4));
|
||||
add(cancelButton, constraint(2, 4));
|
||||
pack();
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
private void configureFrame() {
|
||||
setTitle("Set Reminder");
|
||||
setName("Set Reminder");
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
}
|
||||
|
||||
private static JLabel createSetDelayLabel() {
|
||||
return createLabel("Set Delay", "Set Delay Label");
|
||||
}
|
||||
|
||||
private static JLabel createRepeatPeriodLabel() {
|
||||
return createLabel("Set Period", "Set Repeat Period Label");
|
||||
}
|
||||
|
||||
private static JLabel createReminderTextLabel() {
|
||||
return createLabel("Reminder Text", "Reminder Text Label");
|
||||
}
|
||||
|
||||
private JLabel createPeriodLabel() {
|
||||
return createLabel("0", "Period label");
|
||||
}
|
||||
|
||||
private JLabel createDelaysLabel() {
|
||||
return createLabel("30", "Delays Label");
|
||||
}
|
||||
|
||||
private JComboBox<Integer> createPeriodComboBox(final int periodInSeconds) {
|
||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20}));
|
||||
comboBox.setSelectedItem(periodInSeconds);
|
||||
comboBox.setName("set Period");
|
||||
comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString()));
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private JComboBox<Integer> createDelayComboBox(final int delayInSeconds) {
|
||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5}));
|
||||
comboBox.setSelectedItem(delayInSeconds);
|
||||
comboBox.setName("set Delay");
|
||||
comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString()));
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private JTextField createTextField(final String reminderText) {
|
||||
final JTextField textField = new JTextField(20);
|
||||
textField.setName("Field");
|
||||
textField.setText(reminderText);
|
||||
return textField;
|
||||
}
|
||||
|
||||
private JButton createOkButton() {
|
||||
final JButton button = new JButton("ok");
|
||||
button.setName("OK");
|
||||
return button;
|
||||
}
|
||||
|
||||
private void updateReminder() {
|
||||
okButton.addActionListener(e -> this.dispose());
|
||||
okButton.addActionListener(e -> {
|
||||
final int periodInSeconds = getTimeInSeconds(period);
|
||||
final int delayInSeconds = getTimeInSeconds(delay);
|
||||
final Reminder reminder = new Reminder(textField.getText(), delayInSeconds, periodInSeconds);
|
||||
((DefaultListModel<Reminder>) reminderApplication.getReminders()).set(reminderIndex, reminder);
|
||||
});
|
||||
okButton.addActionListener(e -> scheduleReminder(textField, delay, period));
|
||||
}
|
||||
|
||||
private void scheduleReminder(final JTextField textField, final JComboBox<Integer> delay, final JComboBox<Integer> period) {
|
||||
final int periodInSeconds = getTimeInSeconds(period);
|
||||
if (periodInSeconds == 0)
|
||||
scheduleNonRepeatedReminder(textField, delay);
|
||||
else
|
||||
scheduleRepeatedReminder(textField, delay, period);
|
||||
}
|
||||
|
||||
private void scheduleRepeatedReminder(final JTextField textField, final JComboBox<Integer> delay, final JComboBox<Integer> period) {
|
||||
final int delayInSeconds = getTimeInSeconds(delay);
|
||||
final int periodInSeconds = getTimeInSeconds(period);
|
||||
final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds);
|
||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds), TimeUnit.SECONDS.toMillis(periodInSeconds));
|
||||
}
|
||||
|
||||
private void scheduleNonRepeatedReminder(final JTextField textField, final JComboBox<Integer> delay) {
|
||||
final int delayInSeconds = getTimeInSeconds(delay);
|
||||
final int periodInSeconds = 0;
|
||||
final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds);
|
||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds));
|
||||
|
||||
}
|
||||
|
||||
private int getTimeInSeconds(final JComboBox<Integer> comboBox) {
|
||||
if (comboBox != null && comboBox.getSelectedItem() != null)
|
||||
return ((Integer) comboBox.getSelectedItem());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
private TimerTask getTimerTask(final String reminderText, final Integer delayInSeconds, final Integer periodInSeconds) {
|
||||
return new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
new ReminderPopupFrame(reminderApplication, reminderText, delayInSeconds, periodInSeconds);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private JButton createCancelButton() {
|
||||
final JButton button = new JButton("cancel");
|
||||
button.setName("Cancel");
|
||||
button.addActionListener(e -> this.dispose());
|
||||
return button;
|
||||
}
|
||||
|
||||
private static JLabel createLabel(final String text, final String name) {
|
||||
JLabel label = new JLabel(text);
|
||||
label.setName(name);
|
||||
return label;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package reminderapplication;
|
||||
|
||||
public class Reminder {
|
||||
|
||||
private static String REMINDER_FORMAT = "Reminder Text: %s; Delay: %d; Period: %d;";
|
||||
|
||||
private final String name;
|
||||
private final int delay;
|
||||
private final int period;
|
||||
|
||||
public Reminder(final String name, final int delay, final int period) {
|
||||
this.name = name;
|
||||
this.delay = delay;
|
||||
this.period = period;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getDelay() {
|
||||
return delay;
|
||||
}
|
||||
|
||||
public int getPeriod() {
|
||||
return period;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return REMINDER_FORMAT.formatted(name, delay, period);
|
||||
}
|
||||
}
|
||||
@@ -1,186 +0,0 @@
|
||||
package reminderapplication;
|
||||
|
||||
import static reminderapplication.ConstraintsBuilder.*;
|
||||
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.HeadlessException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
public class ReminderFrame extends JFrame {
|
||||
|
||||
private static Timer TIMER = new Timer();
|
||||
private final TimeReminderApplication reminderApplication;
|
||||
private final JLabel reminderTextLabel;
|
||||
private final JLabel repeatPeriodLabel;
|
||||
private final JLabel setDelayLabel;
|
||||
private final JComboBox<Integer> delay;
|
||||
private final JComboBox<Integer> period;
|
||||
private final JButton cancelButton;
|
||||
private final JButton okButton;
|
||||
private final JTextField textField;
|
||||
private final JLabel delaysLabel;
|
||||
private final JLabel periodLabel;
|
||||
|
||||
public ReminderFrame(TimeReminderApplication reminderApp) throws HeadlessException {
|
||||
this.reminderApplication = reminderApp;
|
||||
textField = createTextField();
|
||||
delay = createDelayComboBox();
|
||||
period = createPeriodComboBox();
|
||||
cancelButton = createCancelButton();
|
||||
okButton = createOkButton();
|
||||
reminderTextLabel = createReminderTextLabel();
|
||||
repeatPeriodLabel = createRepeatPeriodLabel();
|
||||
setDelayLabel = createSetDelayLabel();
|
||||
delaysLabel = createDelaysLabel();
|
||||
periodLabel = createPeriodLabel();
|
||||
configureVisualRepresentation();
|
||||
configureActions();
|
||||
}
|
||||
|
||||
private void configureActions() {
|
||||
createNewReminder();
|
||||
}
|
||||
|
||||
private void configureVisualRepresentation() {
|
||||
configureFrame();
|
||||
setLocationRelativeTo(null);
|
||||
setLayout(new GridBagLayout());
|
||||
add(reminderTextLabel, constraint(0,0));
|
||||
add(repeatPeriodLabel, constraint(1,0));
|
||||
add(setDelayLabel, constraint(2,0));
|
||||
add(textField, constraint(0, 1));
|
||||
add(delay, constraint(1, 1));
|
||||
add(period, constraint(2, 1));
|
||||
add(delaysLabel, constraint(1,3));
|
||||
add(periodLabel, constraint(2,3));
|
||||
add(okButton, constraint(1, 4));
|
||||
add(cancelButton, constraint(2, 4));
|
||||
pack();
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
private void configureFrame() {
|
||||
setTitle("Set Reminder");
|
||||
setName("Set Reminder");
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
}
|
||||
|
||||
private static JLabel createSetDelayLabel() {
|
||||
return createLabel("Set Delay", "Set Delay Label");
|
||||
}
|
||||
|
||||
private static JLabel createRepeatPeriodLabel() {
|
||||
return createLabel("Set Period", "Set Repeat Period Label");
|
||||
}
|
||||
|
||||
private static JLabel createReminderTextLabel() {
|
||||
return createLabel("Reminder Text", "Reminder Text Label");
|
||||
}
|
||||
|
||||
private JLabel createPeriodLabel() {
|
||||
return createLabel("0", "Period label");
|
||||
}
|
||||
|
||||
private JLabel createDelaysLabel() {
|
||||
return createLabel("30", "Delays Label");
|
||||
}
|
||||
|
||||
private JComboBox<Integer> createPeriodComboBox() {
|
||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20}));
|
||||
comboBox.setName("set Period");
|
||||
comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString()));
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private JComboBox<Integer> createDelayComboBox() {
|
||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5}));
|
||||
comboBox.setName("set Delay");
|
||||
comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString()));
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private JTextField createTextField() {
|
||||
final JTextField textField = new JTextField(20);
|
||||
textField.setName("Field");
|
||||
return textField;
|
||||
}
|
||||
|
||||
private JButton createOkButton() {
|
||||
final JButton button = new JButton("ok");
|
||||
button.setName("OK");
|
||||
return button;
|
||||
}
|
||||
|
||||
private void createNewReminder() {
|
||||
|
||||
okButton.addActionListener(e -> this.dispose());
|
||||
okButton.addActionListener(e -> {
|
||||
final int periodInSeconds = getTimeInSeconds(period);
|
||||
final int delayInSeconds = getTimeInSeconds(delay);
|
||||
final Reminder reminder = new Reminder(textField.getText(), delayInSeconds, periodInSeconds);
|
||||
((DefaultListModel<Reminder>) reminderApplication.getReminders()).addElement(reminder);
|
||||
});
|
||||
okButton.addActionListener(e -> scheduleReminder(textField, delay, period));
|
||||
}
|
||||
|
||||
private void scheduleReminder(final JTextField textField, final JComboBox<Integer> delay, final JComboBox<Integer> period) {
|
||||
final int periodInSeconds = getTimeInSeconds(period);
|
||||
if (periodInSeconds == 0)
|
||||
scheduleNonRepeatedReminder(textField, delay);
|
||||
else
|
||||
scheduleRepeatedReminder(textField, delay, period);
|
||||
}
|
||||
|
||||
private void scheduleRepeatedReminder(final JTextField textField, final JComboBox<Integer> delay, final JComboBox<Integer> period) {
|
||||
final int delayInSeconds = getTimeInSeconds(delay) + 200;
|
||||
final int periodInSeconds = getTimeInSeconds(period);
|
||||
final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds);
|
||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds), TimeUnit.SECONDS.toMillis(periodInSeconds));
|
||||
}
|
||||
|
||||
private void scheduleNonRepeatedReminder(final JTextField textField, final JComboBox<Integer> delay) {
|
||||
final int delayInSeconds = getTimeInSeconds(delay);
|
||||
final int periodInSeconds = 0;
|
||||
final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds);
|
||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds));
|
||||
|
||||
}
|
||||
|
||||
private int getTimeInSeconds(final JComboBox<Integer> comboBox) {
|
||||
if (comboBox != null && comboBox.getSelectedItem() != null)
|
||||
return ((Integer) comboBox.getSelectedItem());
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
private TimerTask getTimerTask(final String reminderText, final Integer delayInSeconds, final Integer periodInSeconds) {
|
||||
return new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
new ReminderPopupFrame(reminderApplication, reminderText, delayInSeconds, periodInSeconds);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private JButton createCancelButton() {
|
||||
final JButton button = new JButton("cancel");
|
||||
button.setName("Cancel");
|
||||
button.addActionListener(e -> this.dispose());
|
||||
return button;
|
||||
}
|
||||
|
||||
private static JLabel createLabel(final String text, final String name) {
|
||||
JLabel label = new JLabel(text);
|
||||
label.setName(name);
|
||||
return label;
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
package reminderapplication;
|
||||
|
||||
import static reminderapplication.ConstraintsBuilder.*;
|
||||
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.HeadlessException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
public class ReminderPopupFrame extends JFrame {
|
||||
|
||||
private static final Timer TIMER = new Timer();
|
||||
private final int AUTOMATIC_CLOSE_TIME_IN_SECONDS = 10;
|
||||
private final TimeReminderApplication reminderApplication;
|
||||
private final JLabel reminderTextLabel;
|
||||
private final JLabel repeatPeriodLabel;
|
||||
private final JLabel setDelayLabel;
|
||||
private final JComboBox<Integer> delay;
|
||||
private final JComboBox<Integer> period;
|
||||
private final JButton cancelButton;
|
||||
private final JButton okButton;
|
||||
private final JTextField textField;
|
||||
private final JLabel delaysLabel;
|
||||
private final JLabel periodLabel;
|
||||
|
||||
public ReminderPopupFrame(TimeReminderApplication reminderApp, final String text, final Integer delayInSeconds, final Integer periodInSeconds) throws HeadlessException {
|
||||
this.reminderApplication = reminderApp;
|
||||
textField = createTextField(text);
|
||||
delay = createDelayComboBox(delayInSeconds);
|
||||
period = createPeriodComboBox(periodInSeconds);
|
||||
cancelButton = createCancelButton();
|
||||
okButton = createDisabledOkButton();
|
||||
reminderTextLabel = createReminderTextLabel();
|
||||
repeatPeriodLabel = createRepeatPeriodLabel();
|
||||
setDelayLabel = createSetDelayLabel();
|
||||
delaysLabel = createDelaysLabel();
|
||||
periodLabel = createPeriodLabel();
|
||||
configureVisualRepresentation();
|
||||
configureActions();
|
||||
}
|
||||
|
||||
private void configureActions() {
|
||||
scheduleClosing();
|
||||
}
|
||||
|
||||
private void scheduleClosing() {
|
||||
final TimerTask timerTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
ReminderPopupFrame.this.dispose();
|
||||
}
|
||||
};
|
||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(AUTOMATIC_CLOSE_TIME_IN_SECONDS));
|
||||
}
|
||||
|
||||
private void configureVisualRepresentation() {
|
||||
configureFrame();
|
||||
setLocationRelativeTo(null);
|
||||
setLayout(new GridBagLayout());
|
||||
add(reminderTextLabel, constraint(0,0));
|
||||
add(repeatPeriodLabel, constraint(1,0));
|
||||
add(setDelayLabel, constraint(2,0));
|
||||
add(textField, constraint(0, 1));
|
||||
add(delay, constraint(1, 1));
|
||||
add(period, constraint(2, 1));
|
||||
add(delaysLabel, constraint(1,3));
|
||||
add(periodLabel, constraint(2,3));
|
||||
add(okButton, constraint(1, 4));
|
||||
add(cancelButton, constraint(2, 4));
|
||||
pack();
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
private void configureFrame() {
|
||||
setTitle("Set Reminder");
|
||||
setName("Set Reminder");
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
}
|
||||
|
||||
private static JLabel createSetDelayLabel() {
|
||||
return createLabel("Set Delay", "Set Delay Label");
|
||||
}
|
||||
|
||||
private static JLabel createRepeatPeriodLabel() {
|
||||
return createLabel("Set Period", "Set Repeat Period Label");
|
||||
}
|
||||
|
||||
private static JLabel createReminderTextLabel() {
|
||||
return createLabel("Reminder Text", "Reminder Text Label");
|
||||
}
|
||||
|
||||
private JLabel createPeriodLabel() {
|
||||
return createLabel("0", "Period label");
|
||||
}
|
||||
|
||||
private JLabel createDelaysLabel() {
|
||||
return createLabel("30", "Delays Label");
|
||||
}
|
||||
|
||||
private JComboBox<Integer> createPeriodComboBox(final Integer periodInSeconds) {
|
||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20}));
|
||||
comboBox.setName("set Period");
|
||||
comboBox.setSelectedItem(periodInSeconds);
|
||||
comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString()));
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private JComboBox<Integer> createDelayComboBox(Integer delay) {
|
||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5}));
|
||||
comboBox.setSelectedItem(delay);
|
||||
comboBox.setName("set Delay");
|
||||
comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString()));
|
||||
return comboBox;
|
||||
}
|
||||
|
||||
private JTextField createTextField(final String text) {
|
||||
final JTextField textField = new JTextField(20);
|
||||
textField.setName("Field");
|
||||
textField.setText(text);
|
||||
return textField;
|
||||
}
|
||||
|
||||
private JButton createDisabledOkButton() {
|
||||
final JButton button = new JButton("ok");
|
||||
button.setName("OK");
|
||||
button.setEnabled(false);
|
||||
return button;
|
||||
}
|
||||
|
||||
private JButton createCancelButton() {
|
||||
final JButton button = new JButton("cancel");
|
||||
button.setName("Cancel");
|
||||
button.addActionListener(e -> this.dispose());
|
||||
return button;
|
||||
}
|
||||
|
||||
private static JLabel createLabel(final String text, final String name) {
|
||||
JLabel label = new JLabel(text);
|
||||
label.setName(name);
|
||||
return label;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -48,7 +48,6 @@
|
||||
|
||||
<properties>
|
||||
<maven.compiler.release>14</maven.compiler.release>
|
||||
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
|
||||
<surefire.plugin.version>3.0.0-M3</surefire.plugin.version>
|
||||
</properties>
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
|
||||
<properties>
|
||||
<maven.compiler.release>15</maven.compiler.release>
|
||||
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
|
||||
<surefire.plugin.version>3.0.0-M3</surefire.plugin.version>
|
||||
</properties>
|
||||
|
||||
|
||||
@@ -7,3 +7,4 @@
|
||||
- [Random Number Generators in Java 17](https://www.baeldung.com/java-17-random-number-generators)
|
||||
- [Sealed Classes and Interfaces in Java](https://www.baeldung.com/java-sealed-classes-interfaces)
|
||||
- [Migrate From Java 8 to Java 17](https://www.baeldung.com/java-migrate-8-to-17)
|
||||
- [Format Multiple ‘or’ Conditions in an If Statement in Java](https://www.baeldung.com/java-multiple-or-conditions-if-statement)
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
1
core-java-modules/core-java-21/README.md
Normal file
1
core-java-modules/core-java-21/README.md
Normal file
@@ -0,0 +1 @@
|
||||
## Relevant Articles
|
||||
34
core-java-modules/core-java-21/pom.xml
Normal file
34
core-java-modules/core-java-21/pom.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?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>
|
||||
<artifactId>core-java-21</artifactId>
|
||||
<name>core-java-21</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung.core-java-modules</groupId>
|
||||
<artifactId>core-java-modules</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<!-- <build>-->
|
||||
<!-- <plugins>-->
|
||||
<!-- <plugin>-->
|
||||
<!-- <groupId>org.apache.maven.plugins</groupId>-->
|
||||
<!-- <artifactId>maven-compiler-plugin</artifactId>-->
|
||||
<!-- <configuration>-->
|
||||
<!-- <source>{maven.compiler.source.version}</source>-->
|
||||
<!-- <target>{maven.compiler.target.version}</target>-->
|
||||
<!-- </configuration>-->
|
||||
<!-- </plugin>-->
|
||||
<!-- </plugins>-->
|
||||
<!-- </build>-->
|
||||
|
||||
<!-- <properties>-->
|
||||
<!-- <maven.compiler.source.version>21</maven.compiler.source.version>-->
|
||||
<!-- <maven.compiler.target.version>21</maven.compiler.target.version>-->
|
||||
<!-- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>-->
|
||||
<!-- </properties>-->
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.sequenced.collections;
|
||||
|
||||
/*
|
||||
interface SequencedCollection<E> extends Collection<E> {
|
||||
// new method
|
||||
SequencedCollection<E> reversed();
|
||||
// methods promoted from Deque
|
||||
void addFirst(E);
|
||||
void addLast(E);
|
||||
E getFirst();
|
||||
E getLast();
|
||||
E removeFirst();
|
||||
E removeLast();
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.baeldung.sequenced.collections;
|
||||
|
||||
/*
|
||||
interface SequencedMap<K,V> extends Map<K,V> {
|
||||
// new methods
|
||||
SequencedMap<K,V> reversed();
|
||||
SequencedSet<K> sequencedKeySet();
|
||||
SequencedCollection<V> sequencedValues();
|
||||
SequencedSet<Entry<K,V>> sequencedEntrySet();
|
||||
V putFirst(K, V);
|
||||
V putLast(K, V);
|
||||
// methods promoted from NavigableMap
|
||||
Entry<K, V> firstEntry();
|
||||
Entry<K, V> lastEntry();
|
||||
Entry<K, V> pollFirstEntry();
|
||||
Entry<K, V> pollLastEntry();
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.baeldung.sequenced.collections;
|
||||
|
||||
/*
|
||||
interface SequencedSet<E> extends Set<E>, SequencedCollection<E> {
|
||||
SequencedSet<E> reversed(); // covariant override
|
||||
}
|
||||
*/
|
||||
@@ -152,7 +152,6 @@
|
||||
<awaitility.version>4.0.2</awaitility.version>
|
||||
<maven.compiler.source>1.9</maven.compiler.source>
|
||||
<maven.compiler.target>1.9</maven.compiler.target>
|
||||
<maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -12,3 +12,4 @@ This module contains articles about Java 9 core features
|
||||
- [Private Methods in Java Interfaces](https://www.baeldung.com/java-interface-private-methods)
|
||||
- [Java Scanner useDelimiter with Examples](https://www.baeldung.com/java-scanner-usedelimiter)
|
||||
- [Is There a Destructor in Java?](https://www.baeldung.com/java-destructor)
|
||||
- [Java 9 Migration Issues and Resolutions](https://www.baeldung.com/java-9-migration-issue)
|
||||
@@ -46,6 +46,11 @@
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>${commons-io.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.xml.bind</groupId>
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
<version>${javax.xml.bind.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -58,6 +63,9 @@
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
<compilerArgs>
|
||||
<arg>--add-exports=java.base/com.sun.crypto.provider=ALL-UNNAMED</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
@@ -74,6 +82,7 @@
|
||||
<awaitility.version>1.7.0</awaitility.version>
|
||||
<maven.compiler.source>1.9</maven.compiler.source>
|
||||
<maven.compiler.target>1.9</maven.compiler.target>
|
||||
<javax.xml.bind.version>2.4.0-b180725.0427</javax.xml.bind.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -1,15 +1,16 @@
|
||||
package com.baeldung.prejpms;
|
||||
package com.baeldung.java9.prejpms;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.lang.StackWalker.Option;
|
||||
import java.lang.StackWalker.StackFrame;
|
||||
import com.sun.crypto.provider.SunJCE;
|
||||
import java.util.Base64;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.Marshaller;
|
||||
|
||||
import com.sun.crypto.provider.SunJCE;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.baeldung.prejpms;
|
||||
package com.baeldung.java9.prejpms;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
@@ -8,3 +8,5 @@ This module contains articles about arrays conversion in Java
|
||||
- [Convert a Byte Array to a Numeric Representation in Java](https://www.baeldung.com/java-byte-array-to-number)
|
||||
- [Converting a String Array Into an int Array in Java](https://www.baeldung.com/java-convert-string-array-to-int-array)
|
||||
- [Convert Java Array to Iterable](https://www.baeldung.com/java-array-convert-to-iterable)
|
||||
- [Converting an int[] to HashSet in Java](https://www.baeldung.com/java-converting-int-array-to-hashset)
|
||||
- [Convert an ArrayList of String to a String Array in Java](https://www.baeldung.com/java-convert-string-arraylist-array)
|
||||
|
||||
@@ -20,5 +20,4 @@
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -13,3 +13,5 @@ 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)
|
||||
- [Find the Middle Element of an Array in Java](https://www.baeldung.com/java-array-middle-item)
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.baeldung.arraymiddle;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
public class MiddleOfArray {
|
||||
int[] middleOfArray(int[] array) {
|
||||
if (ObjectUtils.isEmpty(array) || array.length < 3)
|
||||
return array;
|
||||
int n = array.length;
|
||||
int mid = n / 2;
|
||||
if (n % 2 == 0) {
|
||||
int mid2 = mid - 1;
|
||||
return new int[] { array[mid2], array[mid] };
|
||||
} else {
|
||||
return new int[] { array[mid] };
|
||||
}
|
||||
}
|
||||
|
||||
int[] middleOfArrayWithStartEndNaive(int[] array, int start, int end) {
|
||||
int mid = (start + end) / 2;
|
||||
int n = end - start;
|
||||
if (n % 2 == 0) {
|
||||
int mid2 = mid - 1;
|
||||
return new int[] { array[mid2], array[mid] };
|
||||
} else {
|
||||
return new int[] { array[mid] };
|
||||
}
|
||||
}
|
||||
|
||||
int[] middleOfArrayWithStartEnd(int[] array, int start, int end) {
|
||||
int mid = start + (end - start) / 2;
|
||||
int n = end - start;
|
||||
if (n % 2 == 0) {
|
||||
int mid2 = mid - 1;
|
||||
return new int[] { array[mid2], array[mid] };
|
||||
} else {
|
||||
return new int[] { array[mid] };
|
||||
}
|
||||
}
|
||||
|
||||
int[] middleOfArrayWithStartEndBitwise(int[] array, int start, int end) {
|
||||
int mid = (start + end) >>> 1;
|
||||
int n = end - start;
|
||||
if (n % 2 == 0) {
|
||||
int mid2 = mid - 1;
|
||||
return new int[] { array[mid2], array[mid] };
|
||||
} else {
|
||||
return new int[] { array[mid] };
|
||||
}
|
||||
}
|
||||
|
||||
int medianOfArray(int[] array, int start, int end) {
|
||||
Arrays.sort(array); // for safety. This can be ignored
|
||||
int mid = (start + end) >>> 1;
|
||||
int n = end - start;
|
||||
if (n % 2 == 0) {
|
||||
int mid2 = mid - 1;
|
||||
return (array[mid2] + array[mid]) / 2;
|
||||
} else {
|
||||
return array[mid];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.baeldung.arraysums;
|
||||
|
||||
public class SumArraysUsingForEach {
|
||||
|
||||
public static int[] sumOfTwoArrays(int[] arr1, int[] arr2) {
|
||||
int[] arr3 = new int[arr1.length];
|
||||
int counter = 0;
|
||||
for (int num1 : arr1) {
|
||||
arr3[counter] = num1 + arr2[counter];
|
||||
counter++;
|
||||
}
|
||||
return arr3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.arraysums;
|
||||
|
||||
public class SumArraysUsingForLoop {
|
||||
|
||||
public static int[] sumOfTwoArrays(int[] arr1, int[] arr2) {
|
||||
int[] arr3 = new int[arr1.length];
|
||||
for (int i = 0; i < arr1.length; i++) {
|
||||
arr3[i] = arr1[i] + arr2[i];
|
||||
}
|
||||
return arr3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.baeldung.arraysums;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class SumArraysUsingStreams {
|
||||
|
||||
public static int[] sumOfTwoArrays(int[] arr1, int[] arr2) {
|
||||
IntStream range = IntStream.range(0, Math.min(arr1.length, arr2.length));
|
||||
IntStream stream3 = range.map(i -> arr1[i] + arr2[i]);
|
||||
int[] arr3 = stream3.toArray();
|
||||
return arr3;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.baeldung.arraymiddle;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MiddleOfArrayUnitTest {
|
||||
|
||||
@Test
|
||||
public void givenArrayOfEvenLength_whenMiddleOfArray_thenReturn2Values() {
|
||||
int[] array = new int[100];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = i + 1;
|
||||
}
|
||||
int[] expectedMidArray = { 50, 51 };
|
||||
MiddleOfArray middleOfArray = new MiddleOfArray();
|
||||
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArray(array));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenArrayOfEdgeCaseLength_whenMiddleOfArray_thenReturn2Values() {
|
||||
int[] array = new int[0];
|
||||
int[] expectedMidArray = new int[0];
|
||||
MiddleOfArray middleOfArray = new MiddleOfArray();
|
||||
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArray(array));
|
||||
|
||||
array = new int[] { 1, 2 };
|
||||
expectedMidArray = new int[] { 1, 2 };
|
||||
|
||||
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArray(array));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenArrayOfOddLength_whenMiddleOfArray_thenReturnMid() {
|
||||
int[] array = new int[99];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = i + 1;
|
||||
}
|
||||
int[] expectedMidArray = { 50 };
|
||||
MiddleOfArray middleOfArray = new MiddleOfArray();
|
||||
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArray(array));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenArrayWithStartAndEnd_whenMiddleOfArray_thenReturnMid() {
|
||||
int[] array = new int[100];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = i + 1;
|
||||
}
|
||||
int[] expectedMidArray = { 58 };
|
||||
MiddleOfArray middleOfArray = new MiddleOfArray();
|
||||
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArrayWithStartEndNaive(array, 55, 60));
|
||||
|
||||
expectedMidArray = new int[] { 58, 59 };
|
||||
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArrayWithStartEndNaive(array, 56, 60));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenArrayWithStartAndEndOptimized_whenMiddleOfArray_thenReturnMid() {
|
||||
int[] array = new int[100];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = i + 1;
|
||||
}
|
||||
int[] expectedMidArray = { 78 };
|
||||
MiddleOfArray middleOfArray = new MiddleOfArray();
|
||||
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArrayWithStartEnd(array, 55, 100));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenArrayWithStartAndEndBitwise_whenMiddleOfArray_thenReturnMid() {
|
||||
int[] array = new int[100];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = i + 1;
|
||||
}
|
||||
int[] expectedMidArray = { 78 };
|
||||
MiddleOfArray middleOfArray = new MiddleOfArray();
|
||||
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArrayWithStartEndBitwise(array, 55, 100));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenArrayWithStartAndEnd_whenMedianOfArray_thenReturnMid() {
|
||||
int[] array = new int[100];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = i + 1;
|
||||
}
|
||||
int expectMedian = 50;
|
||||
MiddleOfArray middleOfArray = new MiddleOfArray();
|
||||
Assert.assertEquals(expectMedian, middleOfArray.medianOfArray(array, 0, 100));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.baeldung.arraysums;
|
||||
|
||||
import com.baeldung.arraysums.SumArraysUsingForEach;
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class SumArraysUsingForEachUnitTest {
|
||||
|
||||
@Test
|
||||
public void sumOfTwoArraysUsingForEach_GivenTwoEqualSizedIntArrays_ReturnsCorrectSumArray() {
|
||||
int[] arr1 = { 4, 5, 1, 6, 4, 15 };
|
||||
int[] arr2 = { 3, 5, 6, 1, 9, 6 };
|
||||
int[] expected = { 7, 10, 7, 7, 13, 21 };
|
||||
assertArrayEquals(expected, SumArraysUsingForEach.sumOfTwoArrays(arr1, arr2));
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user