Merge branch 'eugenp:master' into BAEL-7618
This commit is contained in:
@@ -7,4 +7,5 @@
|
||||
- [Rotate Arrays in Java](https://www.baeldung.com/java-rotate-arrays)
|
||||
- [Find Missing Number From a Given Array in Java](https://www.baeldung.com/java-array-find-missing-number)
|
||||
- [Calculate Weighted Mean in Java](https://www.baeldung.com/java-compute-weighted-average)
|
||||
- [Check if Two Strings Are Rotations of Each Other](https://www.baeldung.com/java-string-check-strings-rotations)
|
||||
- More articles: [[<-- prev]](/algorithms-miscellaneous-6)
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
<bval.version>2.0.6</bval.version>
|
||||
<javax.validation.validation-api.version>2.0.1.Final</javax.validation.validation-api.version>
|
||||
<meecrowave-junit.version>1.2.15</meecrowave-junit.version>
|
||||
<okhttp.version>4.12.0</okhttp.version>
|
||||
<okhttp.version>5.0.0-alpha.12</okhttp.version>
|
||||
<meecrowave-jpa.version>1.2.15</meecrowave-jpa.version>
|
||||
<meecrowave-core.version>1.2.15</meecrowave-core.version>
|
||||
<meecrowave-maven-plugin.version>1.2.15</meecrowave-maven-plugin.version>
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
## Relevant Articles
|
||||
- [Deprecate Finalization in Java 18](https://www.baeldung.com/java-18-deprecate-finalization)
|
||||
- [Simple Web Server in Java 18](https://www.baeldung.com/simple-web-server-java-18)
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
<version>${guava.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -29,4 +29,4 @@
|
||||
<properties>
|
||||
<vavr.version>0.10.4</vavr.version>
|
||||
</properties>
|
||||
</project>
|
||||
</project>
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package com.baeldung.modifyandprint;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
public class ModifyAndPrintListElementsUnitTest {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(ModifyAndPrintListElementsUnitTest.class);
|
||||
|
||||
@Test
|
||||
void whenPrintingInForEach_thenListIsPrinted() {
|
||||
List<String> theList = Lists.newArrayList("Kai", "Liam", "Eric", "Kevin");
|
||||
theList.forEach(element -> log.info(element));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenUsingModifyAndPrintingSeparately_thenListIsModifiedAndPrinted() {
|
||||
List<String> theList = Lists.newArrayList("Kai", "Liam", "Eric", "Kevin");
|
||||
theList.replaceAll(element -> element.toUpperCase());
|
||||
theList.forEach(element -> log.info(element));
|
||||
assertEquals(List.of("KAI", "LIAM", "ERIC", "KEVIN"), theList);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPrintingInMap_thenStreamIsModifiedAndPrinted() {
|
||||
List<String> theList = List.of("Kai", "Liam", "Eric", "Kevin");
|
||||
List<String> newList = theList.stream()
|
||||
.map(element -> {
|
||||
String newElement = element.toUpperCase();
|
||||
log.info(newElement);
|
||||
return newElement;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(List.of("KAI", "LIAM", "ERIC", "KEVIN"), newList);
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenPrintingInPeek_thenStreamIsModifiedAndPrinted() {
|
||||
List<String> theList = List.of("Kai", "Liam", "Eric", "Kevin");
|
||||
List<String> newList = theList.stream()
|
||||
.map(element -> element.toUpperCase())
|
||||
.peek(element-> log.info(element))
|
||||
.collect(Collectors.toList());
|
||||
assertEquals(List.of("KAI", "LIAM", "ERIC", "KEVIN"), newList);
|
||||
}
|
||||
}
|
||||
@@ -8,4 +8,5 @@
|
||||
- [How to Sort LinkedHashMap by Values in Java](https://www.baeldung.com/java-sort-linkedhashmap-using-values)
|
||||
- [How to Increment a Map Value in Java](https://www.baeldung.com/java-increment-map-value)
|
||||
- [Collect Stream of entrySet() to a LinkedHashMap](https://www.baeldung.com/java-linkedhashmap-entryset-stream)
|
||||
- [How to Pretty-Print a Map in Java](https://www.baeldung.com/java-map-pretty-print)
|
||||
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-6)
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>32.1.1-jre</version>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -9,3 +9,5 @@
|
||||
- [Parallelize for Loop in Java](https://www.baeldung.com/java-for-loop-parallel)
|
||||
- [How to Effectively Unit Test CompletableFuture](https://www.baeldung.com/java-completablefuture-unit-test)
|
||||
- [How to Collect All Results and Handle Exceptions With CompletableFuture in a Loop](https://www.baeldung.com/java-completablefuture-collect-results-handle-exceptions)
|
||||
- [CompletableFuture runAsync() vs. supplyAsync() in Java](https://www.baeldung.com/java-completablefuture-runasync-supplyasync)
|
||||
- [Difference Between thenApply() and thenApplyAsync() in CompletableFuture](https://www.baeldung.com/java-completablefuture-thenapply-thenapplyasync)
|
||||
|
||||
@@ -17,4 +17,5 @@
|
||||
- [Validate if a String Is a Valid Geo Coordinate](https://www.baeldung.com/java-geo-coordinates-validation)
|
||||
- [Rotate a Vertex Around a Certain Point in Java](https://www.baeldung.com/java-rotate-vertex-around-point)
|
||||
- [Calculating the Power of Any Number in Java Without Using Math pow() Method](https://www.baeldung.com/java-calculating-the-power-without-math-pow)
|
||||
- [Solving Rod Cutting Problem in Java](https://www.baeldung.com/java-rod-cutting-problem)
|
||||
- More articles: [[<-- Prev]](/core-java-modules/core-java-lang-math-2)
|
||||
|
||||
+9
-7
@@ -1,19 +1,21 @@
|
||||
package com.baeldung.outofmemoryerror;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class OutOfMemoryGCLimitExceed {
|
||||
public static void addRandomDataToMap() {
|
||||
Map<Integer, String> dataMap = new HashMap<>();
|
||||
Random r = new Random();
|
||||
|
||||
public static final Random RANDOM = new Random();
|
||||
|
||||
public static void addRandomDataToList() {
|
||||
List<String> dataList = new LinkedList<>();
|
||||
while (true) {
|
||||
dataMap.put(r.nextInt(), String.valueOf(r.nextInt()));
|
||||
dataList.add(String.valueOf(RANDOM.nextInt()));
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
OutOfMemoryGCLimitExceed.addRandomDataToMap();
|
||||
OutOfMemoryGCLimitExceed.addRandomDataToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
## Relevant Articles
|
||||
- [Java 8 Stream Operation on the Empty List](https://www.baeldung.com/java-empty-list-stream-ops)
|
||||
- [Get a Range of Items from a Stream in Java](https://www.baeldung.com/java-stream-get-range)
|
||||
|
||||
|
||||
@@ -6,3 +6,4 @@ This module contains articles about string-related algorithms.
|
||||
- [Rotating a Java String By n Characters](https://www.baeldung.com/java-rotate-string-by-n-characters)
|
||||
- [Remove Characters From a String That Are in the Other String](https://www.baeldung.com/java-strings-character-difference)
|
||||
- [Run-Length Encoding and Decoding in Java](https://www.baeldung.com/java-rle-compression)
|
||||
- [Check if a String Is Equal to Its Mirror Reflection](https://www.baeldung.com/java-string-mirror-image-test)
|
||||
|
||||
@@ -1,2 +1,6 @@
|
||||
### Relevant Articles:
|
||||
- [Count Uppercase and Lowercase Letters in a String](https://www.baeldung.com/java-string-count-letters-uppercase-lowercase)
|
||||
- [Find The Largest Number in a String](https://www.baeldung.com/java-find-largest-number-string)
|
||||
- [Check if String is Base64 Encoded](https://www.baeldung.com/java-check-string-base64-encoding)
|
||||
- [Find an Unique Email Address in a List](https://www.baeldung.com/java-find-unique-email-address)
|
||||
- [Get First n Characters in a String in Java](https://www.baeldung.com/get-first-n-characters-in-a-string-in-java)
|
||||
|
||||
-83
@@ -1,83 +0,0 @@
|
||||
package com.baeldung.uuid;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Methods are called by reflection in the unit test
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class UUIDPositiveLongGenerator {
|
||||
public long getLeastSignificantBits() {
|
||||
return Math.abs(UUID.randomUUID().getLeastSignificantBits());
|
||||
}
|
||||
|
||||
public long getMostSignificantBits() {
|
||||
return Math.abs(UUID.randomUUID().getMostSignificantBits());
|
||||
}
|
||||
|
||||
public long combineByteBuffer() {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
|
||||
bb.putLong(uuid.getMostSignificantBits());
|
||||
bb.putLong(uuid.getLeastSignificantBits());
|
||||
bb.rewind();
|
||||
return Math.abs(bb.getLong());
|
||||
}
|
||||
|
||||
public long combineBitwise() {
|
||||
UUID uniqueUUID = UUID.randomUUID();
|
||||
long mostSignificantBits = uniqueUUID.getMostSignificantBits();
|
||||
long leastSignificantBits = uniqueUUID.getLeastSignificantBits();
|
||||
return Math.abs((mostSignificantBits << 32) | (leastSignificantBits & 0xFFFFFFFFL));
|
||||
}
|
||||
|
||||
public long combineDirect() {
|
||||
UUID uniqueUUID = UUID.randomUUID();
|
||||
long mostSignificantBits = uniqueUUID.getMostSignificantBits();
|
||||
long leastSignificantBits = uniqueUUID.getLeastSignificantBits();
|
||||
return Math.abs(mostSignificantBits ^ (leastSignificantBits >> 1));
|
||||
}
|
||||
|
||||
public long combinePermutation() {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
long mostSigBits = uuid.getMostSignificantBits();
|
||||
long leastSigBits = uuid.getLeastSignificantBits();
|
||||
byte[] uuidBytes = new byte[16];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
uuidBytes[i] = (byte) (mostSigBits >>> (8 * (7 - i)));
|
||||
uuidBytes[i + 8] = (byte) (leastSigBits >>> (8 * (7 - i)));
|
||||
}
|
||||
|
||||
long result = 0;
|
||||
for (byte b : uuidBytes) {
|
||||
result = (result << 8) | (b & 0xFF);
|
||||
}
|
||||
return Math.abs(result);
|
||||
}
|
||||
|
||||
public long combineWithSecureRandom() {
|
||||
UUID uniqueUUID = UUID.randomUUID();
|
||||
SecureRandom secureRandom = new SecureRandom();
|
||||
long randomBits = secureRandom.nextLong();
|
||||
|
||||
long mostSignificantBits = uniqueUUID.getMostSignificantBits() ^ randomBits;
|
||||
long leastSignificantBits = uniqueUUID.getLeastSignificantBits();
|
||||
|
||||
return Math.abs((mostSignificantBits << 32) | (leastSignificantBits & 0xFFFFFFFFL));
|
||||
}
|
||||
|
||||
public long combineWithNanoTime() {
|
||||
UUID uniqueUUID = UUID.randomUUID();
|
||||
long nanoTime = System.nanoTime();
|
||||
|
||||
long mostSignificantBits = uniqueUUID.getMostSignificantBits() ^ nanoTime;
|
||||
long leastSignificantBits = uniqueUUID.getLeastSignificantBits();
|
||||
|
||||
return Math.abs((mostSignificantBits << 32) | (leastSignificantBits & 0xFFFFFFFFL));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+7
-28
@@ -2,42 +2,21 @@ package com.baeldung.uuid;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class UUIDPositiveLongGeneratorUnitTest {
|
||||
|
||||
private final UUIDPositiveLongGenerator uuidLongGenerator = new UUIDPositiveLongGenerator();
|
||||
|
||||
private final Set<Long> uniqueValues = new HashSet<>();
|
||||
|
||||
@Test
|
||||
void whenForeachMethods_thenRetryWhileNotUnique() throws Exception {
|
||||
for (Method method : uuidLongGenerator.getClass().getDeclaredMethods()) {
|
||||
long uniqueValue;
|
||||
do uniqueValue = (long) method.invoke(uuidLongGenerator); while (!isUnique(uniqueValue));
|
||||
assertThat(uniqueValue).isPositive();
|
||||
}
|
||||
public void whenGetMostSignificantBits_thenAssertPositive() {
|
||||
long randomPositiveLong = Math.abs(UUID.randomUUID().getMostSignificantBits());
|
||||
assertThat(randomPositiveLong).isNotNegative();
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenGivenLongValue_thenCheckUniqueness() {
|
||||
long uniqueValue = generateUniqueLong();
|
||||
assertThat(uniqueValue).isPositive();
|
||||
public void whenGetLeastSignificantBits_thenAssertPositive() {
|
||||
long randomPositiveLong = Math.abs(UUID.randomUUID().getLeastSignificantBits());
|
||||
assertThat(randomPositiveLong).isNotNegative();
|
||||
}
|
||||
|
||||
private long generateUniqueLong() {
|
||||
long uniqueValue;
|
||||
do uniqueValue = uuidLongGenerator.combineBitwise(); while (!isUnique(uniqueValue));
|
||||
return uniqueValue;
|
||||
}
|
||||
|
||||
private boolean isUnique(long value) {
|
||||
// Implement uniqueness checking logic, for example, by checking in the database
|
||||
return uniqueValues.add(value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
|
||||
<properties>
|
||||
<exchange-rate-api.version>1.0.0-SNAPSHOT</exchange-rate-api.version>
|
||||
<okhttp.version>4.12.0</okhttp.version>
|
||||
<okhttp.version>5.0.0-alpha.12</okhttp.version>
|
||||
<javax.json.bind-api.version>1.0</javax.json.bind-api.version>
|
||||
<yasson.version>1.0.1</yasson.version>
|
||||
<javax.json.version>1.1.2</javax.json.version>
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<guava.version>33.0.0-jre</guava.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<artifactId>parent-boot-3</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../../parent-boot-2</relativePath>
|
||||
<relativePath>../../parent-boot-3</relativePath>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
#
|
||||
# docker build -f src/main/docker/Dockerfile .
|
||||
|
||||
FROM adoptopenjdk:11-jre-hotspot as builder
|
||||
FROM openjdk:17-jdk-alpine as builder
|
||||
ARG JAR_FILE=target/*.jar
|
||||
COPY ${JAR_FILE} application.jar
|
||||
RUN java -Djarmode=layertools -jar application.jar extract
|
||||
|
||||
FROM adoptopenjdk:11-jre-hotspot
|
||||
FROM openjdk:17-jdk-alpine
|
||||
COPY --from=builder dependencies/ ./
|
||||
COPY --from=builder spring-boot-loader/ ./
|
||||
COPY --from=builder internal-dependencies/ ./
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
# To run with profiles:
|
||||
# docker run -e "SPRING_PROFILES_ACTIVE=test1,test2,test3" docker-with-spring-profile:latest
|
||||
|
||||
FROM openjdk:11
|
||||
FROM openjdk:17-jdk-alpine
|
||||
COPY target/*.jar app.jar
|
||||
ENTRYPOINT ["java", "-jar", "/app.jar"]
|
||||
|
||||
@@ -8,3 +8,4 @@ This module contains articles about Jackson custom conversions.
|
||||
- [Serialize Only Fields That Meet a Custom Criteria With Jackson](https://www.baeldung.com/jackson-serialize-field-custom-criteria)
|
||||
- [Calling Default Serializer from Custom Serializer in Jackson](https://www.baeldung.com/jackson-call-default-serializer-from-custom-serializer)
|
||||
- [OffsetDateTime Serialization With Jackson](https://www.baeldung.com/java-jackson-offsetdatetime)
|
||||
- [Create JavaType From Class with Jackson](https://www.baeldung.com/java-javatype-class-jackson)
|
||||
|
||||
@@ -11,3 +11,4 @@ This module contains articles about IO data processing libraries.
|
||||
- [Introduction To Docx4J](https://www.baeldung.com/docx4j)
|
||||
- [Breaking YAML Strings Over Multiple Lines](https://www.baeldung.com/yaml-multi-line)
|
||||
- [Different Serialization Approaches for Java](https://www.baeldung.com/java-serialization-approaches)
|
||||
- [A Guide to etcd](https://www.baeldung.com/java-etcd-guide)
|
||||
|
||||
@@ -109,9 +109,9 @@
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<okhttp.version>4.12.0</okhttp.version>
|
||||
<okhttp.version>5.0.0-alpha.12</okhttp.version>
|
||||
<gson.version>2.10.1</gson.version>
|
||||
<mockwebserver.version>4.9.1</mockwebserver.version>
|
||||
<mockwebserver.version>5.0.0-alpha.12</mockwebserver.version>
|
||||
<jetty.httpclient.version>1.0.3</jetty.httpclient.version>
|
||||
<jetty.server.version>9.4.19.v20190610</jetty.server.version>
|
||||
<rxjava2.version>2.2.11</rxjava2.version>
|
||||
|
||||
+2
-9
@@ -52,17 +52,10 @@ public class BinaryFileDownloaderUnitTest {
|
||||
verify(writer).close();
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void givenUrlAndResponseWithNullBody_whenDownload_thenExpectIllegalStateException() throws Exception {
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void givenUrlAndResponseWithNullBody_whenDownload_thenExpectNullPointerException() throws Exception {
|
||||
String url = "http://example.com/file";
|
||||
Call call = mock(Call.class);
|
||||
when(client.newCall(any(Request.class))).thenReturn(call);
|
||||
Response response = createResponse(url, null);
|
||||
when(call.execute()).thenReturn(response);
|
||||
|
||||
tested.download(url);
|
||||
|
||||
verify(writer, times(0)).write(any(InputStream.class), anyDouble());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -13,13 +13,11 @@
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<!-- Dependencies for response decoder with okhttp -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>${com.squareup.okhttp3.version}</version>
|
||||
</dependency>
|
||||
<!-- Dependencies for google http client -->
|
||||
<dependency>
|
||||
<groupId>com.google.http-client</groupId>
|
||||
<artifactId>google-http-client</artifactId>
|
||||
@@ -30,7 +28,6 @@
|
||||
<artifactId>google-http-client-jackson2</artifactId>
|
||||
<version>${googleclient.version}</version>
|
||||
</dependency>
|
||||
<!-- Retrofit -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.retrofit2</groupId>
|
||||
<artifactId>retrofit</artifactId>
|
||||
@@ -46,7 +43,6 @@
|
||||
<artifactId>adapter-rxjava</artifactId>
|
||||
<version>${retrofit.version}</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.asynchttpclient/async-http-client -->
|
||||
<dependency>
|
||||
<groupId>org.asynchttpclient</groupId>
|
||||
<artifactId>async-http-client</artifactId>
|
||||
@@ -68,7 +64,6 @@
|
||||
<artifactId>unirest-java</artifactId>
|
||||
<version>${unirest.version}</version>
|
||||
</dependency>
|
||||
<!-- javalin -->
|
||||
<dependency>
|
||||
<groupId>io.javalin</groupId>
|
||||
<artifactId>javalin</artifactId>
|
||||
@@ -105,7 +100,7 @@
|
||||
<properties>
|
||||
<gson.version>2.10.1</gson.version>
|
||||
<httpclient.version>4.5.3</httpclient.version>
|
||||
<com.squareup.okhttp3.version>4.12.0</com.squareup.okhttp3.version>
|
||||
<com.squareup.okhttp3.version>5.0.0-alpha.12</com.squareup.okhttp3.version>
|
||||
<googleclient.version>1.23.0</googleclient.version>
|
||||
<async.http.client.version>2.2.0</async.http.client.version>
|
||||
<retrofit.version>2.3.0</retrofit.version>
|
||||
|
||||
@@ -30,6 +30,12 @@
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<version>${jetty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -73,6 +79,7 @@
|
||||
<properties>
|
||||
<jetty.version>9.4.27.v20200227</jetty.version>
|
||||
<alpn.version>8.1.11.v20170118</alpn.version>
|
||||
<netty.version>4.1.104.Final</netty.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
package com.baeldung.netty.customhandlersandlisteners;
|
||||
|
||||
import java.util.Scanner;
|
||||
|
||||
import com.baeldung.netty.customhandlersandlisteners.handler.ClientEventHandler;
|
||||
import com.baeldung.netty.customhandlersandlisteners.listener.ChannelInfoListener;
|
||||
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.string.StringDecoder;
|
||||
import io.netty.handler.codec.string.StringEncoder;
|
||||
|
||||
public class ChatClientMain {
|
||||
|
||||
private static final String SYSTEM_USER = System.getProperty("user.name");
|
||||
private static String user;
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventLoopGroup group = new NioEventLoopGroup();
|
||||
try (Scanner scanner = new Scanner(System.in)) {
|
||||
Bootstrap bootstrap = new Bootstrap();
|
||||
bootstrap.group(group)
|
||||
.channel(NioSocketChannel.class)
|
||||
.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
public void initChannel(SocketChannel channel) throws Exception {
|
||||
channel.pipeline()
|
||||
.addFirst(new StringDecoder(), new ClientEventHandler(), new StringEncoder());
|
||||
}
|
||||
});
|
||||
|
||||
ChannelFuture future = bootstrap.connect(ChatServerMain.HOST, ChatServerMain.PORT)
|
||||
.sync();
|
||||
|
||||
future.addListener(new ChannelInfoListener("connected to server"));
|
||||
Channel channel = future.sync()
|
||||
.channel();
|
||||
|
||||
messageLoop(scanner, channel);
|
||||
|
||||
channel.close();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
Thread.currentThread().interrupt();
|
||||
} finally {
|
||||
group.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
|
||||
private static void messageLoop(Scanner scanner, Channel channel) throws InterruptedException {
|
||||
Thread.sleep(50);
|
||||
|
||||
if (user == null) {
|
||||
System.out.printf("your name [%s]: ", SYSTEM_USER);
|
||||
user = scanner.nextLine();
|
||||
if (user.isEmpty())
|
||||
user = SYSTEM_USER;
|
||||
}
|
||||
|
||||
System.out.print("> ");
|
||||
while (scanner.hasNext()) {
|
||||
String message = scanner.nextLine();
|
||||
if (message.equals("exit"))
|
||||
break;
|
||||
|
||||
ChannelFuture sent = channel.writeAndFlush(user + ";" + message);
|
||||
sent.addListener(new ChannelInfoListener("message sent"));
|
||||
sent.addListener(future -> System.out.print("> "));
|
||||
}
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
package com.baeldung.netty.customhandlersandlisteners;
|
||||
|
||||
import com.baeldung.netty.customhandlersandlisteners.handler.ServerEventHandler;
|
||||
import com.baeldung.netty.customhandlersandlisteners.listener.ChannelInfoListener;
|
||||
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.handler.codec.string.StringDecoder;
|
||||
import io.netty.handler.codec.string.StringEncoder;
|
||||
|
||||
public final class ChatServerMain {
|
||||
|
||||
public static final String HOST = "localhost";
|
||||
public static final int PORT = 8081;
|
||||
|
||||
public static void main(String[] args) {
|
||||
EventLoopGroup serverGroup = new NioEventLoopGroup(1);
|
||||
EventLoopGroup clientGroup = new NioEventLoopGroup();
|
||||
try {
|
||||
ServerBootstrap bootstrap = new ServerBootstrap();
|
||||
bootstrap.group(serverGroup, clientGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
public void initChannel(SocketChannel channel) throws Exception {
|
||||
channel.pipeline()
|
||||
.addFirst(new StringDecoder(), new ServerEventHandler(), new StringEncoder());
|
||||
}
|
||||
});
|
||||
|
||||
ChannelFuture future = bootstrap.bind(HOST, PORT)
|
||||
.sync();
|
||||
|
||||
System.out.println("chat server started. ready to accept clients.");
|
||||
future.addListener(new ChannelInfoListener("server online"));
|
||||
|
||||
future.channel()
|
||||
.closeFuture()
|
||||
.sync();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
Thread.currentThread().interrupt();
|
||||
} finally {
|
||||
serverGroup.shutdownGracefully();
|
||||
clientGroup.shutdownGracefully();
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package com.baeldung.netty.customhandlersandlisteners.handler;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
|
||||
public class ClientEventHandler extends SimpleChannelInboundHandler<String> {
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext context, String msg) {
|
||||
System.out.println(msg);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user