Merge branch 'eugenp:master' into master

This commit is contained in:
Mladen Savic 2021-08-31 20:43:19 +02:00 committed by GitHub
commit f49b1f9235
460 changed files with 19893 additions and 16346 deletions

View File

@ -8,6 +8,9 @@ import java.util.PriorityQueue;
import java.util.Queue;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class RouteFinder<T extends GraphNode> {
private final Graph<T> graph;
private final Scorer<T> nextNodeScorer;
@ -28,11 +31,11 @@ public class RouteFinder<T extends GraphNode> {
openSet.add(start);
while (!openSet.isEmpty()) {
System.out.println("Open Set contains: " + openSet.stream().map(RouteNode::getCurrent).collect(Collectors.toSet()));
log.debug("Open Set contains: " + openSet.stream().map(RouteNode::getCurrent).collect(Collectors.toSet()));
RouteNode<T> next = openSet.poll();
System.out.println("Looking at node: " + next);
log.debug("Looking at node: " + next);
if (next.getCurrent().equals(to)) {
System.out.println("Found our destination!");
log.debug("Found our destination!");
List<T> route = new ArrayList<>();
RouteNode<T> current = next;
@ -41,7 +44,7 @@ public class RouteFinder<T extends GraphNode> {
current = allNodes.get(current.getPrevious());
} while (current != null);
System.out.println("Route: " + route);
log.debug("Route: " + route);
return route;
}
@ -55,7 +58,7 @@ public class RouteFinder<T extends GraphNode> {
nextNode.setRouteScore(newScore);
nextNode.setEstimatedScore(newScore + targetScorer.computeCost(connection, to));
openSet.add(nextNode);
System.out.println("Found a better route to node: " + nextNode);
log.debug("Found a better route to node: " + nextNode);
}
});
}

View File

@ -1,5 +1,7 @@
package com.baeldung.algorithms.astar.underground;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -10,9 +12,13 @@ import java.util.stream.Stream;
import com.baeldung.algorithms.astar.Graph;
import com.baeldung.algorithms.astar.RouteFinder;
import lombok.extern.slf4j.Slf4j;
import org.junit.Before;
import org.junit.Test;
@Slf4j
public class RouteFinderIntegrationTest {
private Graph<Station> underground;
@ -637,7 +643,8 @@ public class RouteFinderIntegrationTest {
@Test
public void findRoute() {
List<Station> route = routeFinder.findRoute(underground.getNode("74"), underground.getNode("7"));
assertThat(route).size().isPositive();
System.out.println(route.stream().map(Station::getName).collect(Collectors.toList()));
route.stream().map(Station::getName).collect(Collectors.toList()).forEach(station -> log.debug(station));
}
}

View File

@ -20,19 +20,16 @@
<version>${org.assertj.core.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>${commons-collections4.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>retrofit</artifactId>
@ -43,13 +40,11 @@
<artifactId>converter-jackson</artifactId>
<version>${retrofit.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
</dependency>
<dependency>
<groupId>pl.pragmatists</groupId>
<artifactId>JUnitParams</artifactId>

View File

@ -39,7 +39,6 @@
<artifactId>junit-platform-commons</artifactId>
<version>${junit.platform.version}</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>

View File

@ -14,7 +14,6 @@
</parent>
<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
@ -33,7 +32,6 @@
<version>${bind-api.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>

18
apache-kafka/README.md Normal file
View File

@ -0,0 +1,18 @@
## Apache Kafka
This module contains articles about Apache Kafka.
### Relevant articles
- [Kafka Streams vs Kafka Consumer](https://www.baeldung.com/java-kafka-streams-vs-kafka-consumer)
- [Kafka Topic Creation Using Java](https://www.baeldung.com/kafka-topic-creation)
- [Using Kafka MockConsumer](https://www.baeldung.com/kafka-mockconsumer)
- [Using Kafka MockProducer](https://www.baeldung.com/kafka-mockproducer)
- [Introduction to KafkaStreams in Java](https://www.baeldung.com/java-kafka-streams)
- [Introduction to Kafka Connectors](https://www.baeldung.com/kafka-connectors-guide)
- [Kafka Connect Example with MQTT and MongoDB](https://www.baeldung.com/kafka-connect-mqtt-mongodb)
- [Building a Data Pipeline with Flink and Kafka](https://www.baeldung.com/kafka-flink-data-pipeline)
- [Exactly Once Processing in Kafka with Java](https://www.baeldung.com/kafka-exactly-once)
##### Building the project
You can build the project from the command line using: *mvn clean install*, or in an IDE.

180
apache-kafka/pom.xml Normal file
View File

@ -0,0 +1,180 @@
<?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>apache-kafka</artifactId>
<name>apache-kafka</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>${kafka.version}</version>
</dependency>
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-streams</artifactId>
<version>${kafka.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-connector-kafka-0.11_2.11</artifactId>
<version>${flink.version}</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-streaming-java_2.11</artifactId>
<version>${flink.version}</version>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-core</artifactId>
<version>${flink.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-java</artifactId>
<version>${flink.version}</version>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-test-utils_2.11</artifactId>
<version>${flink.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>${awaitility.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility-proxy</artifactId>
<version>${awaitility.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>kafka</artifactId>
<version>${testcontainers-kafka.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${testcontainers-jupiter.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>${org.apache.spark.spark-core.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>${org.apache.spark.spark-core.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-graphx_2.11</artifactId>
<version>${org.apache.spark.spark-core.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.11</artifactId>
<version>${org.apache.spark.spark-core.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-mllib_2.11</artifactId>
<version>${org.apache.spark.spark-core.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming-kafka-0-10_2.11</artifactId>
<version>${org.apache.spark.spark-core.version}</version>
</dependency>
<dependency>
<groupId>com.datastax.spark</groupId>
<artifactId>spark-cassandra-connector_2.11</artifactId>
<version>${com.datastax.spark.spark-cassandra-connector.version}</version>
</dependency>
<dependency>
<groupId>com.datastax.spark</groupId>
<artifactId>spark-cassandra-connector-java_2.11</artifactId>
<version>${com.datastax.spark.spark-cassandra-connector-java.version}</version>
</dependency>
</dependencies>
<properties>
<assertj.version>3.6.2</assertj.version>
<kafka.version>2.8.0</kafka.version>
<testcontainers-kafka.version>1.15.3</testcontainers-kafka.version>
<testcontainers-jupiter.version>1.15.3</testcontainers-jupiter.version>
<flink.version>1.5.0</flink.version>
<awaitility.version>3.0.0</awaitility.version>
<guava.version>29.0-jre</guava.version>
<org.apache.spark.spark-core.version>2.4.8</org.apache.spark.spark-core.version>
<graphframes.version>0.8.1-spark3.0-s_2.12</graphframes.version>
<com.datastax.spark.spark-cassandra-connector.version>2.5.2</com.datastax.spark.spark-cassandra-connector.version>
<com.datastax.spark.spark-cassandra-connector-java.version>1.6.0-M1</com.datastax.spark.spark-cassandra-connector-java.version>
</properties>
</project>

View File

@ -0,0 +1,70 @@
package com.baeldung.flink;
import com.baeldung.flink.model.Backup;
import com.baeldung.flink.model.InputMessage;
import com.baeldung.flink.operator.BackupAggregator;
import com.baeldung.flink.operator.InputMessageTimestampAssigner;
import com.baeldung.flink.operator.WordsCapitalizer;
import org.apache.flink.streaming.api.TimeCharacteristic;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.windowing.time.Time;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer011;
import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer011;
import static com.baeldung.flink.connector.Consumers.*;
import static com.baeldung.flink.connector.Producers.*;
public class FlinkDataPipeline {
public static void capitalize() throws Exception {
String inputTopic = "flink_input";
String outputTopic = "flink_output";
String consumerGroup = "baeldung";
String address = "localhost:9092";
StreamExecutionEnvironment environment = StreamExecutionEnvironment.getExecutionEnvironment();
FlinkKafkaConsumer011<String> flinkKafkaConsumer = createStringConsumerForTopic(inputTopic, address, consumerGroup);
flinkKafkaConsumer.setStartFromEarliest();
DataStream<String> stringInputStream = environment.addSource(flinkKafkaConsumer);
FlinkKafkaProducer011<String> flinkKafkaProducer = createStringProducer(outputTopic, address);
stringInputStream.map(new WordsCapitalizer())
.addSink(flinkKafkaProducer);
environment.execute();
}
public static void createBackup() throws Exception {
String inputTopic = "flink_input";
String outputTopic = "flink_output";
String consumerGroup = "baeldung";
String kafkaAddress = "localhost:9092";
StreamExecutionEnvironment environment = StreamExecutionEnvironment.getExecutionEnvironment();
environment.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
FlinkKafkaConsumer011<InputMessage> flinkKafkaConsumer = createInputMessageConsumer(inputTopic, kafkaAddress, consumerGroup);
flinkKafkaConsumer.setStartFromEarliest();
flinkKafkaConsumer.assignTimestampsAndWatermarks(new InputMessageTimestampAssigner());
FlinkKafkaProducer011<Backup> flinkKafkaProducer = createBackupProducer(outputTopic, kafkaAddress);
DataStream<InputMessage> inputMessagesStream = environment.addSource(flinkKafkaConsumer);
inputMessagesStream.timeWindowAll(Time.hours(24))
.aggregate(new BackupAggregator())
.addSink(flinkKafkaProducer);
environment.execute();
}
public static void main(String[] args) throws Exception {
createBackup();
}
}

View File

@ -9,13 +9,11 @@ import java.util.Properties;
public class Consumers {
public static FlinkKafkaConsumer011<String> createStringConsumerForTopic(
String topic, String kafkaAddress, String kafkaGroup ) {
public static FlinkKafkaConsumer011<String> createStringConsumerForTopic(String topic, String kafkaAddress, String kafkaGroup) {
Properties props = new Properties();
props.setProperty("bootstrap.servers", kafkaAddress);
props.setProperty("group.id", kafkaGroup);
FlinkKafkaConsumer011<String> consumer =
new FlinkKafkaConsumer011<>(topic, new SimpleStringSchema(),props);
FlinkKafkaConsumer011<String> consumer = new FlinkKafkaConsumer011<>(topic, new SimpleStringSchema(), props);
return consumer;
}
@ -24,8 +22,7 @@ public static FlinkKafkaConsumer011<String> createStringConsumerForTopic(
Properties properties = new Properties();
properties.setProperty("bootstrap.servers", kafkaAddress);
properties.setProperty("group.id", kafkaGroup);
FlinkKafkaConsumer011<InputMessage> consumer = new FlinkKafkaConsumer011<InputMessage>(
topic, new InputMessageDeserializationSchema(),properties);
FlinkKafkaConsumer011<InputMessage> consumer = new FlinkKafkaConsumer011<InputMessage>(topic, new InputMessageDeserializationSchema(), properties);
return consumer;
}

View File

@ -18,6 +18,7 @@ public class InputMessage {
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
@ -55,8 +56,10 @@ public class InputMessage {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
InputMessage message1 = (InputMessage) o;
return Objects.equal(sender, message1.sender) &&
Objects.equal(recipient, message1.recipient) &&

View File

@ -0,0 +1,34 @@
package com.baeldung.flink.operator;
import com.baeldung.flink.model.Backup;
import com.baeldung.flink.model.InputMessage;
import org.apache.flink.api.common.functions.AggregateFunction;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
public class BackupAggregator implements AggregateFunction<InputMessage, List<InputMessage>, Backup> {
@Override
public List<InputMessage> createAccumulator() {
return new ArrayList<>();
}
@Override
public List<InputMessage> add(InputMessage inputMessage, List<InputMessage> inputMessages) {
inputMessages.add(inputMessage);
return inputMessages;
}
@Override
public Backup getResult(List<InputMessage> inputMessages) {
Backup backup = new Backup(inputMessages, LocalDateTime.now());
return backup;
}
@Override
public List<InputMessage> merge(List<InputMessage> inputMessages, List<InputMessage> acc1) {
inputMessages.addAll(acc1);
return inputMessages;
}
}

View File

@ -12,7 +12,9 @@ public class InputMessageTimestampAssigner implements AssignerWithPunctuatedWate
@Override
public long extractTimestamp(InputMessage element, long previousElementTimestamp) {
ZoneId zoneId = ZoneId.systemDefault();
return element.getSentAt().atZone(zoneId).toEpochSecond() * 1000;
return element.getSentAt()
.atZone(zoneId)
.toEpochSecond() * 1000;
}
@Nullable

View File

@ -9,8 +9,7 @@ import org.apache.flink.api.common.serialization.SerializationSchema;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BackupSerializationSchema
implements SerializationSchema<Backup> {
public class BackupSerializationSchema implements SerializationSchema<Backup> {
static ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule());

View File

@ -8,12 +8,10 @@ import org.apache.flink.api.common.typeinfo.TypeInformation;
import java.io.IOException;
public class InputMessageDeserializationSchema implements
DeserializationSchema<InputMessage> {
public class InputMessageDeserializationSchema implements DeserializationSchema<InputMessage> {
static ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule());
@Override
public InputMessage deserialize(byte[] bytes) throws IOException {

View File

@ -27,11 +27,11 @@ public class KafkaTopicApplication {
short replicationFactor = 1;
NewTopic newTopic = new NewTopic(topicName, partitions, replicationFactor);
CreateTopicsResult result = admin.createTopics(
Collections.singleton(newTopic));
CreateTopicsResult result = admin.createTopics(Collections.singleton(newTopic));
// get the async result for the new topic creation
KafkaFuture<Void> future = result.values().get(topicName);
KafkaFuture<Void> future = result.values()
.get(topicName);
// call get() to block until topic creation has completed or failed
future.get();
@ -47,15 +47,13 @@ public class KafkaTopicApplication {
short replicationFactor = 1;
NewTopic newTopic = new NewTopic(topicName, partitions, replicationFactor);
CreateTopicsOptions topicOptions = new CreateTopicsOptions()
.validateOnly(true)
CreateTopicsOptions topicOptions = new CreateTopicsOptions().validateOnly(true)
.retryOnQuotaViolation(true);
CreateTopicsResult result = admin.createTopics(
Collections.singleton(newTopic), topicOptions
);
CreateTopicsResult result = admin.createTopics(Collections.singleton(newTopic), topicOptions);
KafkaFuture<Void> future = result.values().get(topicName);
KafkaFuture<Void> future = result.values()
.get(topicName);
future.get();
}
}
@ -72,14 +70,12 @@ public class KafkaTopicApplication {
Map<String, String> newTopicConfig = new HashMap<>();
newTopicConfig.put(TopicConfig.CLEANUP_POLICY_CONFIG, TopicConfig.CLEANUP_POLICY_COMPACT);
newTopicConfig.put(TopicConfig.COMPRESSION_TYPE_CONFIG, "lz4");
NewTopic newTopic = new NewTopic(topicName, partitions, replicationFactor)
.configs(newTopicConfig);
NewTopic newTopic = new NewTopic(topicName, partitions, replicationFactor).configs(newTopicConfig);
CreateTopicsResult result = admin.createTopics(
Collections.singleton(newTopic)
);
CreateTopicsResult result = admin.createTopics(Collections.singleton(newTopic));
KafkaFuture<Void> future = result.values().get(topicName);
KafkaFuture<Void> future = result.values()
.get(topicName);
future.get();
}
}

View File

@ -19,9 +19,7 @@ public class CountryPopulationConsumer {
private java.util.function.Consumer<Throwable> exceptionConsumer;
private java.util.function.Consumer<CountryPopulation> countryPopulationConsumer;
public CountryPopulationConsumer(
Consumer<String, Integer> consumer, java.util.function.Consumer<Throwable> exceptionConsumer,
java.util.function.Consumer<CountryPopulation> countryPopulationConsumer) {
public CountryPopulationConsumer(Consumer<String, Integer> consumer, java.util.function.Consumer<Throwable> exceptionConsumer, java.util.function.Consumer<CountryPopulation> countryPopulationConsumer) {
this.consumer = consumer;
this.exceptionConsumer = exceptionConsumer;
this.countryPopulationConsumer = countryPopulationConsumer;

View File

@ -1,4 +1,4 @@
package com.baeldung.kafka;
package com.baeldung.kafka.exactlyonce;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
@ -28,8 +28,8 @@ public class TransactionalMessageProducer {
producer.beginTransaction();
Stream.of(DATA_MESSAGE_1, DATA_MESSAGE_2).forEach(s -> producer.send(
new ProducerRecord<String, String>("input", null, s)));
Stream.of(DATA_MESSAGE_1, DATA_MESSAGE_2)
.forEach(s -> producer.send(new ProducerRecord<String, String>("input", null, s)));
producer.commitTransaction();

View File

@ -1,4 +1,4 @@
package com.baeldung.kafka;
package com.baeldung.kafka.exactlyonce;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
@ -44,7 +44,8 @@ public class TransactionalWordCount {
Map<String, Integer> wordCountMap = records.records(new TopicPartition(INPUT_TOPIC, 0))
.stream()
.flatMap(record -> Stream.of(record.value().split(" ")))
.flatMap(record -> Stream.of(record.value()
.split(" ")))
.map(word -> Tuple.of(word, 1))
.collect(Collectors.toMap(tuple -> tuple.getKey(), t1 -> t1.getValue(), (v1, v2) -> v1 + v2));
@ -56,7 +57,8 @@ public class TransactionalWordCount {
for (TopicPartition partition : records.partitions()) {
List<ConsumerRecord<String, String>> partitionedRecords = records.records(partition);
long offset = partitionedRecords.get(partitionedRecords.size() - 1).offset();
long offset = partitionedRecords.get(partitionedRecords.size() - 1)
.offset();
offsetsToCommit.put(partition, new OffsetAndMetadata(offset + 1));
}
@ -72,7 +74,6 @@ public class TransactionalWordCount {
}
}
private static KafkaConsumer<String, String> createKafkaConsumer() {

View File

@ -1,4 +1,4 @@
package com.baeldung.kafka;
package com.baeldung.kafka.exactlyonce;
public class Tuple {

View File

@ -15,8 +15,7 @@ public class KafkaProducer {
}
public Future<RecordMetadata> send(String key, String value) {
ProducerRecord record = new ProducerRecord("topic_sports_news",
key, value);
ProducerRecord record = new ProducerRecord("topic_sports_news", key, value);
return producer.send(record);
}
@ -36,5 +35,4 @@ public class KafkaProducer {
producer.commitTransaction();
}
}

View File

@ -1,4 +1,4 @@
package com.baeldung.kafka.streams;
package com.baeldung.kafka.streamsvsconsumer;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.producer.KafkaProducer;

View File

@ -1,23 +1,28 @@
package com.baeldung.kafkastreams;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.Serde;
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KafkaStreams;
import org.apache.kafka.streams.StreamsConfig;
import org.apache.kafka.streams.kstream.KStream;
import org.apache.kafka.streams.kstream.KStreamBuilder;
import org.apache.kafka.streams.kstream.KTable;
import org.apache.kafka.test.TestUtils;
import org.junit.Ignore;
import org.junit.Test;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Properties;
import java.util.regex.Pattern;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.KafkaStreams;
import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.StreamsConfig;
import org.apache.kafka.streams.Topology;
import org.apache.kafka.streams.kstream.KStream;
import org.apache.kafka.streams.kstream.KTable;
import org.apache.kafka.streams.kstream.Produced;
import org.junit.Ignore;
import org.junit.Test;
public class KafkaStreamsLiveTest {
private String bootstrapServers = "localhost:9092";
private Path stateDirectory;
@Test
@Ignore("it needs to have kafka broker running on local")
@ -28,31 +33,43 @@ public class KafkaStreamsLiveTest {
Properties streamsConfiguration = new Properties();
streamsConfiguration.put(StreamsConfig.APPLICATION_ID_CONFIG, "wordcount-live-test");
streamsConfiguration.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
streamsConfiguration.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName());
streamsConfiguration.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String().getClass().getName());
streamsConfiguration.put(StreamsConfig.DEFAULT_KEY_SERDE_CLASS_CONFIG, Serdes.String()
.getClass()
.getName());
streamsConfiguration.put(StreamsConfig.DEFAULT_VALUE_SERDE_CLASS_CONFIG, Serdes.String()
.getClass()
.getName());
streamsConfiguration.put(StreamsConfig.COMMIT_INTERVAL_MS_CONFIG, 1000);
streamsConfiguration.put(ConsumerConfig.AUTO_OFFSET_RESET_CONFIG, "earliest");
// Use a temporary directory for storing state, which will be automatically removed after the test.
streamsConfiguration.put(StreamsConfig.STATE_DIR_CONFIG, TestUtils.tempDirectory().getAbsolutePath());
try {
this.stateDirectory = Files.createTempDirectory("kafka-streams");
streamsConfiguration.put(StreamsConfig.STATE_DIR_CONFIG, this.stateDirectory.toAbsolutePath()
.toString());
} catch (final IOException e) {
throw new UncheckedIOException("Cannot create temporary directory", e);
}
// when
KStreamBuilder builder = new KStreamBuilder();
final StreamsBuilder builder = new StreamsBuilder();
KStream<String, String> textLines = builder.stream(inputTopic);
Pattern pattern = Pattern.compile("\\W+", Pattern.UNICODE_CHARACTER_CLASS);
KTable<String, Long> wordCounts = textLines
.flatMapValues(value -> Arrays.asList(pattern.split(value.toLowerCase())))
KTable<String, Long> wordCounts = textLines.flatMapValues(value -> Arrays.asList(pattern.split(value.toLowerCase())))
.groupBy((key, word) -> word)
.count();
wordCounts.foreach((word, count) -> System.out.println("word: " + word + " -> " + count));
wordCounts.toStream()
.foreach((word, count) -> System.out.println("word: " + word + " -> " + count));
String outputTopic = "outputTopic";
final Serde<String> stringSerde = Serdes.String();
final Serde<Long> longSerde = Serdes.Long();
wordCounts.to(stringSerde, longSerde, outputTopic);
KafkaStreams streams = new KafkaStreams(builder, streamsConfiguration);
wordCounts.toStream()
.to(outputTopic, Produced.with(Serdes.String(), Serdes.Long()));
final Topology topology = builder.build();
KafkaStreams streams = new KafkaStreams(topology, streamsConfiguration);
streams.start();
// then

View File

@ -183,7 +183,6 @@
</execution>
</executions>
</plugin>
<!-- meecrowave -->
<plugin>
<groupId>org.apache.meecrowave</groupId>

File diff suppressed because it is too large Load Diff

View File

@ -25,4 +25,5 @@
<geode.core>1.6.0</geode.core>
<rocketmq.version>2.0.4</rocketmq.version>
</properties>
</project>

View File

@ -77,7 +77,6 @@
<optimize>true</optimize>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
@ -88,7 +87,6 @@
</systemPropertyVariables>
</configuration>
</plugin>
<!-- Run the application using "mvn jetty:run" -->
<plugin>
<groupId>org.mortbay.jetty</groupId>
@ -119,7 +117,6 @@
<id>jboss</id>
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
</repository>
<!-- This repository is only needed when the Tapestry version is a preview release, rather than
a final release. -->
<repository>

View File

@ -1,4 +1,5 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>helloworld</groupId>
@ -6,10 +7,6 @@
<version>1.0</version>
<packaging>jar</packaging>
<name>ToDoFunction</name>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
@ -102,4 +99,10 @@
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>

View File

@ -93,4 +93,5 @@
<spring.version>2.2.1.RELEASE</spring.version>
<awssdk.version>2.10.27</awssdk.version>
</properties>
</project>

View File

@ -83,7 +83,6 @@
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>${assembly.plugin.version}</version>

View File

@ -48,13 +48,11 @@
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>${maven-shade-plugin.version}</version>
</plugin>
</plugins>
</build>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns="http://maven.apache.org/POM/4.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>

View File

@ -2,3 +2,4 @@
- [String API Updates in Java 12](https://www.baeldung.com/java12-string-api)
- [New Features in Java 12](https://www.baeldung.com/java-12-new-features)
- [Compare the Content of Two Files in Java](https://www.baeldung.com/java-compare-files)

View File

@ -23,6 +23,11 @@
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
</dependencies>
<build>
@ -37,6 +42,12 @@
<compilerArgs>--enable-preview</compilerArgs>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>--enable-preview</argLine>
</configuration>
</plugin>
</plugins>
</build>

View File

@ -0,0 +1,88 @@
package com.baeldung.file.content.comparison;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
public class CompareFileContents {
public static long filesCompareByByte(Path path1, Path path2) throws IOException {
if (path1.getFileSystem()
.provider()
.isSameFile(path1, path2)) {
return -1;
}
try (BufferedInputStream fis1 = new BufferedInputStream(new FileInputStream(path1.toFile()));
BufferedInputStream fis2 = new BufferedInputStream(new FileInputStream(path2.toFile()))) {
int ch = 0;
long pos = 1;
while ((ch = fis1.read()) != -1) {
if (ch != fis2.read()) {
return pos;
}
pos++;
}
if (fis2.read() == -1) {
return -1;
} else {
return pos;
}
}
}
public static long filesCompareByLine(Path path1, Path path2) throws IOException {
if (path1.getFileSystem()
.provider()
.isSameFile(path1, path2)) {
return -1;
}
try (BufferedReader bf1 = Files.newBufferedReader(path1);
BufferedReader bf2 = Files.newBufferedReader(path2)) {
long lineNumber = 1;
String line1 = "", line2 = "";
while ((line1 = bf1.readLine()) != null) {
line2 = bf2.readLine();
if (line2 == null || !line1.equals(line2)) {
return lineNumber;
}
lineNumber++;
}
if (bf2.readLine() == null) {
return -1;
} else {
return lineNumber;
}
}
}
public static boolean compareByMemoryMappedFiles(Path path1, Path path2) throws IOException {
try (RandomAccessFile randomAccessFile1 = new RandomAccessFile(path1.toFile(), "r");
RandomAccessFile randomAccessFile2 = new RandomAccessFile(path2.toFile(), "r")) {
FileChannel ch1 = randomAccessFile1.getChannel();
FileChannel ch2 = randomAccessFile2.getChannel();
if (ch1.size() != ch2.size()) {
return false;
}
long size = ch1.size();
MappedByteBuffer m1 = ch1.map(FileChannel.MapMode.READ_ONLY, 0L, size);
MappedByteBuffer m2 = ch2.map(FileChannel.MapMode.READ_ONLY, 0L, size);
return m1.equals(m2);
}
}
}

View File

@ -0,0 +1,88 @@
package com.baeldung.file.content.comparison;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
public class CampareFileContentsApacheIOUnitTest {
public static Path path1 = null;
public static Path path2 = null;
@BeforeAll
public static void setup() throws IOException {
path1 = Files.createTempFile("file1Test", ".txt");
path2 = Files.createTempFile("file2Test", ".txt");
}
@Test
public void whenFilesIdentical_thenReturnTrue() throws IOException {
InputStream inputStream1 = new FileInputStream(path1.toFile());
InputStream inputStream2 = new FileInputStream(path2.toFile());
Files.writeString(path1, "testing line 1" + System.lineSeparator() + "line 2");
Files.writeString(path2, "testing line 1" + System.lineSeparator() + "line 2");
assertTrue(IOUtils.contentEquals(inputStream1, inputStream2));
}
@Test
public void whenFilesDifferent_thenReturnFalse() throws IOException {
InputStream inputStream1 = new FileInputStream(path1.toFile());
InputStream inputStream2 = new FileInputStream(path2.toFile());
Files.writeString(path1, "testing line " + System.lineSeparator() + "line 2");
Files.writeString(path2, "testing line 1" + System.lineSeparator() + "line 2");
assertFalse(IOUtils.contentEquals(inputStream1, inputStream2));
}
@Test
public void whenFilesIdenticalIgnoreEOF_thenReturnTrue() throws IOException {
Files.writeString(path1, "testing line 1 \n line 2");
Files.writeString(path2, "testing line 1 \r\n line 2");
Reader reader1 = new BufferedReader(new FileReader(path1.toFile()));
Reader reader2 = new BufferedReader(new FileReader(path2.toFile()));
assertTrue(IOUtils.contentEqualsIgnoreEOL(reader1, reader2));
}
@Test
public void whenFilesNotIdenticalIgnoreEOF_thenReturnFalse() throws IOException {
Files.writeString(path1, "testing line \n line 2");
Files.writeString(path2, "testing line 1 \r\n line 2");
Reader reader1 = new BufferedReader(new FileReader(path1.toFile()));
Reader reader2 = new BufferedReader(new FileReader(path2.toFile()));
assertFalse(IOUtils.contentEqualsIgnoreEOL(reader1, reader2));
}
@AfterAll
public static void shutDown() {
path1.toFile()
.deleteOnExit();
path2.toFile()
.deleteOnExit();
}
}

View File

@ -0,0 +1,42 @@
package com.baeldung.file.content.comparison;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
public class CompareByMemoryMappedFilesUnitTest {
public static Path path1 = null;
public static Path path2 = null;
@BeforeAll
public static void setup() throws IOException {
path1 = Files.createTempFile("file1Test", ".txt");
path2 = Files.createTempFile("file2Test", ".txt");
}
@Test
public void whenFilesIdentical_thenReturnTrue() throws IOException {
Files.writeString(path1, "testing line 1" + System.lineSeparator() + "line 2");
Files.writeString(path2, "testing line 1" + System.lineSeparator() + "line 2");
assertTrue(CompareFileContents.compareByMemoryMappedFiles(path1, path2));
}
@Test
public void whenFilesDifferent_thenReturnFalse() throws IOException {
Files.writeString(path1, "testing line " + System.lineSeparator() + "line 2");
Files.writeString(path2, "testing line 1" + System.lineSeparator() + "line 2");
assertFalse(CompareFileContents.compareByMemoryMappedFiles(path1, path2));
}
}

View File

@ -0,0 +1,96 @@
package com.baeldung.file.content.comparison;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
public class CompareFileContentsByBytesUnitTest {
public static Path path1 = null;
public static Path path2 = null;
@BeforeAll
public static void setup() throws IOException {
path1 = Files.createTempFile("file1Test", ".txt");
path2 = Files.createTempFile("file2Test", ".txt");
}
@Test
public void whenFirstFileShorter_thenPositionInSecondFile() throws IOException {
Files.writeString(path1, "testing");
Files.writeString(path2, "testing1");
assertEquals(8, CompareFileContents.filesCompareByByte(path1, path2));
}
@Test
public void whenSecondFileShorter_thenPositionInFirstFile() throws IOException {
Files.writeString(path1, "testing1");
Files.writeString(path2, "testing");
assertEquals(8, CompareFileContents.filesCompareByByte(path1, path2));
}
@Test
public void whenFilesIdentical_thenSuccess() throws IOException {
Files.writeString(path1, "testing");
Files.writeString(path2, "testing");
assertEquals(-1, CompareFileContents.filesCompareByByte(path1, path2));
}
@Test
public void whenFilesDifferent_thenPosition() throws IOException {
Files.writeString(path1, "tesXing");
Files.writeString(path2, "testing");
assertEquals(4, CompareFileContents.filesCompareByByte(path1, path2));
}
@Test
public void whenBothFilesEmpty_thenEqual() throws IOException {
Files.writeString(path1, "");
Files.writeString(path2, "");
assertEquals(-1, CompareFileContents.filesCompareByByte(path1, path2));
}
@Test
public void whenFirstEmpty_thenPositionFirst() throws IOException {
Files.writeString(path1, "");
Files.writeString(path2, "test");
assertEquals(1, CompareFileContents.filesCompareByByte(path1, path2));
}
@Test
public void whenSecondEmpty_thenPositionFirst() throws IOException {
Files.writeString(path1, "test");
Files.writeString(path2, "");
assertEquals(1, CompareFileContents.filesCompareByByte(path1, path2));
}
@AfterAll
public static void shutDown() {
path1.toFile().deleteOnExit();
path2.toFile().deleteOnExit();
}
}

View File

@ -0,0 +1,94 @@
package com.baeldung.file.content.comparison;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
public class CompareFileContentsByLinesUnitTest {
public static Path path1 = null;
public static Path path2 = null;
@BeforeAll
public static void setup() throws IOException {
path1 = Files.createTempFile("file1Test", ".txt");
path2 = Files.createTempFile("file2Test", ".txt");
}
@Test
public void whenFirstFileShorter_thenLineNumbersFirstFile() throws IOException {
Files.writeString(path1, "testing line 1");
Files.writeString(path2, "testing1 line 1" + System.lineSeparator() + "line 2");
assertEquals(1, CompareFileContents.filesCompareByLine(path1, path2));
}
@Test
public void whenSecondFileShorter_thenLineNumbersSecondFile() throws IOException {
Files.writeString(path1, "testing1 line 1" + System.lineSeparator() + "line 2");
Files.writeString(path2, "testing line 1");
assertEquals(1, CompareFileContents.filesCompareByLine(path1, path2));
}
@Test
public void whenFileIdentical_thenLineSuccess() throws IOException {
Files.writeString(path1, "testing1 line 1" + System.lineSeparator() + "line 2");
Files.writeString(path2, "testing1 line 1" + System.lineSeparator() + "line 2");
assertEquals(-1, CompareFileContents.filesCompareByLine(path1, path2));
}
@Test
public void whenFilesDifferent_thenLineNumber() throws IOException {
Files.writeString(path1, "testing1 line 1" + System.lineSeparator() + "line 2");
Files.writeString(path2, "testing1 line 1" + System.lineSeparator() + "linX 2");
assertEquals(2, CompareFileContents.filesCompareByLine(path1, path2));
}
@Test
public void whenBothFilesEmpty_thenEqual() throws IOException {
Files.writeString(path1, "");
Files.writeString(path2, "");
assertEquals(-1, CompareFileContents.filesCompareByByte(path1, path2));
}
@Test
public void whenFirstEmpty_thenPositionFirst() throws IOException {
Files.writeString(path1, "");
Files.writeString(path2, "testing1 line 1" + System.lineSeparator() + "line 2");
assertEquals(1, CompareFileContents.filesCompareByByte(path1, path2));
}
@Test
public void whenSecondEmpty_thenPositionFirst() throws IOException {
Files.writeString(path1, "testing1 line 1" + System.lineSeparator() + "line 2");
Files.writeString(path2, "");
assertEquals(1, CompareFileContents.filesCompareByByte(path1, path2));
}
@AfterAll
public static void shutDown() {
path1.toFile().deleteOnExit();
path2.toFile().deleteOnExit();
}
}

View File

@ -1,6 +1,6 @@
package java.com.baeldung.newfeatures;
package com.baeldung.newfeatures;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import java.text.NumberFormat;
import java.util.Locale;
@ -16,6 +16,6 @@ public class CompactNumbersUnitTest {
assertEquals("2.59K", likesShort.format(2592));
NumberFormat likesLong = NumberFormat.getCompactNumberInstance(new Locale("en", "US"), NumberFormat.Style.LONG);
likesLong.setMaximumFractionDigits(2);
assertEquals("2.59 thousand", likesShort.format(2592));
assertEquals("2.59 thousand", likesLong.format(2592));
}
}

View File

@ -1,6 +1,6 @@
package java.com.baeldung.newfeatures;
package com.baeldung.newfeatures;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.nio.file.Files;

View File

@ -1,6 +1,6 @@
package java.com.baeldung.newfeatures;
package com.baeldung.newfeatures;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import static org.junit.Assert.assertEquals;

View File

@ -1,6 +1,6 @@
package java.com.baeldung.newfeatures;
package com.baeldung.newfeatures;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -13,6 +13,6 @@ public class TeeingCollectorUnitTest {
public void givenSetOfNumbers_thenCalculateAverage() {
double mean = Stream.of(1, 2, 3, 4, 5)
.collect(Collectors.teeing(Collectors.summingDouble(i -> i), Collectors.counting(), (sum, count) -> sum / count));
assertEquals(3.0, mean);
assertEquals(3.0, mean, 0);
}
}

View File

@ -23,6 +23,11 @@
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
<build>

View File

@ -0,0 +1,43 @@
package com.baeldung.java_16_features.groupingby;
import java.util.IntSummaryStatistics;
public class BlogPost {
private String title;
private String author;
private BlogPostType type;
private int likes;
record AuthPostTypesLikes(String author, BlogPostType type, int likes) {};
record PostcountTitlesLikesStats(long postCount, String titles, IntSummaryStatistics likesStats){};
record TitlesBoundedSumOfLikes(String titles, int boundedSumOfLikes) {};
public BlogPost(String title, String author, BlogPostType type, int likes) {
this.title = title;
this.author = author;
this.type = type;
this.likes = likes;
}
public String getTitle() {
return title;
}
public String getAuthor() {
return author;
}
public BlogPostType getType() {
return type;
}
public int getLikes() {
return likes;
}
@Override
public String toString() {
return "BlogPost{" + "title='" + title + '\'' + ", type=" + type + ", likes=" + likes + '}';
}
}

View File

@ -0,0 +1,5 @@
package com.baeldung.java_16_features.groupingby;
public enum BlogPostType {
NEWS, REVIEW, GUIDE
}

View File

@ -0,0 +1,41 @@
package com.baeldung.java_16_features.groupingby;
import java.util.Objects;
public class Tuple {
private final BlogPostType type;
private final String author;
public Tuple(BlogPostType type, String author) {
this.type = type;
this.author = author;
}
public BlogPostType getType() {
return type;
}
public String getAuthor() {
return author;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Tuple tuple = (Tuple) o;
return type == tuple.type && author.equals(tuple.author);
}
@Override
public int hashCode() {
return Objects.hash(type, author);
}
@Override
public String toString() {
return "Tuple{" + "type=" + type + ", author='" + author + '\'' + '}';
}
}

View File

@ -0,0 +1,302 @@
package com.baeldung.java_16_features.groupingby;
import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.averagingInt;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.groupingByConcurrent;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.maxBy;
import static java.util.stream.Collectors.summarizingInt;
import static java.util.stream.Collectors.summingInt;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toSet;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.offset;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.jupiter.api.Test;
public class JavaGroupingByCollectorUnitTest {
private static final List<BlogPost> posts = Arrays.asList(new BlogPost("News item 1", "Author 1", BlogPostType.NEWS, 15), new BlogPost("Tech review 1", "Author 2", BlogPostType.REVIEW, 5),
new BlogPost("Programming guide", "Author 1", BlogPostType.GUIDE, 20), new BlogPost("News item 2", "Author 2", BlogPostType.NEWS, 35), new BlogPost("Tech review 2", "Author 1", BlogPostType.REVIEW, 15));
@Test
public void givenAListOfPosts_whenGroupedByType_thenGetAMapBetweenTypeAndPosts() {
Map<BlogPostType, List<BlogPost>> postsPerType = posts.stream()
.collect(groupingBy(BlogPost::getType));
assertEquals(2, postsPerType.get(BlogPostType.NEWS)
.size());
assertEquals(1, postsPerType.get(BlogPostType.GUIDE)
.size());
assertEquals(2, postsPerType.get(BlogPostType.REVIEW)
.size());
}
@Test
public void givenAListOfPosts_whenGroupedByTypeAndTheirTitlesAreJoinedInAString_thenGetAMapBetweenTypeAndCsvTitles() {
Map<BlogPostType, String> postsPerType = posts.stream()
.collect(groupingBy(BlogPost::getType, mapping(BlogPost::getTitle, joining(", ", "Post titles: [", "]"))));
assertEquals("Post titles: [News item 1, News item 2]", postsPerType.get(BlogPostType.NEWS));
assertEquals("Post titles: [Programming guide]", postsPerType.get(BlogPostType.GUIDE));
assertEquals("Post titles: [Tech review 1, Tech review 2]", postsPerType.get(BlogPostType.REVIEW));
}
@Test
public void givenAListOfPosts_whenGroupedByTypeAndSumTheLikes_thenGetAMapBetweenTypeAndPostLikes() {
Map<BlogPostType, Integer> likesPerType = posts.stream()
.collect(groupingBy(BlogPost::getType, summingInt(BlogPost::getLikes)));
assertEquals(50, likesPerType.get(BlogPostType.NEWS)
.intValue());
assertEquals(20, likesPerType.get(BlogPostType.REVIEW)
.intValue());
assertEquals(20, likesPerType.get(BlogPostType.GUIDE)
.intValue());
}
@Test
public void givenAListOfPosts_whenGroupedByTypeInAnEnumMap_thenGetAnEnumMapBetweenTypeAndPosts() {
EnumMap<BlogPostType, List<BlogPost>> postsPerType = posts.stream()
.collect(groupingBy(BlogPost::getType, () -> new EnumMap<>(BlogPostType.class), toList()));
assertEquals(2, postsPerType.get(BlogPostType.NEWS)
.size());
assertEquals(1, postsPerType.get(BlogPostType.GUIDE)
.size());
assertEquals(2, postsPerType.get(BlogPostType.REVIEW)
.size());
}
@Test
public void givenAListOfPosts_whenGroupedByTypeInSets_thenGetAMapBetweenTypesAndSetsOfPosts() {
Map<BlogPostType, Set<BlogPost>> postsPerType = posts.stream()
.collect(groupingBy(BlogPost::getType, toSet()));
assertEquals(2, postsPerType.get(BlogPostType.NEWS)
.size());
assertEquals(1, postsPerType.get(BlogPostType.GUIDE)
.size());
assertEquals(2, postsPerType.get(BlogPostType.REVIEW)
.size());
}
@Test
public void givenAListOfPosts_whenGroupedByTypeConcurrently_thenGetAMapBetweenTypeAndPosts() {
ConcurrentMap<BlogPostType, List<BlogPost>> postsPerType = posts.parallelStream()
.collect(groupingByConcurrent(BlogPost::getType));
assertEquals(2, postsPerType.get(BlogPostType.NEWS)
.size());
assertEquals(1, postsPerType.get(BlogPostType.GUIDE)
.size());
assertEquals(2, postsPerType.get(BlogPostType.REVIEW)
.size());
}
@Test
public void givenAListOfPosts_whenGroupedByTypeAndAveragingLikes_thenGetAMapBetweenTypeAndAverageNumberOfLikes() {
Map<BlogPostType, Double> averageLikesPerType = posts.stream()
.collect(groupingBy(BlogPost::getType, averagingInt(BlogPost::getLikes)));
assertEquals(25, averageLikesPerType.get(BlogPostType.NEWS)
.intValue());
assertEquals(20, averageLikesPerType.get(BlogPostType.GUIDE)
.intValue());
assertEquals(10, averageLikesPerType.get(BlogPostType.REVIEW)
.intValue());
}
@Test
public void givenAListOfPosts_whenGroupedByTypeAndCounted_thenGetAMapBetweenTypeAndNumberOfPosts() {
Map<BlogPostType, Long> numberOfPostsPerType = posts.stream()
.collect(groupingBy(BlogPost::getType, counting()));
assertEquals(2, numberOfPostsPerType.get(BlogPostType.NEWS)
.intValue());
assertEquals(1, numberOfPostsPerType.get(BlogPostType.GUIDE)
.intValue());
assertEquals(2, numberOfPostsPerType.get(BlogPostType.REVIEW)
.intValue());
}
@Test
public void givenAListOfPosts_whenGroupedByTypeAndMaxingLikes_thenGetAMapBetweenTypeAndMaximumNumberOfLikes() {
Map<BlogPostType, Optional<BlogPost>> maxLikesPerPostType = posts.stream()
.collect(groupingBy(BlogPost::getType, maxBy(comparingInt(BlogPost::getLikes))));
assertTrue(maxLikesPerPostType.get(BlogPostType.NEWS)
.isPresent());
assertEquals(35, maxLikesPerPostType.get(BlogPostType.NEWS)
.get()
.getLikes());
assertTrue(maxLikesPerPostType.get(BlogPostType.GUIDE)
.isPresent());
assertEquals(20, maxLikesPerPostType.get(BlogPostType.GUIDE)
.get()
.getLikes());
assertTrue(maxLikesPerPostType.get(BlogPostType.REVIEW)
.isPresent());
assertEquals(15, maxLikesPerPostType.get(BlogPostType.REVIEW)
.get()
.getLikes());
}
@Test
public void givenAListOfPosts_whenGroupedByAuthorAndThenByType_thenGetAMapBetweenAuthorAndMapsBetweenTypeAndBlogPosts() {
Map<String, Map<BlogPostType, List<BlogPost>>> map = posts.stream()
.collect(groupingBy(BlogPost::getAuthor, groupingBy(BlogPost::getType)));
assertEquals(1, map.get("Author 1")
.get(BlogPostType.NEWS)
.size());
assertEquals(1, map.get("Author 1")
.get(BlogPostType.GUIDE)
.size());
assertEquals(1, map.get("Author 1")
.get(BlogPostType.REVIEW)
.size());
assertEquals(1, map.get("Author 2")
.get(BlogPostType.NEWS)
.size());
assertEquals(1, map.get("Author 2")
.get(BlogPostType.REVIEW)
.size());
assertNull(map.get("Author 2")
.get(BlogPostType.GUIDE));
}
@Test
public void givenAListOfPosts_whenGroupedByTypeAndSummarizingLikes_thenGetAMapBetweenTypeAndSummary() {
Map<BlogPostType, IntSummaryStatistics> likeStatisticsPerType = posts.stream()
.collect(groupingBy(BlogPost::getType, summarizingInt(BlogPost::getLikes)));
IntSummaryStatistics newsLikeStatistics = likeStatisticsPerType.get(BlogPostType.NEWS);
assertEquals(2, newsLikeStatistics.getCount());
assertEquals(50, newsLikeStatistics.getSum());
assertEquals(25.0, newsLikeStatistics.getAverage(), 0.001);
assertEquals(35, newsLikeStatistics.getMax());
assertEquals(15, newsLikeStatistics.getMin());
}
@Test
public void givenAListOfPosts_whenGroupedByComplexMapPairKeyType_thenGetAMapBetweenPairAndList() {
Map<Pair<BlogPostType, String>, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
.collect(groupingBy(post -> new ImmutablePair<>(post.getType(), post.getAuthor())));
List<BlogPost> result = postsPerTypeAndAuthor.get(new ImmutablePair<>(BlogPostType.GUIDE, "Author 1"));
assertThat(result.size()).isEqualTo(1);
BlogPost blogPost = result.get(0);
assertThat(blogPost.getTitle()).isEqualTo("Programming guide");
assertThat(blogPost.getType()).isEqualTo(BlogPostType.GUIDE);
assertThat(blogPost.getAuthor()).isEqualTo("Author 1");
}
@Test
public void givenAListOfPosts_whenGroupedByComplexMapKeyType_thenGetAMapBetweenTupleAndList() {
Map<Tuple, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
.collect(groupingBy(post -> new Tuple(post.getType(), post.getAuthor())));
List<BlogPost> result = postsPerTypeAndAuthor.get(new Tuple(BlogPostType.GUIDE, "Author 1"));
assertThat(result.size()).isEqualTo(1);
BlogPost blogPost = result.get(0);
assertThat(blogPost.getTitle()).isEqualTo("Programming guide");
assertThat(blogPost.getType()).isEqualTo(BlogPostType.GUIDE);
assertThat(blogPost.getAuthor()).isEqualTo("Author 1");
}
@Test
public void givenAListOfPosts_whenGroupedByRecord_thenGetAMapBetweenRecordAndList() {
Map<BlogPost.AuthPostTypesLikes, List<BlogPost>> postsPerTypeAndAuthor = posts.stream()
.collect(groupingBy(post -> new BlogPost.AuthPostTypesLikes(post.getAuthor(), post.getType(), post.getLikes())));
List<BlogPost> result = postsPerTypeAndAuthor.get(new BlogPost.AuthPostTypesLikes("Author 1", BlogPostType.GUIDE, 20));
assertThat(result.size()).isEqualTo(1);
BlogPost blogPost = result.get(0);
assertThat(blogPost.getTitle()).isEqualTo("Programming guide");
assertThat(blogPost.getType()).isEqualTo(BlogPostType.GUIDE);
assertThat(blogPost.getAuthor()).isEqualTo("Author 1");
assertThat(blogPost.getLikes()).isEqualTo(20);
}
@Test
public void givenListOfPosts_whenGroupedByAuthor_thenGetAMapUsingCollectingAndThen() {
Map<String, BlogPost.PostcountTitlesLikesStats> postsPerAuthor = posts.stream()
.collect(groupingBy(BlogPost::getAuthor, collectingAndThen(toList(), list -> {
long count = list.stream()
.map(BlogPost::getTitle)
.collect(counting());
String titles = list.stream()
.map(BlogPost::getTitle)
.collect(joining(" : "));
IntSummaryStatistics summary = list.stream()
.collect(summarizingInt(BlogPost::getLikes));
return new BlogPost.PostcountTitlesLikesStats(count, titles, summary);
})));
BlogPost.PostcountTitlesLikesStats result = postsPerAuthor.get("Author 1");
assertThat(result.postCount()).isEqualTo(3L);
assertThat(result.titles()).isEqualTo("News item 1 : Programming guide : Tech review 2");
assertThat(result.likesStats().getMax()).isEqualTo(20);
assertThat(result.likesStats().getMin()).isEqualTo(15);
assertThat(result.likesStats().getAverage()).isEqualTo(16.666d, offset(0.001d));
}
@Test
public void givenListOfPosts_whenGroupedByAuthor_thenGetAMapUsingToMap() {
int maxValLikes = 17;
Map<String, BlogPost.TitlesBoundedSumOfLikes> postsPerAuthor = posts.stream()
.collect(toMap(BlogPost::getAuthor, post -> {
int likes = (post.getLikes() > maxValLikes) ? maxValLikes : post.getLikes();
return new BlogPost.TitlesBoundedSumOfLikes(post.getTitle(), likes);
}, (u1, u2) -> {
int likes = (u2.boundedSumOfLikes() > maxValLikes) ? maxValLikes : u2.boundedSumOfLikes();
return new BlogPost.TitlesBoundedSumOfLikes(u1.titles()
.toUpperCase() + " : "
+ u2.titles()
.toUpperCase(),
u1.boundedSumOfLikes() + likes);
}));
BlogPost.TitlesBoundedSumOfLikes result = postsPerAuthor.get("Author 1");
assertThat(result.titles()).isEqualTo("NEWS ITEM 1 : PROGRAMMING GUIDE : TECH REVIEW 2");
assertThat(result.boundedSumOfLikes()).isEqualTo(47);
}
}

View File

@ -31,7 +31,6 @@
<artifactId>jmh-generator-annprocess</artifactId>
<version>${jmh-generator.version}</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>

View File

@ -189,21 +189,8 @@ public class StopExecution {
longRunningSort();
}
private void longRunningOperation() {
LOG.info("long Running operation started");
try {
//Thread.sleep(500);
longFileRead();
LOG.info("long running operation finished");
} catch (InterruptedException e) {
LOG.info("long Running operation interrupted");
}
}
private void longRunningSort() {
LOG.info("long Running task started");
// Do you long running calculation here
LOG.info("Long running task started");
int len = 100000;
List<Integer> numbers = new ArrayList<>();
try {
@ -229,25 +216,7 @@ public class StopExecution {
LOG.info("Index position: " + i);
LOG.info("Long running task finished");
} catch (InterruptedException e) {
LOG.info("long Running operation interrupted");
}
}
private void longFileRead() throws InterruptedException {
String file = "input.txt";
ClassLoader classloader = getClass().getClassLoader();
try (InputStream inputStream = classloader.getResourceAsStream(file)) {
Reader inputStreamReader = new InputStreamReader(inputStream);
int data = inputStreamReader.read();
while (data != -1) {
char theChar = (char) data;
data = inputStreamReader.read();
throwExceptionOnThreadInterrupt();
}
} catch (IOException e) {
LOG.error("Exception: ", e);
LOG.info("Long running operation interrupted");
}
}

View File

@ -49,7 +49,6 @@
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -13,12 +13,9 @@ import java.util.stream.IntStream;
public class TimeApi {
public static List<Date> getDatesBetweenUsingJava7(Date startDate, Date endDate) {
List<Date> datesInRange = new ArrayList<Date>();
Calendar calendar = new GregorianCalendar();
calendar.setTime(startDate);
Calendar endCalendar = new GregorianCalendar();
endCalendar.setTime(endDate);
List<Date> datesInRange = new ArrayList<>();
Calendar calendar = getCalendarWithoutTime(startDate);
Calendar endCalendar = getCalendarWithoutTime(endDate);
while (calendar.before(endCalendar)) {
Date result = calendar.getTime();
@ -40,4 +37,15 @@ public class TimeApi {
return startDate.datesUntil(endDate).collect(Collectors.toList());
}
private static Calendar getCalendarWithoutTime(Date date) {
Calendar calendar = new GregorianCalendar();
calendar.setTime(date);
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
return calendar;
}
}

View File

@ -1,12 +1,13 @@
package com.baeldung.java9.time;
import org.junit.Test;
import java.time.LocalDate;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import static org.junit.Assert.assertEquals;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class TimeApiUnitTest {
@ -18,19 +19,18 @@ public class TimeApiUnitTest {
Date endDate = endCalendar.getTime();
List<Date> dates = TimeApi.getDatesBetweenUsingJava7(startDate, endDate);
assertEquals(dates.size(), 2);
assertThat(dates).hasSize(2);
Calendar calendar = Calendar.getInstance();
Date date1 = calendar.getTime();
assertEquals(dates.get(0).getDay(), date1.getDay());
assertEquals(dates.get(0).getMonth(), date1.getMonth());
assertEquals(dates.get(0).getYear(), date1.getYear());
Date expectedDate1 = calendar.getTime();
assertThat(dates.get(0)).isInSameDayAs(expectedDate1);
assertThatTimeFieldsAreZero(dates.get(0));
calendar.add(Calendar.DATE, 1);
Date date2 = calendar.getTime();
assertEquals(dates.get(1).getDay(), date2.getDay());
assertEquals(dates.get(1).getMonth(), date2.getMonth());
assertEquals(dates.get(1).getYear(), date2.getYear());
Date expectedDate2 = calendar.getTime();
assertThat(dates.get(1)).isInSameDayAs(expectedDate2);
assertThatTimeFieldsAreZero(dates.get(1));
}
@Test
@ -39,9 +39,8 @@ public class TimeApiUnitTest {
LocalDate endDate = LocalDate.now().plusDays(2);
List<LocalDate> dates = TimeApi.getDatesBetweenUsingJava8(startDate, endDate);
assertEquals(dates.size(), 2);
assertEquals(dates.get(0), LocalDate.now());
assertEquals(dates.get(1), LocalDate.now().plusDays(1));
assertThat(dates).containsExactly(LocalDate.now(), LocalDate.now().plusDays(1));
}
@Test
@ -50,9 +49,15 @@ public class TimeApiUnitTest {
LocalDate endDate = LocalDate.now().plusDays(2);
List<LocalDate> dates = TimeApi.getDatesBetweenUsingJava9(startDate, endDate);
assertEquals(dates.size(), 2);
assertEquals(dates.get(0), LocalDate.now());
assertEquals(dates.get(1), LocalDate.now().plusDays(1));
assertThat(dates).containsExactly(LocalDate.now(), LocalDate.now().plusDays(1));
}
private static void assertThatTimeFieldsAreZero(Date date) {
assertThat(date).hasHourOfDay(0);
assertThat(date).hasMinute(0);
assertThat(date).hasSecond(0);
assertThat(date).hasMillisecond(0);
}
}

View File

@ -48,7 +48,6 @@
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -75,7 +75,7 @@
<properties>
<commons-validator.version>1.6</commons-validator.version>
<joda-time.version>2.10</joda-time.version>
<joda-time.version>2.10.10</joda-time.version>
<!-- testing -->
<assertj.version>3.6.1</assertj.version>
<maven.compiler.source>1.9</maven.compiler.source>

View File

@ -0,0 +1,54 @@
package com.baeldung.formatduration;
import org.apache.commons.lang3.time.DurationFormatUtils;
import org.joda.time.Period;
import org.junit.Test;
import java.time.Duration;
import java.util.concurrent.TimeUnit;
import static org.assertj.core.api.Assertions.assertThat;
public class FormatDurationUnitTest {
@Test
public void givenInterval_WhenFormatInterval_formatDuration() {
long HH = TimeUnit.MILLISECONDS.toHours(38114000);
long MM = TimeUnit.MILLISECONDS.toMinutes(38114000) % 60;
long SS = TimeUnit.MILLISECONDS.toSeconds(38114000) % 60;
String timeInHHMMSS = String.format("%02d:%02d:%02d", HH, MM, SS);
assertThat(timeInHHMMSS).isEqualTo("10:35:14");
}
@Test
public void givenInterval_WhenFormatUsingDuration_formatDuration() {
Duration duration = Duration.ofMillis(38114000);
long seconds = duration.getSeconds();
long HH = seconds / 3600;
long MM = (seconds % 3600) / 60;
long SS = seconds % 60;
String timeInHHMMSS = String.format("%02d:%02d:%02d", HH, MM, SS);
assertThat(timeInHHMMSS).isEqualTo("10:35:14");
}
@Test
public void givenInterval_WhenFormatDurationUsingApacheCommons_formatDuration() {
assertThat(DurationFormatUtils.formatDuration(38114000, "HH:mm:ss"))
.isEqualTo("10:35:14");
}
@Test
public void givenInterval_WhenFormatDurationUsingJodaTime_formatDuration() {
org.joda.time.Duration duration = new org.joda.time.Duration(38114000);
Period period = duration.toPeriod();
long HH = period.getHours();
long MM = period.getMinutes();
long SS = period.getSeconds();
String timeInHHMMSS = String.format("%02d:%02d:%02d", HH, MM, SS);
assertThat(timeInHHMMSS).isEqualTo("10:35:14");
}
}

View File

@ -7,6 +7,7 @@
<version>0.1.0-SNAPSHOT</version>
<name>core-java-io-conversions</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>

View File

@ -97,6 +97,7 @@
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>integration</id>

View File

@ -7,6 +7,7 @@
<version>0.1.0-SNAPSHOT</version>
<name>core-java-jar</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung.core-java-modules</groupId>
<artifactId>core-java-modules</artifactId>

View File

@ -48,4 +48,5 @@
</resource>
</resources>
</build>
</project>

View File

@ -7,3 +7,4 @@ This module contains article about constructors in Java
- [Java Copy Constructor](https://www.baeldung.com/java-copy-constructor)
- [Cannot Reference “X” Before Supertype Constructor Has Been Called](https://www.baeldung.com/java-cannot-reference-x-before-supertype-constructor-error)
- [Private Constructors in Java](https://www.baeldung.com/java-private-constructors)
- [Throwing Exceptions in Constructors](https://www.baeldung.com/java-constructors-exceptions)

View File

@ -0,0 +1,32 @@
package com.baeldung.constructors.exception;
import java.io.File;
import java.io.IOException;
public class Animal {
public Animal() throws InstantiationException {
throw new InstantiationException("Cannot be instantiated");
}
public Animal(String id, int age) {
if (id == null)
throw new NullPointerException("Id cannot be null");
if (age < 0)
throw new IllegalArgumentException("Age cannot be negative");
}
public Animal(File file) throws SecurityException, IOException {
// Avoiding Path traversal attacks
if (file.isAbsolute()) {
throw new SecurityException("Traversal attack - absolute path not allowed");
}
// Avoiding directory traversal
// a/../..b/
if (!file.getCanonicalPath()
.equals(file.getAbsolutePath())) {
throw new SecurityException("Directory traversal attempt?");
}
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.constructors.exception;
public class Bird extends Animal {
// Note that we are throwing parent exception
public Bird() throws ReflectiveOperationException {
super();
}
public Bird(String id, int age) {
super(id, age);
}
}

View File

@ -0,0 +1,47 @@
package com.baeldung.constructors.exception;
import java.io.File;
import org.assertj.core.api.Assertions;
import org.junit.Test;
public class AnimalUnitTest {
@Test
public void givenNoArgument_thenFails() {
Assertions.assertThatThrownBy(() -> {
new Animal();
})
.isInstanceOf(Exception.class);
}
@Test
public void givenInvalidArg_thenFails() {
Assertions.assertThatThrownBy(() -> {
new Animal(null, 30);
})
.isInstanceOf(NullPointerException.class);
}
@Test(expected = Test.None.class)
public void givenValidArg_thenSuccess() {
new Animal("1234", 30);
}
@Test
public void givenAbsolutePath_thenFails() {
Assertions.assertThatThrownBy(() -> {
new Animal(new File("temp.txt").getAbsoluteFile());
})
.isInstanceOf(SecurityException.class);
}
@Test
public void givenDirectoryTraversalPath_thenFails() {
Assertions.assertThatThrownBy(() -> {
new Animal(new File(File.separator + ".." + File.separator + "temp.txt"));
})
.isInstanceOf(SecurityException.class);
}
}

View File

@ -5,3 +5,4 @@ This module contains articles about Java operators
## Relevant Articles:
- [Logical vs Bitwise OR Operator](https://www.baeldung.com/java-logical-vs-bitwise-or-operator)
- [Bitmasking in Java with Bitwise Operators](https://www.baeldung.com/java-bitmasking)

View File

@ -25,9 +25,9 @@ public class GrepWithUnix4JIntegrationTest {
@Test
public void whenGrepWithSimpleString_thenCorrect() {
int expectedLineCount = 4;
int expectedLineCount = 5;
// grep "NINETEEN" dictionary.txt
// grep "NINETEEN" dictionary.in
List<Line> lines = Unix4j.grep("NINETEEN", fileToGrep).toLineList();
assertEquals(expectedLineCount, lines.size());
@ -35,9 +35,9 @@ public class GrepWithUnix4JIntegrationTest {
@Test
public void whenInverseGrepWithSimpleString_thenCorrect() {
int expectedLineCount = 178687;
int expectedLineCount = 8;
// grep -v "NINETEEN" dictionary.txt
// grep -v "NINETEEN" dictionary.in
List<Line> lines = grep(Options.v, "NINETEEN", fileToGrep).toLineList();
assertEquals(expectedLineCount, lines.size());
@ -45,9 +45,9 @@ public class GrepWithUnix4JIntegrationTest {
@Test
public void whenGrepWithRegex_thenCorrect() {
int expectedLineCount = 151;
int expectedLineCount = 5;
// grep -c ".*?NINE.*?" dictionary.txt
// grep -c ".*?NINE.*?" dictionary.in
String patternCount = grep(Options.c, ".*?NINE.*?", fileToGrep).cut(fields, ":", 1).toStringResult();
assertEquals(expectedLineCount, Integer.parseInt(patternCount));

View File

@ -0,0 +1,13 @@
EIGHTTEEN
EIGHTTEENS
EIGHTTEENTH
EIGHTTEENTHS
NINETEEN
NINETEENS
NINETEENTH
NINETEENTHS
TWENTY
TWENTHIES
TWENTHIETH
TWENTHIETHS
TWENTYNINETEEN

View File

@ -62,4 +62,5 @@
<target.version>1.8</target.version>
<spring.version>5.3.4</spring.version>
</properties>
</project>

View File

@ -38,7 +38,6 @@
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -91,7 +91,6 @@
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>

View File

@ -27,7 +27,6 @@
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>

View File

@ -33,33 +33,29 @@
<version>${hamcrest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
<version>${icu.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>${commons-text.version}</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<icu.version>64.2</icu.version>
<assertj.version>3.12.2</assertj.version>

View File

@ -4,3 +4,4 @@
- [Java (String) or .toString()?](https://www.baeldung.com/java-string-casting-vs-tostring)
- [Split Java String by Newline](https://www.baeldung.com/java-string-split-by-newline)
- [Split a String in Java and Keep the Delimiters](https://www.baeldung.com/java-split-string-keep-delimiters)
- [Validate String as Filename in Java](https://www.baeldung.com/java-validate-filename)

View File

@ -5,7 +5,6 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>core-java-string-operations-3</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>core-java-string-operations-3</name>
<packaging>jar</packaging>
@ -58,6 +57,13 @@
</plugins>
</build>
<repositories>
<repository>
<id>gradle-repo</id>
<url>https://repo.gradle.org/gradle/libs-releases-local/</url>
</repository>
</repositories>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
@ -68,10 +74,4 @@
<semver4j.version>3.1.0</semver4j.version>
</properties>
<repositories>
<repository>
<id>gradle-repo</id>
<url>https://repo.gradle.org/gradle/libs-releases-local/</url>
</repository>
</repositories>
</project>

View File

@ -0,0 +1,61 @@
package com.baeldung.stringfilenamevalidaiton;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Arrays;
public class StringFilenameValidationUtils {
public static final Character[] INVALID_WINDOWS_SPECIFIC_CHARS = {'"', '*', ':', '<', '>', '?', '\\', '|', 0x7F};
public static final Character[] INVALID_UNIX_SPECIFIC_CHARS = {'\000'};
public static final String REGEX_PATTERN = "^[A-za-z0-9.]{1,255}$";
private StringFilenameValidationUtils() {
}
public static boolean validateStringFilenameUsingIO(String filename) throws IOException {
File file = new File(filename);
boolean created = false;
try {
created = file.createNewFile();
return created;
} finally {
if (created) {
file.delete();
}
}
}
public static boolean validateStringFilenameUsingNIO2(String filename) {
Paths.get(filename);
return true;
}
public static boolean validateStringFilenameUsingContains(String filename) {
if (filename == null || filename.isEmpty() || filename.length() > 255) {
return false;
}
return Arrays.stream(getInvalidCharsByOS())
.noneMatch(ch -> filename.contains(ch.toString()));
}
public static boolean validateStringFilenameUsingRegex(String filename) {
if (filename == null) {
return false;
}
return filename.matches(REGEX_PATTERN);
}
private static Character[] getInvalidCharsByOS() {
String os = System.getProperty("os.name").toLowerCase();
if (os.contains("win")) {
return INVALID_WINDOWS_SPECIFIC_CHARS;
} else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) {
return INVALID_UNIX_SPECIFIC_CHARS;
} else {
return new Character[]{};
}
}
}

View File

@ -0,0 +1,130 @@
package com.baeldung.stringfilenamevalidaiton;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EmptySource;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.NullSource;
import java.io.IOException;
import java.nio.file.InvalidPathException;
import java.util.Arrays;
import java.util.stream.Stream;
import static com.baeldung.stringfilenamevalidaiton.StringFilenameValidationUtils.validateStringFilenameUsingContains;
import static com.baeldung.stringfilenamevalidaiton.StringFilenameValidationUtils.validateStringFilenameUsingIO;
import static com.baeldung.stringfilenamevalidaiton.StringFilenameValidationUtils.validateStringFilenameUsingNIO2;
import static com.baeldung.stringfilenamevalidaiton.StringFilenameValidationUtils.validateStringFilenameUsingRegex;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
public class StringFilenameValidationUnitTest {
private static final String CORRECT_FILENAME_PATTERN = "baeldung.txt";
@ParameterizedTest
@MethodSource("correctAlphanumericFilenamesProvider")
public void givenCorrectAlphanumericRandomFilenameString_whenValidateUsingIO_thenReturnTrue(String filename) throws IOException {
assertThat(validateStringFilenameUsingIO(filename)).isTrue();
assertThat(validateStringFilenameUsingNIO2(filename)).isTrue();
assertThat(validateStringFilenameUsingContains(filename)).isTrue();
assertThat(validateStringFilenameUsingRegex(filename)).isTrue();
}
@Test
public void givenTooLongFileNameString_whenValidate_thenIOAndCustomFailsNIO2Succeed() {
String filename = RandomStringUtils.randomAlphabetic(500);
assertThatThrownBy(() -> validateStringFilenameUsingIO(filename))
.isInstanceOf(IOException.class)
.hasMessageContaining("File name too long");
assertThat(validateStringFilenameUsingNIO2(filename)).isTrue();
assertThat(validateStringFilenameUsingContains(filename)).isFalse();
assertThat(validateStringFilenameUsingRegex(filename)).isFalse();
}
@ParameterizedTest
@NullSource
public void givenNullString_whenValidate_thenFails(String filename) {
assertThatThrownBy(() -> validateStringFilenameUsingIO(filename))
.isInstanceOf(NullPointerException.class);
assertThatThrownBy(() -> validateStringFilenameUsingNIO2(filename))
.isInstanceOf(NullPointerException.class);
assertThat(validateStringFilenameUsingContains(filename)).isFalse();
assertThat(validateStringFilenameUsingRegex(filename)).isFalse();
}
@ParameterizedTest
@EmptySource
public void givenEmptyString_whenValidate_thenIOAndCustomFailsNIO2Succeed(String filename) {
assertThatThrownBy(() -> validateStringFilenameUsingIO(filename))
.isInstanceOf(IOException.class);
assertThat(validateStringFilenameUsingNIO2(filename)).isTrue();
assertThat(validateStringFilenameUsingContains(filename)).isFalse();
assertThat(validateStringFilenameUsingRegex(filename)).isFalse();
}
@ParameterizedTest
@EnabledOnOs({OS.LINUX, OS.MAC})
@MethodSource("filenamesWithInvalidWindowsChars")
public void givenFilenameStringWithInvalidWindowsCharAndIsUnix_whenValidateUsingIO_thenReturnTrue(String filename) throws IOException {
assertThat(validateStringFilenameUsingIO(filename)).isTrue();
assertThat(validateStringFilenameUsingNIO2(filename)).isTrue();
assertThat(validateStringFilenameUsingContains(filename)).isTrue();
}
@ParameterizedTest
@EnabledOnOs(OS.WINDOWS)
@MethodSource("filenamesWithInvalidWindowsChars")
public void givenFilenameStringWithInvalidWindowsCharAndIsWindows_whenValidateUsingIO_thenRaiseException(String filename) {
assertThatThrownBy(() -> validateStringFilenameUsingIO(filename))
.isInstanceOf(IOException.class)
.hasMessageContaining("Invalid file path");
assertThatThrownBy(() -> validateStringFilenameUsingNIO2(filename))
.isInstanceOf(InvalidPathException.class)
.hasMessage("character not allowed");
assertThat(validateStringFilenameUsingContains(filename)).isFalse();
}
@ParameterizedTest
@EnabledOnOs({OS.LINUX, OS.MAC})
@MethodSource("filenamesWithInvalidUnixChars")
public void givenFilenameStringWithInvalidUnixCharAndIsUnix_whenValidate_thenRaiseException(String filename) {
assertThatThrownBy(() -> validateStringFilenameUsingIO(filename))
.isInstanceOf(IOException.class)
.hasMessageContaining("Invalid file path");
assertThatThrownBy(() -> validateStringFilenameUsingNIO2(filename))
.isInstanceOf(InvalidPathException.class)
.hasMessageContaining("character not allowed");
assertThat(validateStringFilenameUsingContains(filename)).isFalse();
}
private static Stream<String> correctAlphanumericFilenamesProvider() {
return Stream.generate(() -> RandomStringUtils.randomAlphanumeric(1, 10) + "." + RandomStringUtils.randomAlphabetic(3, 5)).limit(10);
}
private static Stream<String> filenamesWithInvalidWindowsChars() {
return Arrays.stream(StringFilenameValidationUtils.INVALID_WINDOWS_SPECIFIC_CHARS)
.map(character -> {
int idx = RandomUtils.nextInt(0, CORRECT_FILENAME_PATTERN.length());
return CORRECT_FILENAME_PATTERN.substring(0, idx) + character + CORRECT_FILENAME_PATTERN.substring(idx);
});
}
private static Stream<String> filenamesWithInvalidUnixChars() {
return Arrays.stream(StringFilenameValidationUtils.INVALID_UNIX_SPECIFIC_CHARS)
.map(character -> {
int idx = RandomUtils.nextInt(0, CORRECT_FILENAME_PATTERN.length());
return CORRECT_FILENAME_PATTERN.substring(0, idx) + character + CORRECT_FILENAME_PATTERN.substring(idx);
});
}
}

View File

@ -101,4 +101,5 @@
<properties>
<joda-money.version>1.0.1</joda-money.version>
</properties>
</project>

View File

@ -1,21 +1,21 @@
<?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"
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.baeldung.docker</groupId>
<artifactId>heap-sizing</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>heap-sizing</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
@ -58,4 +58,8 @@
</plugins>
</build>
<properties>
<java.version>11</java.version>
</properties>
</project>

View File

@ -6,7 +6,8 @@
</pattern>
</encoder>
</appender>
<logger name="org.kie.api.internal.utils" level="WARN"/>
<logger name="org.drools.compiler" level="WARN"/>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>

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