From 13da8b8cee14838b28593e55a1878f806ce83c1a Mon Sep 17 00:00:00 2001 From: dupirefr Date: Fri, 2 Aug 2019 08:07:39 +0200 Subject: [PATCH 01/34] [BAEL-3117] XOR implementations --- .../baeldung/java/booleanoperators/Car.java | 20 ++++++ .../java/booleanoperators/XorUnitTest.java | 64 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 core-java-modules/core-java/src/main/java/com/baeldung/java/booleanoperators/Car.java create mode 100644 core-java-modules/core-java/src/test/java/com/baeldung/java/booleanoperators/XorUnitTest.java diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/java/booleanoperators/Car.java b/core-java-modules/core-java/src/main/java/com/baeldung/java/booleanoperators/Car.java new file mode 100644 index 0000000000..8043b6dd93 --- /dev/null +++ b/core-java-modules/core-java/src/main/java/com/baeldung/java/booleanoperators/Car.java @@ -0,0 +1,20 @@ +package com.baeldung.java.booleanoperators; + +public class Car { + + private boolean diesel; + private boolean manual; + + public Car(boolean diesel, boolean manual) { + this.diesel = diesel; + this.manual = manual; + } + + public boolean isDiesel() { + return diesel; + } + + public boolean isManual() { + return manual; + } +} diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/java/booleanoperators/XorUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/java/booleanoperators/XorUnitTest.java new file mode 100644 index 0000000000..0654d07f4f --- /dev/null +++ b/core-java-modules/core-java/src/test/java/com/baeldung/java/booleanoperators/XorUnitTest.java @@ -0,0 +1,64 @@ +package com.baeldung.java.booleanoperators; + +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class XorUnitTest { + + @Test + void givenDieselManualCar_whenXorOldSchool_ThenFalse() { + Car car = new Car(true, true); + boolean dieselXorManual = (car.isDiesel() && !car.isManual()) || (!car.isDiesel() && car.isManual()); + assertThat(dieselXorManual).isFalse(); + } + + @Test + void givenDieselAutomaticCar_whenXorOldSchool_ThenTrue() { + Car car = new Car(true, false); + boolean dieselXorManual = (car.isDiesel() && !car.isManual()) || (!car.isDiesel() && car.isManual()); + assertThat(dieselXorManual).isTrue(); + } + + @Test + void givenNonDieselManualCar_whenXorOldSchool_ThenTrue() { + Car car = new Car(false, true); + boolean dieselXorManual = (car.isDiesel() && !car.isManual()) || (!car.isDiesel() && car.isManual()); + assertThat(dieselXorManual).isTrue(); + } + + @Test + void givenNonDieselAutomaticCar_whenXorOldSchool_ThenFalse() { + Car car = new Car(false, false); + boolean dieselXorManual = (car.isDiesel() && !car.isManual()) || (!car.isDiesel() && car.isManual()); + assertThat(dieselXorManual).isFalse(); + } + + @Test + void givenDieselManualCar_whenXor_ThenFalse() { + Car car = new Car(true, true); + boolean dieselXorManual = car.isDiesel() ^ car.isManual(); + assertThat(dieselXorManual).isFalse(); + } + + @Test + void givenDieselAutomaticCar_whenXor_ThenTrue() { + Car car = new Car(true, false); + boolean dieselXorManual = car.isDiesel() ^ car.isManual(); + assertThat(dieselXorManual).isTrue(); + } + + @Test + void givenNonDieselManualCar_whenXor_ThenTrue() { + Car car = new Car(false, true); + boolean dieselXorManual = car.isDiesel() ^ car.isManual(); + assertThat(dieselXorManual).isTrue(); + } + + @Test + void givenNonDieselAutomaticCar_whenXor_ThenFalse() { + Car car = new Car(false, false); + boolean dieselXorManual = car.isDiesel() ^ car.isManual(); + assertThat(dieselXorManual).isFalse(); + } +} From b01bd36786e5f78c7ade055b556a84731a19505e Mon Sep 17 00:00:00 2001 From: Andrew Shcherbakov Date: Sun, 4 Aug 2019 16:03:12 +0200 Subject: [PATCH 02/34] Add a code on logistic regression article (BAEL-3081) --- ml/README.md | 5 + ml/pom.xml | 52 ++++++ .../com/baeldung/logreg/DataUtilities.java | 102 +++++++++++ .../com/baeldung/logreg/MnistClassifier.java | 166 ++++++++++++++++++ .../com/baeldung/logreg/MnistPrediction.java | 53 ++++++ ml/src/main/resources/logback.xml | 13 ++ pom.xml | 2 + 7 files changed, 393 insertions(+) create mode 100644 ml/README.md create mode 100644 ml/pom.xml create mode 100644 ml/src/main/java/com/baeldung/logreg/DataUtilities.java create mode 100644 ml/src/main/java/com/baeldung/logreg/MnistClassifier.java create mode 100644 ml/src/main/java/com/baeldung/logreg/MnistPrediction.java create mode 100644 ml/src/main/resources/logback.xml diff --git a/ml/README.md b/ml/README.md new file mode 100644 index 0000000000..14e585cd97 --- /dev/null +++ b/ml/README.md @@ -0,0 +1,5 @@ +### Sample deeplearning4j Project +This is a sample project for the [deeplearning4j](https://deeplearning4j.org) library. + +### Relevant Articles: +- [A Guide to Deeplearning4j](http://www.baeldung.com/deeplearning4j) diff --git a/ml/pom.xml b/ml/pom.xml new file mode 100644 index 0000000000..80afcc24f4 --- /dev/null +++ b/ml/pom.xml @@ -0,0 +1,52 @@ + + 4.0.0 + com.baeldung.deeplearning4j + ml + 1.0-SNAPSHOT + Machine Learning + jar + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.nd4j + nd4j-native-platform + ${dl4j.version} + + + org.deeplearning4j + deeplearning4j-core + ${dl4j.version} + + + org.deeplearning4j + deeplearning4j-nn + ${dl4j.version} + + + + org.datavec + datavec-api + ${dl4j.version} + + + org.apache.httpcomponents + httpclient + 4.3.5 + + + + + + + 1.0.0-beta4 + + + \ No newline at end of file diff --git a/ml/src/main/java/com/baeldung/logreg/DataUtilities.java b/ml/src/main/java/com/baeldung/logreg/DataUtilities.java new file mode 100644 index 0000000000..2f18d30219 --- /dev/null +++ b/ml/src/main/java/com/baeldung/logreg/DataUtilities.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) 2015-2019 Skymind, Inc. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ******************************************************************************/ + +package com.baeldung.logreg; + +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; + +import java.io.*; + +/** + * Common data utility functions. + * + * @author fvaleri + */ +public class DataUtilities { + + /** + * Download a remote file if it doesn't exist. + * @param remoteUrl URL of the remote file. + * @param localPath Where to download the file. + * @return True if and only if the file has been downloaded. + * @throws Exception IO error. + */ + public static boolean downloadFile(String remoteUrl, String localPath) throws IOException { + boolean downloaded = false; + if (remoteUrl == null || localPath == null) + return downloaded; + File file = new File(localPath); + if (!file.exists()) { + file.getParentFile().mkdirs(); + HttpClientBuilder builder = HttpClientBuilder.create(); + CloseableHttpClient client = builder.build(); + try (CloseableHttpResponse response = client.execute(new HttpGet(remoteUrl))) { + HttpEntity entity = response.getEntity(); + if (entity != null) { + try (FileOutputStream outstream = new FileOutputStream(file)) { + entity.writeTo(outstream); + outstream.flush(); + outstream.close(); + } + } + } + downloaded = true; + } + if (!file.exists()) + throw new IOException("File doesn't exist: " + localPath); + return downloaded; + } + + /** + * Extract a "tar.gz" file into a local folder. + * @param inputPath Input file path. + * @param outputPath Output directory path. + * @throws IOException IO error. + */ + public static void extractTarGz(String inputPath, String outputPath) throws IOException { + if (inputPath == null || outputPath == null) + return; + final int bufferSize = 4096; + if (!outputPath.endsWith("" + File.separatorChar)) + outputPath = outputPath + File.separatorChar; + try (TarArchiveInputStream tais = new TarArchiveInputStream( + new GzipCompressorInputStream(new BufferedInputStream(new FileInputStream(inputPath))))) { + TarArchiveEntry entry; + while ((entry = (TarArchiveEntry) tais.getNextEntry()) != null) { + if (entry.isDirectory()) { + new File(outputPath + entry.getName()).mkdirs(); + } else { + int count; + byte data[] = new byte[bufferSize]; + FileOutputStream fos = new FileOutputStream(outputPath + entry.getName()); + BufferedOutputStream dest = new BufferedOutputStream(fos, bufferSize); + while ((count = tais.read(data, 0, bufferSize)) != -1) { + dest.write(data, 0, count); + } + dest.close(); + } + } + } + } + +} diff --git a/ml/src/main/java/com/baeldung/logreg/MnistClassifier.java b/ml/src/main/java/com/baeldung/logreg/MnistClassifier.java new file mode 100644 index 0000000000..395307712d --- /dev/null +++ b/ml/src/main/java/com/baeldung/logreg/MnistClassifier.java @@ -0,0 +1,166 @@ +package com.baeldung.logreg; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.Random; + +import org.datavec.api.io.labels.ParentPathLabelGenerator; +import org.datavec.api.split.FileSplit; +import org.datavec.image.loader.NativeImageLoader; +import org.datavec.image.recordreader.ImageRecordReader; +import org.deeplearning4j.datasets.datavec.RecordReaderDataSetIterator; +import org.deeplearning4j.nn.conf.MultiLayerConfiguration; +import org.deeplearning4j.nn.conf.NeuralNetConfiguration; +import org.deeplearning4j.nn.conf.inputs.InputType; +import org.deeplearning4j.nn.conf.layers.ConvolutionLayer; +import org.deeplearning4j.nn.conf.layers.DenseLayer; +import org.deeplearning4j.nn.conf.layers.OutputLayer; +import org.deeplearning4j.nn.conf.layers.SubsamplingLayer; +import org.deeplearning4j.nn.multilayer.MultiLayerNetwork; +import org.deeplearning4j.nn.weights.WeightInit; +import org.deeplearning4j.optimize.listeners.ScoreIterationListener; +import org.deeplearning4j.util.ModelSerializer; +import org.nd4j.evaluation.classification.Evaluation; +import org.nd4j.linalg.activations.Activation; +import org.nd4j.linalg.dataset.api.iterator.DataSetIterator; +import org.nd4j.linalg.dataset.api.preprocessor.DataNormalization; +import org.nd4j.linalg.dataset.api.preprocessor.ImagePreProcessingScaler; +import org.nd4j.linalg.learning.config.Nesterovs; +import org.nd4j.linalg.lossfunctions.LossFunctions; +import org.nd4j.linalg.schedule.MapSchedule; +import org.nd4j.linalg.schedule.ScheduleType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Handwritten digit image classification based on LeNet-5 architecture by Yann LeCun. + * + * This code accompanies the article "Logistic regression in Java" and is heavily based on + * MnistClassifier. + * Some minor changes have been made in order to make article's flow smoother. + * + */ + +public class MnistClassifier { + private static final Logger logger = LoggerFactory.getLogger(MnistClassifier.class); + private static final String basePath = System.getProperty("java.io.tmpdir") + "mnist" + File.separator; + private static final File modelPath = new File(basePath + "mnist-model.zip"); + private static final String dataUrl = "http://github.com/myleott/mnist_png/raw/master/mnist_png.tar.gz"; + + public static void main(String[] args) throws Exception { + // input image sizes in pixels + int height = 28; + int width = 28; + // input image colour depth (1 for gray scale images) + int channels = 1; + // the number of output classes + int outputClasses = 10; + // number of samples that will be propagated through the network in each iteration + int batchSize = 54; + // total number of training epochs + int epochs = 1; + + // initialize a pseudorandom number generator + int seed = 1234; + Random randNumGen = new Random(seed); + + final String path = basePath + "mnist_png" + File.separator; + if (!new File(path).exists()) { + logger.debug("Downloading data {}", dataUrl); + String localFilePath = basePath + "mnist_png.tar.gz"; + logger.info("local file: {}", localFilePath); + if (DataUtilities.downloadFile(dataUrl, localFilePath)) { + DataUtilities.extractTarGz(localFilePath, basePath); + } + } else { + logger.info("local file exists {}", path); + + } + + logger.info("Vectorizing data..."); + // vectorization of train data + File trainData = new File(path + "training"); + FileSplit trainSplit = new FileSplit(trainData, NativeImageLoader.ALLOWED_FORMATS, randNumGen); + // use parent directory name as the image label + ParentPathLabelGenerator labelMaker = new ParentPathLabelGenerator(); + ImageRecordReader trainRR = new ImageRecordReader(height, width, channels, labelMaker); + trainRR.initialize(trainSplit); + DataSetIterator train = new RecordReaderDataSetIterator(trainRR, batchSize, 1, outputClasses); + + // pixel values from 0-255 to 0-1 (min-max scaling) + DataNormalization imageScaler = new ImagePreProcessingScaler(); + imageScaler.fit(train); + train.setPreProcessor(imageScaler); + + // vectorization of test data + File testData = new File(path + "testing"); + FileSplit testSplit = new FileSplit(testData, NativeImageLoader.ALLOWED_FORMATS, randNumGen); + ImageRecordReader testRR = new ImageRecordReader(height, width, channels, labelMaker); + testRR.initialize(testSplit); + DataSetIterator test = new RecordReaderDataSetIterator(testRR, batchSize, 1, outputClasses); + // same normalization for better results + test.setPreProcessor(imageScaler); + + logger.info("Network configuration and training..."); + // reduce the learning rate as the number of training epochs increases + // iteration #, learning rate + Map learningRateSchedule = new HashMap<>(); + learningRateSchedule.put(0, 0.06); + learningRateSchedule.put(200, 0.05); + learningRateSchedule.put(600, 0.028); + learningRateSchedule.put(800, 0.0060); + learningRateSchedule.put(1000, 0.001); + + final ConvolutionLayer layer1 = new ConvolutionLayer.Builder(5, 5).nIn(channels) + .stride(1, 1) + .nOut(20) + .activation(Activation.IDENTITY) + .build(); + final SubsamplingLayer layer2 = new SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.MAX).kernelSize(2, 2) + .stride(2, 2) + .build(); + // nIn need not specified in later layers + final ConvolutionLayer layer3 = new ConvolutionLayer.Builder(5, 5).stride(1, 1) + .nOut(50) + .activation(Activation.IDENTITY) + .build(); + final DenseLayer layer4 = new DenseLayer.Builder().activation(Activation.RELU) + .nOut(500) + .build(); + final OutputLayer layer5 = new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD).nOut(outputClasses) + .activation(Activation.SOFTMAX) + .build(); + final MultiLayerConfiguration config = new NeuralNetConfiguration.Builder().seed(seed) + .l2(0.0005) // ridge regression value + .updater(new Nesterovs(new MapSchedule(ScheduleType.ITERATION, learningRateSchedule))) + .weightInit(WeightInit.XAVIER) + .list() + .layer(layer1) + .layer(layer2) + .layer(layer3) + .layer(layer2) + .layer(layer4) + .layer(layer5) + .setInputType(InputType.convolutionalFlat(height, width, channels)) + .build(); + + final MultiLayerNetwork model = new MultiLayerNetwork(config); + model.init(); + model.setListeners(new ScoreIterationListener(100)); + logger.info("Total num of params: {}", model.numParams()); + + // evaluation while training (the score should go down) + for (int i = 0; i < epochs; i++) { + model.fit(train); + logger.info("Completed epoch {}", i); + train.reset(); + test.reset(); + } + Evaluation eval = model.evaluate(test); + logger.info(eval.stats()); + + ModelSerializer.writeModel(model, modelPath, true); + logger.info("The MINIST model has been saved in {}", modelPath.getPath()); + } +} \ No newline at end of file diff --git a/ml/src/main/java/com/baeldung/logreg/MnistPrediction.java b/ml/src/main/java/com/baeldung/logreg/MnistPrediction.java new file mode 100644 index 0000000000..5ec1348e07 --- /dev/null +++ b/ml/src/main/java/com/baeldung/logreg/MnistPrediction.java @@ -0,0 +1,53 @@ +package com.baeldung.logreg; + +import java.io.File; +import java.io.IOException; + +import javax.swing.JFileChooser; + +import org.datavec.image.loader.NativeImageLoader; +import org.deeplearning4j.nn.multilayer.MultiLayerNetwork; +import org.deeplearning4j.util.ModelSerializer; +import org.nd4j.linalg.api.ndarray.INDArray; +import org.nd4j.linalg.dataset.api.preprocessor.ImagePreProcessingScaler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MnistPrediction { + private static final Logger logger = LoggerFactory.getLogger(MnistPrediction.class); + private static final File modelPath = new File(System.getProperty("java.io.tmpdir") + "mnist" + File.separator + "mnist-model.zip"); + private static final int height = 28; + private static final int width = 28; + private static final int channels = 1; + + /** + * Opens a popup that allows to select a file from the filesystem. + * @return + */ + public static String fileChose() { + JFileChooser fc = new JFileChooser(); + int ret = fc.showOpenDialog(null); + if (ret == JFileChooser.APPROVE_OPTION) { + File file = fc.getSelectedFile(); + return file.getAbsolutePath(); + } else { + return null; + } + } + + public static void main(String[] args) throws IOException { + String path = fileChose().toString(); + MultiLayerNetwork model = ModelSerializer.restoreMultiLayerNetwork(modelPath); + File file = new File(path); + + INDArray image = new NativeImageLoader(height, width, channels).asMatrix(file); + new ImagePreProcessingScaler(0, 1).transform(image); + + // Pass through to neural Net + INDArray output = model.output(image); + + logger.info("File: {}", path); + logger.info(output.toString()); + } + +} diff --git a/ml/src/main/resources/logback.xml b/ml/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/ml/src/main/resources/logback.xml @@ -0,0 +1,13 @@ + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 352da33fee..7e9ce85b50 100644 --- a/pom.xml +++ b/pom.xml @@ -524,6 +524,7 @@ metrics microprofile + ml msf4j mustache @@ -1216,6 +1217,7 @@ metrics microprofile + ml msf4j mustache From 0527d816ccebe352c858c329178517c6d9519649 Mon Sep 17 00:00:00 2001 From: Andrew Shcherbakov Date: Sun, 4 Aug 2019 16:09:01 +0200 Subject: [PATCH 03/34] Update Readme file --- ml/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ml/README.md b/ml/README.md index 14e585cd97..f4712a94da 100644 --- a/ml/README.md +++ b/ml/README.md @@ -1,5 +1,5 @@ -### Sample deeplearning4j Project -This is a sample project for the [deeplearning4j](https://deeplearning4j.org) library. +### Logistic Regression in Java +This is a soft introduction to ML using [deeplearning4j](https://deeplearning4j.org) library ### Relevant Articles: -- [A Guide to Deeplearning4j](http://www.baeldung.com/deeplearning4j) +- [Logistic Regression in Java](http://www.baeldung.com/) From fc16a4707843e59af9c0fe4a1076a3d2e4ca9546 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Sat, 10 Aug 2019 11:51:15 +0200 Subject: [PATCH 04/34] Added factory methods to create cars --- .../com/baeldung/java/booleanoperators/Car.java | 16 ++++++++++++++++ .../java/booleanoperators/XorUnitTest.java | 16 ++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/java/booleanoperators/Car.java b/core-java-modules/core-java/src/main/java/com/baeldung/java/booleanoperators/Car.java index 8043b6dd93..7394895325 100644 --- a/core-java-modules/core-java/src/main/java/com/baeldung/java/booleanoperators/Car.java +++ b/core-java-modules/core-java/src/main/java/com/baeldung/java/booleanoperators/Car.java @@ -17,4 +17,20 @@ public class Car { public boolean isManual() { return manual; } + + static Car dieselAndManualCar() { + return new Car(true, true); + } + + static Car dieselAndAutomaticCar() { + return new Car(true, false); + } + + static Car oilAndManualCar() { + return new Car(false, true); + } + + static Car oilAndAutomaticCar() { + return new Car(false, false); + } } diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/java/booleanoperators/XorUnitTest.java b/core-java-modules/core-java/src/test/java/com/baeldung/java/booleanoperators/XorUnitTest.java index 0654d07f4f..70abc0266d 100644 --- a/core-java-modules/core-java/src/test/java/com/baeldung/java/booleanoperators/XorUnitTest.java +++ b/core-java-modules/core-java/src/test/java/com/baeldung/java/booleanoperators/XorUnitTest.java @@ -8,56 +8,56 @@ class XorUnitTest { @Test void givenDieselManualCar_whenXorOldSchool_ThenFalse() { - Car car = new Car(true, true); + Car car = Car.dieselAndManualCar(); boolean dieselXorManual = (car.isDiesel() && !car.isManual()) || (!car.isDiesel() && car.isManual()); assertThat(dieselXorManual).isFalse(); } @Test void givenDieselAutomaticCar_whenXorOldSchool_ThenTrue() { - Car car = new Car(true, false); + Car car = Car.dieselAndAutomaticCar(); boolean dieselXorManual = (car.isDiesel() && !car.isManual()) || (!car.isDiesel() && car.isManual()); assertThat(dieselXorManual).isTrue(); } @Test void givenNonDieselManualCar_whenXorOldSchool_ThenTrue() { - Car car = new Car(false, true); + Car car = Car.oilAndManualCar(); boolean dieselXorManual = (car.isDiesel() && !car.isManual()) || (!car.isDiesel() && car.isManual()); assertThat(dieselXorManual).isTrue(); } @Test void givenNonDieselAutomaticCar_whenXorOldSchool_ThenFalse() { - Car car = new Car(false, false); + Car car = Car.oilAndAutomaticCar(); boolean dieselXorManual = (car.isDiesel() && !car.isManual()) || (!car.isDiesel() && car.isManual()); assertThat(dieselXorManual).isFalse(); } @Test void givenDieselManualCar_whenXor_ThenFalse() { - Car car = new Car(true, true); + Car car = Car.dieselAndManualCar(); boolean dieselXorManual = car.isDiesel() ^ car.isManual(); assertThat(dieselXorManual).isFalse(); } @Test void givenDieselAutomaticCar_whenXor_ThenTrue() { - Car car = new Car(true, false); + Car car = Car.dieselAndAutomaticCar(); boolean dieselXorManual = car.isDiesel() ^ car.isManual(); assertThat(dieselXorManual).isTrue(); } @Test void givenNonDieselManualCar_whenXor_ThenTrue() { - Car car = new Car(false, true); + Car car = Car.oilAndManualCar(); boolean dieselXorManual = car.isDiesel() ^ car.isManual(); assertThat(dieselXorManual).isTrue(); } @Test void givenNonDieselAutomaticCar_whenXor_ThenFalse() { - Car car = new Car(false, false); + Car car = Car.oilAndAutomaticCar(); boolean dieselXorManual = car.isDiesel() ^ car.isManual(); assertThat(dieselXorManual).isFalse(); } From 72a108f960896c282bf1e4dd4dedb6bbfc3c29f5 Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Fri, 23 Aug 2019 00:23:46 +0200 Subject: [PATCH 05/34] Drop last 4 bytes of computed SHA-1 hash --- .../src/main/java/com/baeldung/uuid/UUIDGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java b/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java index dcf186de93..70217cd556 100644 --- a/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java +++ b/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java @@ -67,7 +67,7 @@ public class UUIDGenerator { } catch (NoSuchAlgorithmException nsae) { throw new InternalError("MD5 not supported", nsae); } - byte[] bytes = md.digest(name); + byte[] bytes = Arrays.copyOfRange(md.digest(name), 0, 16); bytes[6] &= 0x0f; /* clear version */ bytes[6] |= 0x50; /* set to version 5 */ bytes[8] &= 0x3f; /* clear variant */ From ad54ac6f5e569654f72d29d961bf6f3a16edfb1d Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Fri, 23 Aug 2019 00:29:27 +0200 Subject: [PATCH 06/34] Fix message for exception --- .../src/main/java/com/baeldung/uuid/UUIDGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java b/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java index 70217cd556..c4663a429c 100644 --- a/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java +++ b/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java @@ -65,7 +65,7 @@ public class UUIDGenerator { try { md = MessageDigest.getInstance("SHA-1"); } catch (NoSuchAlgorithmException nsae) { - throw new InternalError("MD5 not supported", nsae); + throw new InternalError("SHA-1 not supported", nsae); } byte[] bytes = Arrays.copyOfRange(md.digest(name), 0, 16); bytes[6] &= 0x0f; /* clear version */ From d78101176260809e5c0280650914ec08d570a87d Mon Sep 17 00:00:00 2001 From: dupirefr Date: Tue, 27 Aug 2019 07:36:52 +0200 Subject: [PATCH 07/34] [BAEL-3117] Moved code into operators module --- .../src/main/java/com/baeldung}/booleanoperators/Car.java | 2 +- .../test/java/com/baeldung}/booleanoperators/XorUnitTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename core-java-modules/{core-java/src/main/java/com/baeldung/java => core-java-lang-operators/src/main/java/com/baeldung}/booleanoperators/Car.java (93%) rename core-java-modules/{core-java/src/test/java/com/baeldung/java => core-java-lang-operators/src/test/java/com/baeldung}/booleanoperators/XorUnitTest.java (98%) diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/java/booleanoperators/Car.java b/core-java-modules/core-java-lang-operators/src/main/java/com/baeldung/booleanoperators/Car.java similarity index 93% rename from core-java-modules/core-java/src/main/java/com/baeldung/java/booleanoperators/Car.java rename to core-java-modules/core-java-lang-operators/src/main/java/com/baeldung/booleanoperators/Car.java index 7394895325..37fb139917 100644 --- a/core-java-modules/core-java/src/main/java/com/baeldung/java/booleanoperators/Car.java +++ b/core-java-modules/core-java-lang-operators/src/main/java/com/baeldung/booleanoperators/Car.java @@ -1,4 +1,4 @@ -package com.baeldung.java.booleanoperators; +package com.baeldung.booleanoperators; public class Car { diff --git a/core-java-modules/core-java/src/test/java/com/baeldung/java/booleanoperators/XorUnitTest.java b/core-java-modules/core-java-lang-operators/src/test/java/com/baeldung/booleanoperators/XorUnitTest.java similarity index 98% rename from core-java-modules/core-java/src/test/java/com/baeldung/java/booleanoperators/XorUnitTest.java rename to core-java-modules/core-java-lang-operators/src/test/java/com/baeldung/booleanoperators/XorUnitTest.java index 70abc0266d..e3cee4888a 100644 --- a/core-java-modules/core-java/src/test/java/com/baeldung/java/booleanoperators/XorUnitTest.java +++ b/core-java-modules/core-java-lang-operators/src/test/java/com/baeldung/booleanoperators/XorUnitTest.java @@ -1,4 +1,4 @@ -package com.baeldung.java.booleanoperators; +package com.baeldung.booleanoperators; import org.junit.jupiter.api.Test; From 1b0dea74f6b37fd9083764a90799831b7d3ea1f7 Mon Sep 17 00:00:00 2001 From: dupirefr Date: Tue, 27 Aug 2019 07:55:16 +0200 Subject: [PATCH 08/34] [BAEL-3117] Added integer xor --- .../booleanoperators/XorUnitTest.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/core-java-modules/core-java-lang-operators/src/test/java/com/baeldung/booleanoperators/XorUnitTest.java b/core-java-modules/core-java-lang-operators/src/test/java/com/baeldung/booleanoperators/XorUnitTest.java index e3cee4888a..efe38c6f45 100644 --- a/core-java-modules/core-java-lang-operators/src/test/java/com/baeldung/booleanoperators/XorUnitTest.java +++ b/core-java-modules/core-java-lang-operators/src/test/java/com/baeldung/booleanoperators/XorUnitTest.java @@ -7,58 +7,63 @@ import static org.assertj.core.api.Assertions.assertThat; class XorUnitTest { @Test - void givenDieselManualCar_whenXorOldSchool_ThenFalse() { + void givenDieselManualCar_whenXorOldSchool_thenFalse() { Car car = Car.dieselAndManualCar(); boolean dieselXorManual = (car.isDiesel() && !car.isManual()) || (!car.isDiesel() && car.isManual()); assertThat(dieselXorManual).isFalse(); } @Test - void givenDieselAutomaticCar_whenXorOldSchool_ThenTrue() { + void givenDieselAutomaticCar_whenXorOldSchool_thenTrue() { Car car = Car.dieselAndAutomaticCar(); boolean dieselXorManual = (car.isDiesel() && !car.isManual()) || (!car.isDiesel() && car.isManual()); assertThat(dieselXorManual).isTrue(); } @Test - void givenNonDieselManualCar_whenXorOldSchool_ThenTrue() { + void givenNonDieselManualCar_whenXorOldSchool_thenTrue() { Car car = Car.oilAndManualCar(); boolean dieselXorManual = (car.isDiesel() && !car.isManual()) || (!car.isDiesel() && car.isManual()); assertThat(dieselXorManual).isTrue(); } @Test - void givenNonDieselAutomaticCar_whenXorOldSchool_ThenFalse() { + void givenNonDieselAutomaticCar_whenXorOldSchool_thenFalse() { Car car = Car.oilAndAutomaticCar(); boolean dieselXorManual = (car.isDiesel() && !car.isManual()) || (!car.isDiesel() && car.isManual()); assertThat(dieselXorManual).isFalse(); } @Test - void givenDieselManualCar_whenXor_ThenFalse() { + void givenDieselManualCar_whenXor_thenFalse() { Car car = Car.dieselAndManualCar(); boolean dieselXorManual = car.isDiesel() ^ car.isManual(); assertThat(dieselXorManual).isFalse(); } @Test - void givenDieselAutomaticCar_whenXor_ThenTrue() { + void givenDieselAutomaticCar_whenXor_thenTrue() { Car car = Car.dieselAndAutomaticCar(); boolean dieselXorManual = car.isDiesel() ^ car.isManual(); assertThat(dieselXorManual).isTrue(); } @Test - void givenNonDieselManualCar_whenXor_ThenTrue() { + void givenNonDieselManualCar_whenXor_thenTrue() { Car car = Car.oilAndManualCar(); boolean dieselXorManual = car.isDiesel() ^ car.isManual(); assertThat(dieselXorManual).isTrue(); } @Test - void givenNonDieselAutomaticCar_whenXor_ThenFalse() { + void givenNonDieselAutomaticCar_whenXor_thenFalse() { Car car = Car.oilAndAutomaticCar(); boolean dieselXorManual = car.isDiesel() ^ car.isManual(); assertThat(dieselXorManual).isFalse(); } + + @Test + void givenNumbersOneAndThree_whenXor_thenTwo() { + assertThat(1 ^ 3).isEqualTo(2); + } } From 62eb0f742861df6122bba8812449e92d07948ce1 Mon Sep 17 00:00:00 2001 From: maryarm Date: Wed, 28 Aug 2019 20:00:29 +0430 Subject: [PATCH 09/34] BAEL-3009: Logging Spring WebClient calls --- spring-5-reactive-client/pom.xml | 12 +- .../WebClientLoggingIntegrationTest.java | 150 ++++++++++++++++++ .../reactive/logging/filters/LogFilters.java | 33 ++++ .../logging/jetty/RequestLogEnhancer.java | 88 ++++++++++ .../reactive/logging/netty/CustomLogger.java | 37 +++++ .../src/test/resources/logback-test.xml | 8 +- 6 files changed, 324 insertions(+), 4 deletions(-) create mode 100644 spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java create mode 100644 spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java create mode 100644 spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java create mode 100644 spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java diff --git a/spring-5-reactive-client/pom.xml b/spring-5-reactive-client/pom.xml index 1b71815eb4..5e9fdd9fb4 100644 --- a/spring-5-reactive-client/pom.xml +++ b/spring-5-reactive-client/pom.xml @@ -1,6 +1,6 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-5-reactive-client spring-5-reactive-client @@ -56,7 +56,6 @@ - org.springframework.boot spring-boot-devtools @@ -89,6 +88,14 @@ org.projectlombok lombok + + + + org.eclipse.jetty + jetty-reactive-httpclient + ${jetty-reactive-httpclient.version} + test + @@ -110,6 +117,7 @@ 1.0 1.0 4.1 + 1.0.3 diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java new file mode 100644 index 0000000000..bb88502132 --- /dev/null +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java @@ -0,0 +1,150 @@ +package com.baeldung.reactive.logging; + +import ch.qos.logback.classic.spi.LoggingEvent; +import ch.qos.logback.core.Appender; +import com.baeldung.reactive.logging.filters.LogFilters; +import com.baeldung.reactive.logging.jetty.RequestLogEnhancer; +import com.baeldung.reactive.logging.netty.CustomLogger; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.net.URI; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.slf4j.LoggerFactory; +import org.springframework.http.client.reactive.JettyClientHttpConnector; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.netty.channel.BootstrapHandlers; +import reactor.netty.http.client.HttpClient; + +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + + +public class WebClientLoggingIntegrationTest { + + @AllArgsConstructor + @Data + class Post { + private String title; + private String body; + private int userId; + } + + private Appender jettyAppender; + private Appender nettyAppender; + private Appender mockAppender; + private String sampleUrl = "https://jsonplaceholder.typicode.com/posts"; + + private Post post; + private String sampleResponseBody; + + @BeforeEach + private void setup() throws Exception { + + post = new Post("Learn WebClient logging with Baeldung!", "", 1); + sampleResponseBody = new ObjectMapper().writeValueAsString(post); + + ch.qos.logback.classic.Logger jetty = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.baeldung.reactive.logging.jetty"); + jettyAppender = mock(Appender.class); + when(jettyAppender.getName()).thenReturn("com.baeldung.reactive.logging.jetty"); + jetty.addAppender(jettyAppender); + + ch.qos.logback.classic.Logger netty = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("reactor.netty.http.client"); + nettyAppender = mock(Appender.class); + when(nettyAppender.getName()).thenReturn("reactor.netty.http.client"); + netty.addAppender(nettyAppender); + + ch.qos.logback.classic.Logger test = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger("com.baeldung.reactive"); + mockAppender = mock(Appender.class); + when(mockAppender.getName()).thenReturn("com.baeldung.reactive"); + test.addAppender(mockAppender); + + } + + @Test + public void givenJettyHttpClient_whenEndpointIsConsumed_thenRequestAndResponseBodyShouldBeLogged() { + SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); + org.eclipse.jetty.client.HttpClient httpClient = new org.eclipse.jetty.client.HttpClient(sslContextFactory) { + @Override + public Request newRequest(URI uri) { + Request request = super.newRequest(uri); + return new RequestLogEnhancer().enhance(request); + } + }; + + WebClient + .builder() + .clientConnector(new JettyClientHttpConnector(httpClient)) + .build() + .post() + .uri(sampleUrl) + .body(BodyInserters.fromObject(post)) + .retrieve() + .bodyToMono(String.class) + .block(); + + verify(jettyAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains(sampleResponseBody))); + } + + @Test + public void givenNettyHttpClientWithWiretap_whenEndpointIsConsumed_thenRequestAndResponseBodyShouldBeLogged() { + + reactor.netty.http.client.HttpClient httpClient = HttpClient + .create() + .wiretap(true); + WebClient + .builder() + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .build() + .post() + .uri(sampleUrl) + .body(BodyInserters.fromObject(post)) + .exchange() + .block(); + verify(nettyAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains("00000300"))); + } + + @Test + public void givenNettyHttpClientWithCustomLogger_whenEndpointIsConsumed_thenRequestAndResponseBodyShouldBeLogged() { + + reactor.netty.http.client.HttpClient httpClient = HttpClient + .create() + .tcpConfiguration(tcpClient -> tcpClient.bootstrap(b -> BootstrapHandlers.updateLogSupport(b, new CustomLogger(HttpClient.class)))); + WebClient + .builder() + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .build() + .post() + .uri(sampleUrl) + .body(BodyInserters.fromObject(post)) + .exchange() + .block(); + verify(nettyAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains(sampleResponseBody))); + } + + @Test + public void givenDefaultHttpClientWithString_whenEndpointIsConsumed_thenRequestAndResponseLogged() { + WebClient + .builder() + .filters(exchangeFilterFunctions -> { + exchangeFilterFunctions.addAll(LogFilters.prepareFilters()); + }) + .build() + .post() + .uri(sampleUrl) + .body(BodyInserters.fromObject(post)) + .exchange() + .block(); + + verify(mockAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains("domain=.typicode.com;"))); + } + + +} diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java new file mode 100644 index 0000000000..8bb4c2aecd --- /dev/null +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java @@ -0,0 +1,33 @@ +package com.baeldung.reactive.logging.filters; + +import java.util.Arrays; +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; +import reactor.core.publisher.Mono; + +@Slf4j +public class LogFilters { + public static List prepareFilters(){ + return Arrays.asList(ExchangeFilterFunction.ofRequestProcessor(clientRequest -> { + if ( log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder("Request: \n").append(clientRequest.method()).append(" ").append(clientRequest.url()); + clientRequest + .headers() + .forEach((name, values) -> values.forEach(value -> sb.append("\n").append(name).append(":").append(value))); + log.debug(sb.toString()); + } + return Mono.just(clientRequest); + }), ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { + if ( log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder("Response: \n").append("Status: ").append(clientResponse.rawStatusCode()); + clientResponse + .headers() + .asHttpHeaders() + .forEach((key, value1) -> value1.forEach(value -> sb.append("\n").append(key).append(":").append(value))); + log.debug(sb.toString()); + } + return Mono.just(clientResponse); + })); + } +} diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java new file mode 100644 index 0000000000..334faf2c91 --- /dev/null +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java @@ -0,0 +1,88 @@ +package com.baeldung.reactive.logging.jetty; + +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Locale; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.http.HttpField; +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpHeader; + +@Slf4j +public class RequestLogEnhancer { + + public Request enhance(Request request) { + StringBuilder group = new StringBuilder(); + request.onRequestBegin(theRequest -> group + .append("Request ") + .append(theRequest.getMethod()) + .append(" ") + .append(theRequest.getURI()) + .append("\n")); + request.onRequestHeaders(theRequest -> { + for (HttpField header : theRequest.getHeaders()) + group + .append(header) + .append("\n"); + }); + request.onRequestContent((theRequest, content) -> group.append(toString(content, getCharset(theRequest.getHeaders())))); + request.onRequestSuccess(theRequest -> { + log.debug(group.toString()); + group.delete(0, group.length()); + }); + group.append("\n"); + request.onResponseBegin(theResponse -> { + group + .append("Response \n ") + .append(theResponse.getVersion()) + .append(" ") + .append(theResponse.getStatus()); + if (theResponse.getReason() != null) group + .append(" ") + .append(theResponse.getReason()); + group.append("\n"); + }); + request.onResponseHeaders(theResponse -> { + for (HttpField header : theResponse.getHeaders()) + group + .append(header) + .append("\n"); + }); + request.onResponseContent((theResponse, content) -> group.append(toString(content, getCharset(theResponse.getHeaders())))); + request.onResponseSuccess(theResponse -> { + log.debug(group.toString()); + }); + return request; + } + + + private String toString(ByteBuffer buffer, Charset charset) + { + byte[] bytes; + if (buffer.hasArray()) { + bytes = new byte[buffer.capacity()]; + System.arraycopy(buffer.array(), 0, bytes, 0, buffer.capacity() ); + } + else + { + bytes = new byte[buffer.remaining()]; + buffer.get(bytes, 0, bytes.length); + } + return new String(bytes, charset); + } + + + private Charset getCharset(HttpFields headers) { + String contentType = headers.get(HttpHeader.CONTENT_TYPE); + if (contentType == null) return StandardCharsets.UTF_8; + String[] tokens = contentType + .toLowerCase(Locale.US) + .split("charset="); + if (tokens.length != 2) return StandardCharsets.UTF_8; + String encoding = tokens[1].replaceAll("[;\"]", ""); + return Charset.forName(encoding); + } +} + diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java new file mode 100644 index 0000000000..df7c65f33f --- /dev/null +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java @@ -0,0 +1,37 @@ +package com.baeldung.reactive.logging.netty; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.logging.LoggingHandler; +import io.netty.util.internal.PlatformDependent; +import java.nio.charset.Charset; + +public class CustomLogger extends LoggingHandler { + public CustomLogger(Class clazz) { + super(clazz); + } + + @Override + protected String format(ChannelHandlerContext ctx, String eventName, Object arg) { + if (arg instanceof ByteBuf) { + ByteBuf msg = (ByteBuf) arg; + return decodeString(msg, msg.readerIndex(), msg.readableBytes(), Charset.defaultCharset()); + } + return ""; + } + + private String decodeString(ByteBuf src, int readerIndex, int len, Charset charset) { + if (len == 0) return ""; + byte[] array; + int offset; + if (src.hasArray()) { + array = src.array(); + offset = src.arrayOffset() + readerIndex; + } else { + array = PlatformDependent.allocateUninitializedArray(Math.max(len, 1024)); + offset = 0; + src.getBytes(readerIndex, array, 0, len); + } + return new String(array, offset, len, charset); + } +} diff --git a/spring-5-reactive-client/src/test/resources/logback-test.xml b/spring-5-reactive-client/src/test/resources/logback-test.xml index 7072369b8d..42cb0865c5 100644 --- a/spring-5-reactive-client/src/test/resources/logback-test.xml +++ b/spring-5-reactive-client/src/test/resources/logback-test.xml @@ -6,11 +6,15 @@ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n - + + + + + - + \ No newline at end of file From 52a90adf92e086cab6d2900064ed257f9ca070d8 Mon Sep 17 00:00:00 2001 From: maryarm Date: Thu, 29 Aug 2019 16:25:30 +0430 Subject: [PATCH 10/34] BAEL-3009: Apply review notes and formatting standards. --- spring-5-reactive-client/pom.xml | 2 +- .../WebClientLoggingIntegrationTest.java | 4 +- .../reactive/logging/filters/LogFilters.java | 41 +++++++++++++---- .../logging/jetty/RequestLogEnhancer.java | 46 ++++++++++--------- .../reactive/logging/netty/CustomLogger.java | 35 ++++++++------ 5 files changed, 80 insertions(+), 48 deletions(-) diff --git a/spring-5-reactive-client/pom.xml b/spring-5-reactive-client/pom.xml index 5e9fdd9fb4..70771f6832 100644 --- a/spring-5-reactive-client/pom.xml +++ b/spring-5-reactive-client/pom.xml @@ -1,6 +1,6 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 spring-5-reactive-client spring-5-reactive-client diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java index bb88502132..d5f1ef77a0 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java @@ -116,7 +116,9 @@ public class WebClientLoggingIntegrationTest { reactor.netty.http.client.HttpClient httpClient = HttpClient .create() - .tcpConfiguration(tcpClient -> tcpClient.bootstrap(b -> BootstrapHandlers.updateLogSupport(b, new CustomLogger(HttpClient.class)))); + .tcpConfiguration( + tc -> tc.bootstrap( + b -> BootstrapHandlers.updateLogSupport(b, new CustomLogger(HttpClient.class)))); WebClient .builder() .clientConnector(new ReactorClientHttpConnector(httpClient)) diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java index 8bb4c2aecd..c1c3d3e895 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/filters/LogFilters.java @@ -8,26 +8,47 @@ import reactor.core.publisher.Mono; @Slf4j public class LogFilters { - public static List prepareFilters(){ - return Arrays.asList(ExchangeFilterFunction.ofRequestProcessor(clientRequest -> { - if ( log.isDebugEnabled()) { - StringBuilder sb = new StringBuilder("Request: \n").append(clientRequest.method()).append(" ").append(clientRequest.url()); + public static List prepareFilters() { + return Arrays.asList(logRequest(), logResponse()); + } + + private static ExchangeFilterFunction logRequest() { + return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> { + if (log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder("Request: \n") + .append(clientRequest.method()) + .append(" ") + .append(clientRequest.url()); clientRequest .headers() - .forEach((name, values) -> values.forEach(value -> sb.append("\n").append(name).append(":").append(value))); + .forEach((name, values) -> values.forEach(value -> sb + .append("\n") + .append(name) + .append(":") + .append(value))); log.debug(sb.toString()); } return Mono.just(clientRequest); - }), ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { - if ( log.isDebugEnabled()) { - StringBuilder sb = new StringBuilder("Response: \n").append("Status: ").append(clientResponse.rawStatusCode()); + }); + } + + private static ExchangeFilterFunction logResponse() { + return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { + if (log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder("Response: \n") + .append("Status: ") + .append(clientResponse.rawStatusCode()); clientResponse .headers() .asHttpHeaders() - .forEach((key, value1) -> value1.forEach(value -> sb.append("\n").append(key).append(":").append(value))); + .forEach((key, value1) -> value1.forEach(value -> sb + .append("\n") + .append(key) + .append(":") + .append(value))); log.debug(sb.toString()); } return Mono.just(clientResponse); - })); + }); } } diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java index 334faf2c91..ac333feb6c 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java @@ -27,7 +27,9 @@ public class RequestLogEnhancer { .append(header) .append("\n"); }); - request.onRequestContent((theRequest, content) -> group.append(toString(content, getCharset(theRequest.getHeaders())))); + request.onRequestContent((theRequest, content) -> { + group.append(toString(content, getCharset(theRequest.getHeaders()))); + }); request.onRequestSuccess(theRequest -> { log.debug(group.toString()); group.delete(0, group.length()); @@ -35,13 +37,15 @@ public class RequestLogEnhancer { group.append("\n"); request.onResponseBegin(theResponse -> { group - .append("Response \n ") + .append("Response \n") .append(theResponse.getVersion()) .append(" ") .append(theResponse.getStatus()); - if (theResponse.getReason() != null) group - .append(" ") - .append(theResponse.getReason()); + if (theResponse.getReason() != null) { + group + .append(" ") + .append(theResponse.getReason()); + } group.append("\n"); }); request.onResponseHeaders(theResponse -> { @@ -50,39 +54,39 @@ public class RequestLogEnhancer { .append(header) .append("\n"); }); - request.onResponseContent((theResponse, content) -> group.append(toString(content, getCharset(theResponse.getHeaders())))); + request.onResponseContent((theResponse, content) -> { + group.append(toString(content, getCharset(theResponse.getHeaders()))); + }); request.onResponseSuccess(theResponse -> { log.debug(group.toString()); }); return request; } - - private String toString(ByteBuffer buffer, Charset charset) - { + private String toString(ByteBuffer buffer, Charset charset) { byte[] bytes; if (buffer.hasArray()) { bytes = new byte[buffer.capacity()]; - System.arraycopy(buffer.array(), 0, bytes, 0, buffer.capacity() ); - } - else - { + System.arraycopy(buffer.array(), 0, bytes, 0, buffer.capacity()); + } else { bytes = new byte[buffer.remaining()]; buffer.get(bytes, 0, bytes.length); } return new String(bytes, charset); } - private Charset getCharset(HttpFields headers) { String contentType = headers.get(HttpHeader.CONTENT_TYPE); - if (contentType == null) return StandardCharsets.UTF_8; - String[] tokens = contentType - .toLowerCase(Locale.US) - .split("charset="); - if (tokens.length != 2) return StandardCharsets.UTF_8; - String encoding = tokens[1].replaceAll("[;\"]", ""); - return Charset.forName(encoding); + if (contentType != null) { + String[] tokens = contentType + .toLowerCase(Locale.US) + .split("charset="); + if (tokens.length == 2) { + String encoding = tokens[1].replaceAll("[;\"]", ""); + return Charset.forName(encoding); + } + } + return StandardCharsets.UTF_8; } } diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java index df7c65f33f..529549f99b 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java @@ -3,35 +3,40 @@ package com.baeldung.reactive.logging.netty; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.logging.LoggingHandler; -import io.netty.util.internal.PlatformDependent; import java.nio.charset.Charset; +import static io.netty.util.internal.PlatformDependent.allocateUninitializedArray; +import static java.lang.Math.max; +import static java.nio.charset.Charset.defaultCharset; + public class CustomLogger extends LoggingHandler { public CustomLogger(Class clazz) { super(clazz); } @Override - protected String format(ChannelHandlerContext ctx, String eventName, Object arg) { + protected String format(ChannelHandlerContext ctx, String event, Object arg) { if (arg instanceof ByteBuf) { ByteBuf msg = (ByteBuf) arg; - return decodeString(msg, msg.readerIndex(), msg.readableBytes(), Charset.defaultCharset()); + return decode(msg, msg.readerIndex(), msg.readableBytes(), defaultCharset()); } return ""; } - private String decodeString(ByteBuf src, int readerIndex, int len, Charset charset) { - if (len == 0) return ""; - byte[] array; - int offset; - if (src.hasArray()) { - array = src.array(); - offset = src.arrayOffset() + readerIndex; - } else { - array = PlatformDependent.allocateUninitializedArray(Math.max(len, 1024)); - offset = 0; - src.getBytes(readerIndex, array, 0, len); + private String decode(ByteBuf src, int readerIndex, int len, Charset charset) { + if (len != 0) { + byte[] array; + int offset; + if (src.hasArray()) { + array = src.array(); + offset = src.arrayOffset() + readerIndex; + } else { + array = allocateUninitializedArray(max(len, 1024)); + offset = 0; + src.getBytes(readerIndex, array, 0, len); + } + return new String(array, offset, len, charset); } - return new String(array, offset, len, charset); + return ""; } } From 69bdf2b5fcfa1423585354c1be2486d86f2747b5 Mon Sep 17 00:00:00 2001 From: Anshul Bansal Date: Sun, 1 Sep 2019 15:46:43 +0300 Subject: [PATCH 11/34] BAEL-3190 - Working with web services in Groovy --- core-groovy-2/pom.xml | 5 + .../webservice/WebserviceUnitTest.groovy | 148 ++++++++++++++++++ 2 files changed, 153 insertions(+) create mode 100644 core-groovy-2/src/test/groovy/com/baeldung/webservice/WebserviceUnitTest.groovy diff --git a/core-groovy-2/pom.xml b/core-groovy-2/pom.xml index ba3fd0802b..85f6106e95 100644 --- a/core-groovy-2/pom.xml +++ b/core-groovy-2/pom.xml @@ -48,6 +48,11 @@ ${spock-core.version} test + + com.github.groovy-wslite + groovy-wslite + 1.1.3 + diff --git a/core-groovy-2/src/test/groovy/com/baeldung/webservice/WebserviceUnitTest.groovy b/core-groovy-2/src/test/groovy/com/baeldung/webservice/WebserviceUnitTest.groovy new file mode 100644 index 0000000000..edf2dca33f --- /dev/null +++ b/core-groovy-2/src/test/groovy/com/baeldung/webservice/WebserviceUnitTest.groovy @@ -0,0 +1,148 @@ +package com.baeldung.webservice + +import groovy.json.JsonSlurper +import wslite.rest.ContentType +import wslite.rest.RESTClient +import wslite.rest.RESTClientException +import wslite.soap.SOAPClient +import wslite.soap.SOAPMessageBuilder + +class WebserviceUnitTest extends GroovyTestCase { + + JsonSlurper jsonSlurper = new JsonSlurper() + + static RESTClient client = new RESTClient("https://postman-echo.com") + + static { + client.defaultAcceptHeader = ContentType.JSON + client.httpClient.sslTrustAllCerts = true + } + + void testHttpGetRequest() { + def postmanGet = new URL('https://postman-echo.com/get') + def getConnection = postmanGet.openConnection() + getConnection.requestMethod = 'GET' + assert getConnection.responseCode == 200 + if (getConnection.responseCode == 200) { + assert jsonSlurper.parseText(getConnection.content.text)?.headers?.host == "postman-echo.com" + } + } + + void testHttpPostRequest() { + def postmanPost = new URL('https://postman-echo.com/post') + def query = "q=This is post request form parameter." + def postConnection = postmanPost.openConnection() + postConnection.requestMethod = 'POST' + assert postConnection.responseCode == 200 + } + + void testHttpPostRequestWithParams() { + def postmanPost = new URL('https://postman-echo.com/post') + def form = "param1=This is request parameter." + def postConnection = postmanPost.openConnection() + postConnection.requestMethod = 'POST' + postConnection.doOutput = true + def text + postConnection.with { + outputStream.withWriter { outputStreamWriter -> + outputStreamWriter << form + } + text = content.text + } + assert postConnection.responseCode == 200 + assert jsonSlurper.parseText(text)?.json.param1 == "This is request parameter." + } + + void testRssFeed() { + def rssFeed = new XmlParser().parse("https://news.google.com/rss?hl=en-US&gl=US&ceid=US:en") + def stories = [] + (0..4).each { + def item = rssFeed.channel.item.get(it) + stories << item.title.text() + } + assert stories.size() == 5 + } + + void testAtomFeed() { + def atomFeed = new XmlParser().parse("https://news.google.com/atom?hl=en-US&gl=US&ceid=US:en") + def stories = [] + (0..4).each { + def entry = atomFeed.entry.get(it) + stories << entry.title.text() + } + assert stories.size() == 5 + } + + void testSoapClient() { + def url = "http://www.dataaccess.com/webservicesserver/numberconversion.wso" + def soapClient = new SOAPClient(url) + def message = new SOAPMessageBuilder().build({ + body { + NumberToWords(xmlns: "http://www.dataaccess.com/webservicesserver/") { + ubiNum(1234) + } + } + }) + def response = soapClient.send(message.toString()); + def words = response.NumberToWordsResponse + assert words == "one thousand two hundred and thirty four " + } + + void testRestClientGet() { + def path = "/get" + def response + try { + response = client.get(path: path) + assert response.statusCode == 200 + assert response.json?.headers?.host == "postman-echo.com" + } catch (RESTClientException e) { + assert e?.response?.statusCode != 200 + } + } + + void testRestClientPost() { + def path = "/post" + def params = ["foo":1,"bar":2] + def response + try { + response = client.post(path: path) { + type ContentType.JSON + json params + } + assert response.json?.data == params + } catch (RESTClientException e) { + e.printStackTrace() + assert e?.response?.statusCode != 200 + } + } + + void testBasicAuthentication() { + def path = "/basic-auth" + def response + try { + response = client.get(path: path, headers: ["Authorization": "Basic cG9zdG1hbjpwYXNzd29yZA=="]) + assert response.statusCode == 200 + assert response.json?.authenticated == true + } catch (RESTClientException e) { + assert e?.response?.statusCode != 200 + } + } + + void testOAuth() { + RESTClient oAuthClient = new RESTClient("https://postman-echo.com") + oAuthClient.defaultAcceptHeader = ContentType.JSON + oAuthClient.httpClient.sslTrustAllCerts = true + + def path = "/oauth1" + def params = [oauth_consumer_key: "RKCGzna7bv9YD57c", oauth_signature_method: "HMAC-SHA1", oauth_timestamp:1567089944, oauth_nonce: "URT7v4", oauth_version: 1.0, oauth_signature: 'RGgR/ktDmclkM0ISWaFzebtlO0A='] + def response + try { + response = oAuthClient.get(path: path, query: params) + assert response.statusCode == 200 + assert response.statusMessage == "OK" + assert response.json.status == "pass" + } catch (RESTClientException e) { + assert e?.response?.statusCode != 200 + } + } +} \ No newline at end of file From f29bb940134706877f4df7e5dc5d404188468383 Mon Sep 17 00:00:00 2001 From: Anshul Bansal Date: Sun, 1 Sep 2019 15:48:07 +0300 Subject: [PATCH 12/34] BAEL-3190 - Working with web services in Groovy - pom.xml code indentation --- core-groovy-2/pom.xml | 357 +++++++++++++++++++++--------------------- 1 file changed, 179 insertions(+), 178 deletions(-) diff --git a/core-groovy-2/pom.xml b/core-groovy-2/pom.xml index 85f6106e95..6f2f9bd533 100644 --- a/core-groovy-2/pom.xml +++ b/core-groovy-2/pom.xml @@ -1,189 +1,190 @@ - - 4.0.0 - core-groovy-2 - 1.0-SNAPSHOT - core-groovy-2 - jar + + 4.0.0 + core-groovy-2 + 1.0-SNAPSHOT + core-groovy-2 + jar - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - ch.qos.logback - logback-classic - ${logback.version} - - - org.codehaus.groovy - groovy-all - ${groovy.version} - pom - - - org.junit.platform - junit-platform-runner - ${junit.platform.version} - test - - - org.hsqldb - hsqldb - ${hsqldb.version} - test - - - org.spockframework - spock-core - ${spock-core.version} - test - - - com.github.groovy-wslite - groovy-wslite - 1.1.3 + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} - + + ch.qos.logback + logback-classic + ${logback.version} + + + org.codehaus.groovy + groovy-all + ${groovy.version} + pom + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + + org.hsqldb + hsqldb + ${hsqldb.version} + test + + + org.spockframework + spock-core + ${spock-core.version} + test + + + com.github.groovy-wslite + groovy-wslite + 1.1.3 + + - - src/main/groovy - src/main/java - - - org.codehaus.groovy - groovy-eclipse-compiler - 3.3.0-01 - true - - - maven-compiler-plugin - 3.8.0 - - groovy-eclipse-compiler - ${java.version} - ${java.version} - - - - org.codehaus.groovy - groovy-eclipse-compiler - 3.3.0-01 - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.version}-01 - - - - - maven-failsafe-plugin - ${maven-failsafe-plugin.version} - - - org.junit.platform - junit-platform-surefire-provider - ${junit.platform.version} - - - - - junit5 - - integration-test - verify - - - - **/*Test5.java - - - - - - - maven-surefire-plugin - 2.20.1 - - false - - **/*Test.java - **/*Spec.java - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.1.0 - - - - jar-with-dependencies - - - - - com.baeldung.MyJointCompilationApp - - + + src/main/groovy + src/main/java + + + org.codehaus.groovy + groovy-eclipse-compiler + 3.3.0-01 + true + + + maven-compiler-plugin + 3.8.0 + + groovy-eclipse-compiler + ${java.version} + ${java.version} + + + + org.codehaus.groovy + groovy-eclipse-compiler + 3.3.0-01 + + + org.codehaus.groovy + groovy-eclipse-batch + ${groovy.version}-01 + + + + + maven-failsafe-plugin + ${maven-failsafe-plugin.version} + + + org.junit.platform + junit-platform-surefire-provider + ${junit.platform.version} + + + + + junit5 + + integration-test + verify + + + + **/*Test5.java + + + + + + + maven-surefire-plugin + 2.20.1 + + false + + **/*Test.java + **/*Spec.java + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.1.0 + + + + jar-with-dependencies + + + + + com.baeldung.MyJointCompilationApp + + - - - - make-assembly - - package - - single - - - - - - + + + + make-assembly + + package + + single + + + + + + - - - central - http://jcenter.bintray.com - - + + + central + http://jcenter.bintray.com + + - - - bintray - Groovy Bintray - https://dl.bintray.com/groovy/maven - - - never - - - false - - - + + + bintray + Groovy Bintray + https://dl.bintray.com/groovy/maven + + + never + + + false + + + - - 1.0.0 - 2.4.0 - 1.1-groovy-2.4 - 3.8.1 - 1.2.3 - 2.5.7 - UTF-8 - + + 1.0.0 + 2.4.0 + 1.1-groovy-2.4 + 3.8.1 + 1.2.3 + 2.5.7 + UTF-8 + From 78e2331c4fc6be1a1e577b8cda7543eb4aba0dc5 Mon Sep 17 00:00:00 2001 From: Anshul Bansal Date: Sun, 1 Sep 2019 15:51:19 +0300 Subject: [PATCH 13/34] BAEL-3190 - Working with web services in Groovy - pom.xml code indentation --- core-groovy-2/pom.xml | 351 +++++++++++++++++++++--------------------- 1 file changed, 175 insertions(+), 176 deletions(-) diff --git a/core-groovy-2/pom.xml b/core-groovy-2/pom.xml index 6f2f9bd533..2ffef7ae94 100644 --- a/core-groovy-2/pom.xml +++ b/core-groovy-2/pom.xml @@ -1,190 +1,189 @@ - - 4.0.0 - core-groovy-2 - 1.0-SNAPSHOT - core-groovy-2 - jar + + 4.0.0 + core-groovy-2 + 1.0-SNAPSHOT + core-groovy-2 + jar - - com.baeldung - parent-modules - 1.0.0-SNAPSHOT - + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - ch.qos.logback - logback-classic - ${logback.version} - - - org.codehaus.groovy - groovy-all - ${groovy.version} - pom - - - org.junit.platform - junit-platform-runner - ${junit.platform.version} - test - - - org.hsqldb - hsqldb - ${hsqldb.version} - test - - - org.spockframework - spock-core - ${spock-core.version} - test - - + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + org.codehaus.groovy + groovy-all + ${groovy.version} + pom + + + org.junit.platform + junit-platform-runner + ${junit.platform.version} + test + + + org.hsqldb + hsqldb + ${hsqldb.version} + test + + + org.spockframework + spock-core + ${spock-core.version} + test + + com.github.groovy-wslite groovy-wslite 1.1.3 - + - - src/main/groovy - src/main/java - - - org.codehaus.groovy - groovy-eclipse-compiler - 3.3.0-01 - true - - - maven-compiler-plugin - 3.8.0 - - groovy-eclipse-compiler - ${java.version} - ${java.version} - - - - org.codehaus.groovy - groovy-eclipse-compiler - 3.3.0-01 - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.version}-01 - - - - - maven-failsafe-plugin - ${maven-failsafe-plugin.version} - - - org.junit.platform - junit-platform-surefire-provider - ${junit.platform.version} - - - - - junit5 - - integration-test - verify - - - - **/*Test5.java - - - - - - - maven-surefire-plugin - 2.20.1 - - false - - **/*Test.java - **/*Spec.java - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.1.0 - - - - jar-with-dependencies - - - - - com.baeldung.MyJointCompilationApp - - + + src/main/groovy + src/main/java + + + org.codehaus.groovy + groovy-eclipse-compiler + 3.3.0-01 + true + + + maven-compiler-plugin + 3.8.0 + + groovy-eclipse-compiler + ${java.version} + ${java.version} + + + + org.codehaus.groovy + groovy-eclipse-compiler + 3.3.0-01 + + + org.codehaus.groovy + groovy-eclipse-batch + ${groovy.version}-01 + + + + + maven-failsafe-plugin + ${maven-failsafe-plugin.version} + + + org.junit.platform + junit-platform-surefire-provider + ${junit.platform.version} + + + + + junit5 + + integration-test + verify + + + + **/*Test5.java + + + + + + + maven-surefire-plugin + 2.20.1 + + false + + **/*Test.java + **/*Spec.java + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.1.0 + + + + jar-with-dependencies + + + + + com.baeldung.MyJointCompilationApp + + - - - - make-assembly - - package - - single - - - - - - + + + + make-assembly + + package + + single + + + + + + - - - central - http://jcenter.bintray.com - - + + + central + http://jcenter.bintray.com + + - - - bintray - Groovy Bintray - https://dl.bintray.com/groovy/maven - - - never - - - false - - - + + + bintray + Groovy Bintray + https://dl.bintray.com/groovy/maven + + + never + + + false + + + - - 1.0.0 - 2.4.0 - 1.1-groovy-2.4 - 3.8.1 - 1.2.3 - 2.5.7 - UTF-8 - + + 1.0.0 + 2.4.0 + 1.1-groovy-2.4 + 3.8.1 + 1.2.3 + 2.5.7 + UTF-8 + From e5ff15e4aa07667df47af930f6c30973e9c18ee3 Mon Sep 17 00:00:00 2001 From: Anshul Bansal Date: Sun, 1 Sep 2019 15:56:26 +0300 Subject: [PATCH 14/34] BAEL-3190 - Working with web services in Groovy - pom.xml code indentation --- core-groovy-2/pom.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core-groovy-2/pom.xml b/core-groovy-2/pom.xml index 2ffef7ae94..1f5baaf904 100644 --- a/core-groovy-2/pom.xml +++ b/core-groovy-2/pom.xml @@ -51,7 +51,7 @@ com.github.groovy-wslite groovy-wslite - 1.1.3 + ${groovy-wslite.version} @@ -180,6 +180,7 @@ 1.0.0 2.4.0 1.1-groovy-2.4 + 1.1.3 3.8.1 1.2.3 2.5.7 From a92e0ec2bc48618066281fe383cf12b74fcea5bc Mon Sep 17 00:00:00 2001 From: Anshul Bansal Date: Sun, 1 Sep 2019 15:57:37 +0300 Subject: [PATCH 15/34] BAEL-3190 - Working with web services in Groovy - pom.xml code indentation --- core-groovy-2/pom.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core-groovy-2/pom.xml b/core-groovy-2/pom.xml index 1f5baaf904..40e38bef16 100644 --- a/core-groovy-2/pom.xml +++ b/core-groovy-2/pom.xml @@ -49,10 +49,10 @@ test - com.github.groovy-wslite - groovy-wslite - ${groovy-wslite.version} - + com.github.groovy-wslite + groovy-wslite + ${groovy-wslite.version} + @@ -180,7 +180,7 @@ 1.0.0 2.4.0 1.1-groovy-2.4 - 1.1.3 + 1.1.3 3.8.1 1.2.3 2.5.7 From db772047f44e6707a206b7e927b94f8996836b19 Mon Sep 17 00:00:00 2001 From: David Calap Date: Sun, 1 Sep 2019 20:30:58 +0200 Subject: [PATCH 16/34] BAEL-3142 Removing an element from an ArrayList --- .../baeldung/java/list/RemoveFromList.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/RemoveFromList.java diff --git a/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/RemoveFromList.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/RemoveFromList.java new file mode 100644 index 0000000000..9e116c54de --- /dev/null +++ b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/RemoveFromList.java @@ -0,0 +1,40 @@ +package com.baeldung.java.list; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class RemoveFromList { + + public static void main(String[] args) { + List sports = new ArrayList<>(); + sports.add("Football"); + sports.add("Basketball"); + sports.add("Baseball"); + sports.add("Boxing"); + sports.add("Cycling"); + + System.out.println("List before removing: " + sports); + + // Remove with index + sports.remove(1); + + // Remove with an element + sports.remove("Baseball"); + + // Iterator remove method + Iterator iterator = sports.iterator(); + while(iterator.hasNext()){ + if(iterator.next().equals("Boxing")){ + iterator.remove(); + } + } + + // ArrayList removeIf method (Java 8) + for(int i = 0; i < sports.size(); i++){ + sports.removeIf(p -> p.equals("Cycling")); + } + + System.out.println("List after removing: " + sports); + } +} From d3df5e0d9758abb8b157d3c7f677d1516cf04d25 Mon Sep 17 00:00:00 2001 From: Anshul Bansal Date: Sun, 1 Sep 2019 23:08:53 +0300 Subject: [PATCH 17/34] BAEL-3190 - Working with web services in Groovy - pom.xml code indentation --- core-groovy-2/pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core-groovy-2/pom.xml b/core-groovy-2/pom.xml index 40e38bef16..91e31d4cba 100644 --- a/core-groovy-2/pom.xml +++ b/core-groovy-2/pom.xml @@ -49,9 +49,9 @@ test - com.github.groovy-wslite - groovy-wslite - ${groovy-wslite.version} + com.github.groovy-wslite + groovy-wslite + ${groovy-wslite.version} From 0f0908bc18eb30136ccc5c6c0e1ca2d32b6e49c8 Mon Sep 17 00:00:00 2001 From: David Calap Date: Mon, 2 Sep 2019 10:25:22 +0200 Subject: [PATCH 18/34] Identation fixed applying https://github.com/eugenp/tutorials/blob/master/eclipse/formatter.xml --- .../baeldung/java/list/RemoveFromList.java | 51 ++++++++++--------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/RemoveFromList.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/RemoveFromList.java index 9e116c54de..7c23d1c978 100644 --- a/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/RemoveFromList.java +++ b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/RemoveFromList.java @@ -6,35 +6,36 @@ import java.util.List; public class RemoveFromList { - public static void main(String[] args) { - List sports = new ArrayList<>(); - sports.add("Football"); - sports.add("Basketball"); - sports.add("Baseball"); - sports.add("Boxing"); - sports.add("Cycling"); + public static void main(String[] args) { + List sports = new ArrayList<>(); + sports.add("Football"); + sports.add("Basketball"); + sports.add("Baseball"); + sports.add("Boxing"); + sports.add("Cycling"); - System.out.println("List before removing: " + sports); + System.out.println("List before removing: " + sports); - // Remove with index - sports.remove(1); + // Remove with index + sports.remove(1); - // Remove with an element - sports.remove("Baseball"); + // Remove with an element + sports.remove("Baseball"); - // Iterator remove method - Iterator iterator = sports.iterator(); - while(iterator.hasNext()){ - if(iterator.next().equals("Boxing")){ - iterator.remove(); - } + // Iterator remove method + Iterator iterator = sports.iterator(); + while (iterator.hasNext()) { + if (iterator.next().equals("Boxing")) { + iterator.remove(); + } + } + + // ArrayList removeIf method (Java 8) + for (int i = 0; i < sports.size(); i++) { + sports.removeIf(p -> p.equals("Cycling")); + } + + System.out.println("List after removing: " + sports); } - // ArrayList removeIf method (Java 8) - for(int i = 0; i < sports.size(); i++){ - sports.removeIf(p -> p.equals("Cycling")); - } - - System.out.println("List after removing: " + sports); - } } From 784fb624c1ae903a053a19a58755cf5401f4a683 Mon Sep 17 00:00:00 2001 From: David Calap Date: Mon, 2 Sep 2019 14:02:25 +0200 Subject: [PATCH 19/34] break added to avoid unnecessary loop iterations. Get rid of for since a loop is not needed for removeIf method --- .../src/main/java/com/baeldung/java/list/RemoveFromList.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/RemoveFromList.java b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/RemoveFromList.java index 7c23d1c978..df9b3d987d 100644 --- a/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/RemoveFromList.java +++ b/core-java-modules/core-java-collections-array-list/src/main/java/com/baeldung/java/list/RemoveFromList.java @@ -27,13 +27,12 @@ public class RemoveFromList { while (iterator.hasNext()) { if (iterator.next().equals("Boxing")) { iterator.remove(); + break; } } // ArrayList removeIf method (Java 8) - for (int i = 0; i < sports.size(); i++) { - sports.removeIf(p -> p.equals("Cycling")); - } + sports.removeIf(p -> p.equals("Cycling")); System.out.println("List after removing: " + sports); } From 5b2dec57486fc754e3ed5c02b4d80ddd0660eba6 Mon Sep 17 00:00:00 2001 From: Anshul Bansal Date: Tue, 3 Sep 2019 13:12:17 +0300 Subject: [PATCH 20/34] BAEL-3190 - Working with web services in Groovy - basic authorization --- .../groovy/com/baeldung/webservice/WebserviceUnitTest.groovy | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core-groovy-2/src/test/groovy/com/baeldung/webservice/WebserviceUnitTest.groovy b/core-groovy-2/src/test/groovy/com/baeldung/webservice/WebserviceUnitTest.groovy index edf2dca33f..0d4b5cd7ee 100644 --- a/core-groovy-2/src/test/groovy/com/baeldung/webservice/WebserviceUnitTest.groovy +++ b/core-groovy-2/src/test/groovy/com/baeldung/webservice/WebserviceUnitTest.groovy @@ -6,6 +6,7 @@ import wslite.rest.RESTClient import wslite.rest.RESTClientException import wslite.soap.SOAPClient import wslite.soap.SOAPMessageBuilder +import wslite.http.auth.HTTPBasicAuthorization class WebserviceUnitTest extends GroovyTestCase { @@ -120,10 +121,12 @@ class WebserviceUnitTest extends GroovyTestCase { def path = "/basic-auth" def response try { - response = client.get(path: path, headers: ["Authorization": "Basic cG9zdG1hbjpwYXNzd29yZA=="]) + client.authorization = new HTTPBasicAuthorization("postman", "password") + response = client.get(path: path) assert response.statusCode == 200 assert response.json?.authenticated == true } catch (RESTClientException e) { + e.printStackTrace() assert e?.response?.statusCode != 200 } } From c20918329f1ff4c03f0700c0a525603f9ec7a1ad Mon Sep 17 00:00:00 2001 From: Andrew Shcherbakov Date: Wed, 4 Sep 2019 22:25:22 +0200 Subject: [PATCH 21/34] Refactor the utility class --- .../com/baeldung/logreg/DataUtilities.java | 102 ----------------- .../com/baeldung/logreg/MnistClassifier.java | 16 +-- .../com/baeldung/logreg/MnistPrediction.java | 10 +- .../main/java/com/baeldung/logreg/Utils.java | 103 ++++++++++++++++++ 4 files changed, 119 insertions(+), 112 deletions(-) delete mode 100644 ml/src/main/java/com/baeldung/logreg/DataUtilities.java create mode 100644 ml/src/main/java/com/baeldung/logreg/Utils.java diff --git a/ml/src/main/java/com/baeldung/logreg/DataUtilities.java b/ml/src/main/java/com/baeldung/logreg/DataUtilities.java deleted file mode 100644 index 2f18d30219..0000000000 --- a/ml/src/main/java/com/baeldung/logreg/DataUtilities.java +++ /dev/null @@ -1,102 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015-2019 Skymind, Inc. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - * SPDX-License-Identifier: Apache-2.0 - ******************************************************************************/ - -package com.baeldung.logreg; - -import org.apache.commons.compress.archivers.tar.TarArchiveEntry; -import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; -import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; -import org.apache.http.HttpEntity; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClientBuilder; - -import java.io.*; - -/** - * Common data utility functions. - * - * @author fvaleri - */ -public class DataUtilities { - - /** - * Download a remote file if it doesn't exist. - * @param remoteUrl URL of the remote file. - * @param localPath Where to download the file. - * @return True if and only if the file has been downloaded. - * @throws Exception IO error. - */ - public static boolean downloadFile(String remoteUrl, String localPath) throws IOException { - boolean downloaded = false; - if (remoteUrl == null || localPath == null) - return downloaded; - File file = new File(localPath); - if (!file.exists()) { - file.getParentFile().mkdirs(); - HttpClientBuilder builder = HttpClientBuilder.create(); - CloseableHttpClient client = builder.build(); - try (CloseableHttpResponse response = client.execute(new HttpGet(remoteUrl))) { - HttpEntity entity = response.getEntity(); - if (entity != null) { - try (FileOutputStream outstream = new FileOutputStream(file)) { - entity.writeTo(outstream); - outstream.flush(); - outstream.close(); - } - } - } - downloaded = true; - } - if (!file.exists()) - throw new IOException("File doesn't exist: " + localPath); - return downloaded; - } - - /** - * Extract a "tar.gz" file into a local folder. - * @param inputPath Input file path. - * @param outputPath Output directory path. - * @throws IOException IO error. - */ - public static void extractTarGz(String inputPath, String outputPath) throws IOException { - if (inputPath == null || outputPath == null) - return; - final int bufferSize = 4096; - if (!outputPath.endsWith("" + File.separatorChar)) - outputPath = outputPath + File.separatorChar; - try (TarArchiveInputStream tais = new TarArchiveInputStream( - new GzipCompressorInputStream(new BufferedInputStream(new FileInputStream(inputPath))))) { - TarArchiveEntry entry; - while ((entry = (TarArchiveEntry) tais.getNextEntry()) != null) { - if (entry.isDirectory()) { - new File(outputPath + entry.getName()).mkdirs(); - } else { - int count; - byte data[] = new byte[bufferSize]; - FileOutputStream fos = new FileOutputStream(outputPath + entry.getName()); - BufferedOutputStream dest = new BufferedOutputStream(fos, bufferSize); - while ((count = tais.read(data, 0, bufferSize)) != -1) { - dest.write(data, 0, count); - } - dest.close(); - } - } - } - } - -} diff --git a/ml/src/main/java/com/baeldung/logreg/MnistClassifier.java b/ml/src/main/java/com/baeldung/logreg/MnistClassifier.java index 395307712d..1246de973f 100644 --- a/ml/src/main/java/com/baeldung/logreg/MnistClassifier.java +++ b/ml/src/main/java/com/baeldung/logreg/MnistClassifier.java @@ -67,18 +67,20 @@ public class MnistClassifier { final String path = basePath + "mnist_png" + File.separator; if (!new File(path).exists()) { - logger.debug("Downloading data {}", dataUrl); + logger.info("Downloading data {}", dataUrl); String localFilePath = basePath + "mnist_png.tar.gz"; - logger.info("local file: {}", localFilePath); - if (DataUtilities.downloadFile(dataUrl, localFilePath)) { - DataUtilities.extractTarGz(localFilePath, basePath); + File file = new File(localFilePath); + if (!file.exists()) { + file.getParentFile() + .mkdirs(); + Utils.downloadAndSave(dataUrl, file); + Utils.extractTarArchive(file, basePath); } } else { - logger.info("local file exists {}", path); - + logger.info("Using the local data from folder {}", path); } - logger.info("Vectorizing data..."); + logger.info("Vectorizing the data from folder {}", path); // vectorization of train data File trainData = new File(path + "training"); FileSplit trainSplit = new FileSplit(trainData, NativeImageLoader.ALLOWED_FORMATS, randNumGen); diff --git a/ml/src/main/java/com/baeldung/logreg/MnistPrediction.java b/ml/src/main/java/com/baeldung/logreg/MnistPrediction.java index 5ec1348e07..56097d9a45 100644 --- a/ml/src/main/java/com/baeldung/logreg/MnistPrediction.java +++ b/ml/src/main/java/com/baeldung/logreg/MnistPrediction.java @@ -36,18 +36,22 @@ public class MnistPrediction { } public static void main(String[] args) throws IOException { - String path = fileChose().toString(); + if (!modelPath.exists()) { + logger.info("The model not found. Have you trained it?"); + return; + } MultiLayerNetwork model = ModelSerializer.restoreMultiLayerNetwork(modelPath); + String path = fileChose(); File file = new File(path); INDArray image = new NativeImageLoader(height, width, channels).asMatrix(file); new ImagePreProcessingScaler(0, 1).transform(image); - + // Pass through to neural Net INDArray output = model.output(image); logger.info("File: {}", path); - logger.info(output.toString()); + logger.info("Probabilities: {}", output); } } diff --git a/ml/src/main/java/com/baeldung/logreg/Utils.java b/ml/src/main/java/com/baeldung/logreg/Utils.java new file mode 100644 index 0000000000..fa4be127cd --- /dev/null +++ b/ml/src/main/java/com/baeldung/logreg/Utils.java @@ -0,0 +1,103 @@ +package com.baeldung.logreg; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.commons.compress.archivers.ArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveEntry; +import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Utility class for digit classifier. + * + */ +public class Utils { + + private static final Logger logger = LoggerFactory.getLogger(Utils.class); + + private Utils() { + } + + /** + * Download the content of the given url and save it into a file. + * @param url + * @param file + */ + public static void downloadAndSave(String url, File file) throws IOException { + CloseableHttpClient client = HttpClientBuilder.create() + .build(); + logger.info("Connecting to {}", url); + try (CloseableHttpResponse response = client.execute(new HttpGet(url))) { + HttpEntity entity = response.getEntity(); + if (entity != null) { + logger.info("Downloaded {} bytes", entity.getContentLength()); + try (FileOutputStream outstream = new FileOutputStream(file)) { + logger.info("Saving to the local file"); + entity.writeTo(outstream); + outstream.flush(); + logger.info("Local file saved"); + } + } + } + } + + /** + * Extract a "tar.gz" file into a given folder. + * @param file + * @param folder + */ + public static void extractTarArchive(File file, String folder) throws IOException { + logger.info("Extracting archive {} into folder {}", file.getName(), folder); + // @formatter:off + try (FileInputStream fis = new FileInputStream(file); + BufferedInputStream bis = new BufferedInputStream(fis); + GzipCompressorInputStream gzip = new GzipCompressorInputStream(bis); + TarArchiveInputStream tar = new TarArchiveInputStream(gzip)) { + // @formatter:on + TarArchiveEntry entry; + while ((entry = (TarArchiveEntry) tar.getNextEntry()) != null) { + extractEntry(entry, tar, folder); + } + } + logger.info("Archive extracted"); + } + + /** + * Extract an entry of the input stream into a given folder + * @param entry + * @param tar + * @param folder + * @throws IOException + */ + public static void extractEntry(ArchiveEntry entry, InputStream tar, String folder) throws IOException { + final int bufferSize = 4096; + final String path = folder + entry.getName(); + if (entry.isDirectory()) { + new File(path).mkdirs(); + } else { + int count; + byte[] data = new byte[bufferSize]; + // @formatter:off + try (FileOutputStream os = new FileOutputStream(path); + BufferedOutputStream dest = new BufferedOutputStream(os, bufferSize)) { + // @formatter:off + while ((count = tar.read(data, 0, bufferSize)) != -1) { + dest.write(data, 0, count); + } + } + } + } +} From e7e2c0a8a6a650dbd36cc0ae559abe4c301d5489 Mon Sep 17 00:00:00 2001 From: maryarm Date: Thu, 5 Sep 2019 21:00:26 +0430 Subject: [PATCH 22/34] BAEL-3009: Logging Spring WebClient calls. -Review notes applied --- .../logging/WebClientLoggingIntegrationTest.java | 14 ++++++++------ .../reactive/logging/jetty/RequestLogEnhancer.java | 7 ++++--- .../reactive/logging/netty/CustomLogger.java | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java index d5f1ef77a0..95c63f267f 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/WebClientLoggingIntegrationTest.java @@ -3,7 +3,6 @@ package com.baeldung.reactive.logging; import ch.qos.logback.classic.spi.LoggingEvent; import ch.qos.logback.core.Appender; import com.baeldung.reactive.logging.filters.LogFilters; -import com.baeldung.reactive.logging.jetty.RequestLogEnhancer; import com.baeldung.reactive.logging.netty.CustomLogger; import com.fasterxml.jackson.databind.ObjectMapper; import java.net.URI; @@ -21,6 +20,7 @@ import org.springframework.web.reactive.function.client.WebClient; import reactor.netty.channel.BootstrapHandlers; import reactor.netty.http.client.HttpClient; +import static com.baeldung.reactive.logging.jetty.RequestLogEnhancer.enhance; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -69,13 +69,13 @@ public class WebClientLoggingIntegrationTest { } @Test - public void givenJettyHttpClient_whenEndpointIsConsumed_thenRequestAndResponseBodyShouldBeLogged() { + public void givenJettyHttpClient_whenEndpointIsConsumed_thenRequestAndResponseBodyLogged() { SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(); org.eclipse.jetty.client.HttpClient httpClient = new org.eclipse.jetty.client.HttpClient(sslContextFactory) { @Override public Request newRequest(URI uri) { Request request = super.newRequest(uri); - return new RequestLogEnhancer().enhance(request); + return enhance(request); } }; @@ -94,7 +94,7 @@ public class WebClientLoggingIntegrationTest { } @Test - public void givenNettyHttpClientWithWiretap_whenEndpointIsConsumed_thenRequestAndResponseBodyShouldBeLogged() { + public void givenNettyHttpClientWithWiretap_whenEndpointIsConsumed_thenRequestAndResponseBodyLogged() { reactor.netty.http.client.HttpClient httpClient = HttpClient .create() @@ -108,11 +108,12 @@ public class WebClientLoggingIntegrationTest { .body(BodyInserters.fromObject(post)) .exchange() .block(); + verify(nettyAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains("00000300"))); } @Test - public void givenNettyHttpClientWithCustomLogger_whenEndpointIsConsumed_thenRequestAndResponseBodyShouldBeLogged() { + public void givenNettyHttpClientWithCustomLogger_whenEndpointIsConsumed_thenRequestAndResponseBodyLogged() { reactor.netty.http.client.HttpClient httpClient = HttpClient .create() @@ -128,11 +129,12 @@ public class WebClientLoggingIntegrationTest { .body(BodyInserters.fromObject(post)) .exchange() .block(); + verify(nettyAppender).doAppend(argThat(argument -> (((LoggingEvent) argument).getFormattedMessage()).contains(sampleResponseBody))); } @Test - public void givenDefaultHttpClientWithString_whenEndpointIsConsumed_thenRequestAndResponseLogged() { + public void givenDefaultHttpClientWithFilter_whenEndpointIsConsumed_thenRequestAndResponseLogged() { WebClient .builder() .filters(exchangeFilterFunctions -> { diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java index ac333feb6c..43e3660743 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/jetty/RequestLogEnhancer.java @@ -13,7 +13,7 @@ import org.eclipse.jetty.http.HttpHeader; @Slf4j public class RequestLogEnhancer { - public Request enhance(Request request) { + public static Request enhance(Request request) { StringBuilder group = new StringBuilder(); request.onRequestBegin(theRequest -> group .append("Request ") @@ -63,7 +63,7 @@ public class RequestLogEnhancer { return request; } - private String toString(ByteBuffer buffer, Charset charset) { + private static String toString(ByteBuffer buffer, Charset charset) { byte[] bytes; if (buffer.hasArray()) { bytes = new byte[buffer.capacity()]; @@ -75,7 +75,7 @@ public class RequestLogEnhancer { return new String(bytes, charset); } - private Charset getCharset(HttpFields headers) { + private static Charset getCharset(HttpFields headers) { String contentType = headers.get(HttpHeader.CONTENT_TYPE); if (contentType != null) { String[] tokens = contentType @@ -88,5 +88,6 @@ public class RequestLogEnhancer { } return StandardCharsets.UTF_8; } + } diff --git a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java index 529549f99b..9f2a4d127f 100644 --- a/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java +++ b/spring-5-reactive-client/src/test/java/com/baeldung/reactive/logging/netty/CustomLogger.java @@ -20,7 +20,7 @@ public class CustomLogger extends LoggingHandler { ByteBuf msg = (ByteBuf) arg; return decode(msg, msg.readerIndex(), msg.readableBytes(), defaultCharset()); } - return ""; + return super.format(ctx, event, arg); } private String decode(ByteBuf src, int readerIndex, int len, Charset charset) { From 2747b3b5e49e1e55e782481ada4ecec9aaddcc42 Mon Sep 17 00:00:00 2001 From: Eric Martin Date: Thu, 5 Sep 2019 14:45:00 -0500 Subject: [PATCH 23/34] import java.util.Arrays; --- .../core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java b/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java index c4663a429c..2659b29491 100644 --- a/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java +++ b/core-java-modules/core-java/src/main/java/com/baeldung/uuid/UUIDGenerator.java @@ -3,6 +3,7 @@ package com.baeldung.uuid; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.Arrays; import java.util.UUID; public class UUIDGenerator { From c85be3d29dd0146446ac2e79debf138e62edcb04 Mon Sep 17 00:00:00 2001 From: at508 <52303242+at508@users.noreply.github.com> Date: Thu, 5 Sep 2019 17:38:17 -0400 Subject: [PATCH 24/34] BAEL-2076: loading resources (#7347) * commits for BAEL-2076 - Created core-java-io2 module - added resource loading example code - added core-java-io2 to tutorials pom.xml * Committing review changes - change to try-with-resources - change the order of main method * Reformatting try-with-resources * Moving resources example from core-java-io2 to core-java-io. Removing core-java-io2 * Removing stray core-java-io2 in tutorials pom file. --- core-java-modules/core-java-io/pom.xml | 17 ++++++++ .../baeldung/resource/MyResourceLoader.java | 42 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 core-java-modules/core-java-io/src/main/java/com/baeldung/resource/MyResourceLoader.java diff --git a/core-java-modules/core-java-io/pom.xml b/core-java-modules/core-java-io/pom.xml index 1a133d2cbe..84bf3baeed 100644 --- a/core-java-modules/core-java-io/pom.xml +++ b/core-java-modules/core-java-io/pom.xml @@ -207,6 +207,21 @@ ${maven.compiler.target} + + + + org.apache.maven.plugins + maven-jar-plugin + ${maven-jar-plugin.version} + + + + true + com.baeldung.resource.MyResourceLoader + + + + @@ -274,6 +289,8 @@ 1.18 0.1.5 + 3.1.0 + \ No newline at end of file diff --git a/core-java-modules/core-java-io/src/main/java/com/baeldung/resource/MyResourceLoader.java b/core-java-modules/core-java-io/src/main/java/com/baeldung/resource/MyResourceLoader.java new file mode 100644 index 0000000000..7512b177df --- /dev/null +++ b/core-java-modules/core-java-io/src/main/java/com/baeldung/resource/MyResourceLoader.java @@ -0,0 +1,42 @@ +package com.baeldung.resource; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.stream.Collectors; + +public class MyResourceLoader { + + private void loadFileWithReader() throws IOException { + + try (FileReader fileReader = new FileReader("src/main/resources/input.txt"); + BufferedReader reader = new BufferedReader(fileReader)) { + String contents = reader.lines() + .collect(Collectors.joining(System.lineSeparator())); + System.out.println(contents); + } + + } + + private void loadFileAsResource() throws IOException { + + try (InputStream inputStream = getClass().getResourceAsStream("/input.txt"); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) { + String contents = reader.lines() + .collect(Collectors.joining(System.lineSeparator())); + System.out.println(contents); + } + } + + public static void main(String[] args) throws IOException { + + MyResourceLoader resourceLoader = new MyResourceLoader(); + + resourceLoader.loadFileAsResource(); + resourceLoader.loadFileWithReader(); + + } + +} From cb1de34d0f6e04f13cf61c959adf314af26feeab Mon Sep 17 00:00:00 2001 From: Anshul Bansal Date: Fri, 6 Sep 2019 07:06:26 +0300 Subject: [PATCH 25/34] BAEL-3190 - working with webservices in groovy - followed test names convention --- .../webservice/WebserviceUnitTest.groovy | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/core-groovy-2/src/test/groovy/com/baeldung/webservice/WebserviceUnitTest.groovy b/core-groovy-2/src/test/groovy/com/baeldung/webservice/WebserviceUnitTest.groovy index 0d4b5cd7ee..302959d0d9 100644 --- a/core-groovy-2/src/test/groovy/com/baeldung/webservice/WebserviceUnitTest.groovy +++ b/core-groovy-2/src/test/groovy/com/baeldung/webservice/WebserviceUnitTest.groovy @@ -7,6 +7,7 @@ import wslite.rest.RESTClientException import wslite.soap.SOAPClient import wslite.soap.SOAPMessageBuilder import wslite.http.auth.HTTPBasicAuthorization +import org.junit.Test class WebserviceUnitTest extends GroovyTestCase { @@ -19,7 +20,7 @@ class WebserviceUnitTest extends GroovyTestCase { client.httpClient.sslTrustAllCerts = true } - void testHttpGetRequest() { + void test_whenSendingGet_thenRespose200() { def postmanGet = new URL('https://postman-echo.com/get') def getConnection = postmanGet.openConnection() getConnection.requestMethod = 'GET' @@ -29,7 +30,7 @@ class WebserviceUnitTest extends GroovyTestCase { } } - void testHttpPostRequest() { + void test_whenSendingPost_thenRespose200() { def postmanPost = new URL('https://postman-echo.com/post') def query = "q=This is post request form parameter." def postConnection = postmanPost.openConnection() @@ -37,7 +38,7 @@ class WebserviceUnitTest extends GroovyTestCase { assert postConnection.responseCode == 200 } - void testHttpPostRequestWithParams() { + void test_whenSendingPostWithParams_thenRespose200() { def postmanPost = new URL('https://postman-echo.com/post') def form = "param1=This is request parameter." def postConnection = postmanPost.openConnection() @@ -54,7 +55,7 @@ class WebserviceUnitTest extends GroovyTestCase { assert jsonSlurper.parseText(text)?.json.param1 == "This is request parameter." } - void testRssFeed() { + void test_whenReadingRSS_thenReceiveFeed() { def rssFeed = new XmlParser().parse("https://news.google.com/rss?hl=en-US&gl=US&ceid=US:en") def stories = [] (0..4).each { @@ -64,7 +65,7 @@ class WebserviceUnitTest extends GroovyTestCase { assert stories.size() == 5 } - void testAtomFeed() { + void test_whenReadingAtom_thenReceiveFeed() { def atomFeed = new XmlParser().parse("https://news.google.com/atom?hl=en-US&gl=US&ceid=US:en") def stories = [] (0..4).each { @@ -74,7 +75,7 @@ class WebserviceUnitTest extends GroovyTestCase { assert stories.size() == 5 } - void testSoapClient() { + void test_whenConsumingSoap_thenReceiveResponse() { def url = "http://www.dataaccess.com/webservicesserver/numberconversion.wso" def soapClient = new SOAPClient(url) def message = new SOAPMessageBuilder().build({ @@ -89,7 +90,7 @@ class WebserviceUnitTest extends GroovyTestCase { assert words == "one thousand two hundred and thirty four " } - void testRestClientGet() { + void test_whenConsumingRestGet_thenReceiveResponse() { def path = "/get" def response try { @@ -101,7 +102,7 @@ class WebserviceUnitTest extends GroovyTestCase { } } - void testRestClientPost() { + void test_whenConsumingRestPost_thenReceiveResponse() { def path = "/post" def params = ["foo":1,"bar":2] def response @@ -117,7 +118,7 @@ class WebserviceUnitTest extends GroovyTestCase { } } - void testBasicAuthentication() { + void test_whenBasicAuthentication_thenReceive200() { def path = "/basic-auth" def response try { @@ -131,7 +132,7 @@ class WebserviceUnitTest extends GroovyTestCase { } } - void testOAuth() { + void test_whenOAuth_thenReceive200() { RESTClient oAuthClient = new RESTClient("https://postman-echo.com") oAuthClient.defaultAcceptHeader = ContentType.JSON oAuthClient.httpClient.sslTrustAllCerts = true From e9e4f633138a44d88fb4fe61fdcc4b0b85ab9dc8 Mon Sep 17 00:00:00 2001 From: Ger Roza Date: Fri, 6 Sep 2019 06:19:30 -0300 Subject: [PATCH 26/34] [BAEL-9497] Fix failing context tests - part 1 (#7719) * fixed context dependency issue and added LiveContext notes in persistence-modules/spring-data-couchbase-2 module * fixed Context tests and added notes for spring-cloud-bus/spring-cloud-config-client module * Added context test in spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server module, mainly due to incompatible dependencies, plus fixed parent pom path in different modules * fixed context tests for spring-cloud/spring-cloud-task/springcloudtaskbatch module, renamed ContextLiveTest as IntegrationTest, now configured to run with an H2 embedded instance. Moved the run note to the application * Added SpringContextLiveTests in persistence-modules/spring-data-mongodb module --- .../spring-data-couchbase-2/pom.xml | 16 +++++++- .../org/baeldung/SpringContextLiveTest.java | 39 +++++++++++++++++++ .../mongoconfig/SpringContextLiveTest.java | 26 +++++++++++++ .../SpringContextLiveTest.java | 26 +++++++++++++ .../SpringContextLiveTest.java | 26 +++++++++++++ .../SpringContextIntegrationTest.java | 18 --------- .../org/baeldung/SpringContextLiveTest.java | 21 ++++++++-- .../data-flow-server/pom.xml | 20 ++++++++-- .../src/main/resources/application.properties | 2 + .../org/baeldung/SpringContextLiveTest.java | 16 -------- .../src/test/resources/application.properties | 1 + .../data-flow-shell/pom.xml | 2 +- .../log-sink/pom.xml | 2 +- .../time-processor/pom.xml | 2 +- .../time-source/pom.xml | 2 +- .../springcloudtaskbatch/pom.xml | 8 +++- .../main/java/com/baeldung/task/TaskDemo.java | 7 ++++ ...java => SpringContextIntegrationTest.java} | 12 +----- .../src/test/resources/application.yml | 11 ++++++ 19 files changed, 199 insertions(+), 58 deletions(-) create mode 100644 persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/contexttests/mongoconfig/SpringContextLiveTest.java create mode 100644 persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/contexttests/mongoreactiveconfig/SpringContextLiveTest.java create mode 100644 persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/contexttests/simplemongoconfig/SpringContextLiveTest.java delete mode 100644 spring-cloud-bus/spring-cloud-config-client/src/test/java/org/baeldung/SpringContextIntegrationTest.java create mode 100644 spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/main/resources/application.properties delete mode 100644 spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/test/java/org/baeldung/SpringContextLiveTest.java create mode 100644 spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/test/resources/application.properties rename spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/org/baeldung/{SpringContextLiveTest.java => SpringContextIntegrationTest.java} (60%) create mode 100644 spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/resources/application.yml diff --git a/persistence-modules/spring-data-couchbase-2/pom.xml b/persistence-modules/spring-data-couchbase-2/pom.xml index a857ee538f..f57d9aaa62 100644 --- a/persistence-modules/spring-data-couchbase-2/pom.xml +++ b/persistence-modules/spring-data-couchbase-2/pom.xml @@ -1,4 +1,5 @@ - 4.0.0 org.baeldung @@ -59,13 +60,24 @@ ${spring-framework.version} test + + javax.el + javax.el-api + ${javax.el.version} + + + org.glassfish + javax.el + ${javax.el.version} + - 4.3.4.RELEASE + 4.3.4.RELEASE 2.1.5.RELEASE 5.3.3.Final 2.9.6 + 3.0.0 diff --git a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/SpringContextLiveTest.java b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/SpringContextLiveTest.java index af228735b8..5e20a98a1d 100644 --- a/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/SpringContextLiveTest.java +++ b/persistence-modules/spring-data-couchbase-2/src/test/java/org/baeldung/SpringContextLiveTest.java @@ -9,6 +9,45 @@ import org.springframework.test.context.TestExecutionListeners; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; +/** + * This LiveTest requires: + * + * 1- Couchbase instance running (e.g. with `docker run -d --name db -p 8091-8096:8091-8096 -p 11210-11211:11210-11211 couchbase`) + * + * + * 2- Couchbase configured with (we can use the console in localhost:8091): + * + * 2.1- Buckets: named 'baeldung' and 'baeldung2' + * + * 2.2- Security: users 'baeldung' and 'baeldung2'. Note: in newer versions an empty password is not allowed, then we have to change the passwords in the project) + * + * 2.3- Spacial View: Add new spacial view (in Index tab) in document 'campus_spatial', view 'byLocation' with the following function: + * {@code + * function (doc) { + * if (doc.location && + * doc._class == "org.baeldung.spring.data.couchbase.model.Campus") { + * emit([doc.location.x, doc.location.y], null); + * } + * }} + * + * 2.4- MapReduce Views: Add new views in document 'campus': + * 2.4.1- view 'all' with function: + * {@code + * function (doc, meta) { + * if(doc._class == "org.baeldung.spring.data.couchbase.model.Campus") { + * emit(meta.id, null); + * } + * }} + * + * 2.4.2- view 'byName' with function: + * {@code + * function (doc, meta) { + * if(doc._class == "org.baeldung.spring.data.couchbase.model.Campus" && + * doc.name) { + * emit(doc.name, null); + * } + * }} + */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { MultiBucketCouchbaseConfig.class, MultiBucketIntegrationTestConfig.class }) @TestExecutionListeners(listeners = { DependencyInjectionTestExecutionListener.class }) diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/contexttests/mongoconfig/SpringContextLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/contexttests/mongoconfig/SpringContextLiveTest.java new file mode 100644 index 0000000000..a2a3d1761f --- /dev/null +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/contexttests/mongoconfig/SpringContextLiveTest.java @@ -0,0 +1,26 @@ +package com.baeldung.contexttests.mongoconfig; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.config.MongoConfig; + +/** + * This Live test requires: + * * mongodb instance running on the environment + * + * (e.g. `docker run -d -p 27017:27017 --name bael-mongo mongo`) + * + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = MongoConfig.class) +public class SpringContextLiveTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } + +} diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/contexttests/mongoreactiveconfig/SpringContextLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/contexttests/mongoreactiveconfig/SpringContextLiveTest.java new file mode 100644 index 0000000000..d2a946fb90 --- /dev/null +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/contexttests/mongoreactiveconfig/SpringContextLiveTest.java @@ -0,0 +1,26 @@ +package com.baeldung.contexttests.mongoreactiveconfig; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.config.MongoReactiveConfig; + +/** + * This Live test requires: + * * mongodb instance running on the environment + * + * (e.g. `docker run -d -p 27017:27017 --name bael-mongo mongo`) + * + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = MongoReactiveConfig.class) +public class SpringContextLiveTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } + +} diff --git a/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/contexttests/simplemongoconfig/SpringContextLiveTest.java b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/contexttests/simplemongoconfig/SpringContextLiveTest.java new file mode 100644 index 0000000000..6e8905c139 --- /dev/null +++ b/persistence-modules/spring-data-mongodb/src/test/java/com/baeldung/contexttests/simplemongoconfig/SpringContextLiveTest.java @@ -0,0 +1,26 @@ +package com.baeldung.contexttests.simplemongoconfig; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import com.baeldung.config.SimpleMongoConfig; + +/** + * This Live test requires: + * * mongodb instance running on the environment + * + * (e.g. `docker run -d -p 27017:27017 --name bael-mongo mongo`) + * + * + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = SimpleMongoConfig.class) +public class SpringContextLiveTest { + + @Test + public void whenSpringContextIsBootstrapped_thenNoExceptions() { + } + +} diff --git a/spring-cloud-bus/spring-cloud-config-client/src/test/java/org/baeldung/SpringContextIntegrationTest.java b/spring-cloud-bus/spring-cloud-config-client/src/test/java/org/baeldung/SpringContextIntegrationTest.java deleted file mode 100644 index c0298daeb1..0000000000 --- a/spring-cloud-bus/spring-cloud-config-client/src/test/java/org/baeldung/SpringContextIntegrationTest.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.baeldung; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -import com.baeldung.SpringCloudConfigClientApplication; - -@RunWith(SpringRunner.class) -@SpringBootTest(classes = SpringCloudConfigClientApplication.class) -public class SpringContextIntegrationTest { - - @Test - public void contextLoads() { - } - -} diff --git a/spring-cloud-bus/spring-cloud-config-client/src/test/java/org/baeldung/SpringContextLiveTest.java b/spring-cloud-bus/spring-cloud-config-client/src/test/java/org/baeldung/SpringContextLiveTest.java index 8a33efef43..a401d41e1e 100644 --- a/spring-cloud-bus/spring-cloud-config-client/src/test/java/org/baeldung/SpringContextLiveTest.java +++ b/spring-cloud-bus/spring-cloud-config-client/src/test/java/org/baeldung/SpringContextLiveTest.java @@ -7,12 +7,27 @@ import org.springframework.test.context.junit4.SpringRunner; import com.baeldung.SpringCloudConfigClientApplication; +/** + * This LiveTest requires: + * 1- The 'spring-cloud-bus/spring-cloud-config-server' service running, with valid Spring Cloud Config properties, for instance: + * 1.1- `spring.cloud.config.server.git.uri` pointing to a valid URI, which has `user.role` and `user.password` properties configured in a properties file. For example, to achieve this in a dev environment: + * 1.1.1- `cd my/custom/path` + * 1.1.2- `git init .` + * 1.1.3- `echo user.role=Programmer >> application.properties` + * 1.1.4- `echo user.password=d3v3L >> application.properties` + * 1.1.5- `git add .` + * 1.1.6- `git commit -m 'inital commit'` + * 1.1.7- 'spring-cloud-bus/spring-cloud-config-server' with property `spring.cloud.config.server.git.uri=my/custom/path` + * + * Note: This is enough to run the ContextTest successfully, but to get the full functionality shown in the related article, we'll need also a RabbitMQ instance running (e.g. `docker run -d --hostname my-rabbit --name some-rabbit -p 15672:15672 -p 5672:5672 rabbitmq:3-management`) + * + */ @RunWith(SpringRunner.class) @SpringBootTest(classes = SpringCloudConfigClientApplication.class) public class SpringContextLiveTest { - @Test - public void contextLoads() { - } + @Test + public void contextLoads() { + } } diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/pom.xml b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/pom.xml index cf583c216a..7166b0fd32 100644 --- a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/pom.xml +++ b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/pom.xml @@ -1,5 +1,6 @@ - 4.0.0 data-flow-server @@ -12,7 +13,7 @@ parent-boot-1 com.baeldung 0.0.1-SNAPSHOT - ../../parent-boot-1 + ../../../parent-boot-1 @@ -20,6 +21,16 @@ org.springframework.cloud spring-cloud-starter-dataflow-server-local + + org.hibernate + hibernate-core + ${hibernate.compatible.version} + + + org.hibernate + hibernate-entitymanager + ${hibernate.compatible.version} + @@ -42,8 +53,9 @@ - 1.1.0.RELEASE - Brixton.SR7 + 1.3.1.RELEASE + Edgware.SR6 + 5.2.12.Final diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/main/resources/application.properties b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/main/resources/application.properties new file mode 100644 index 0000000000..20ad5d5bcb --- /dev/null +++ b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/main/resources/application.properties @@ -0,0 +1,2 @@ +#spring.datasource.url=jdbc:h2:mem:dataflow +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect \ No newline at end of file diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/test/java/org/baeldung/SpringContextLiveTest.java b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/test/java/org/baeldung/SpringContextLiveTest.java deleted file mode 100644 index 980c096f5e..0000000000 --- a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/test/java/org/baeldung/SpringContextLiveTest.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.baeldung; - -import org.baeldung.spring.cloud.DataFlowServerApplication; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit4.SpringRunner; - -@RunWith(SpringRunner.class) -@SpringBootTest(classes = DataFlowServerApplication.class) -public class SpringContextLiveTest { - - @Test - public void whenSpringContextIsBootstrapped_thenNoExceptions() { - } -} diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/test/resources/application.properties b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/test/resources/application.properties new file mode 100644 index 0000000000..70e3e5c65b --- /dev/null +++ b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-server/src/test/resources/application.properties @@ -0,0 +1 @@ +spring.datasource.url=jdbc:h2:mem:dataflow \ No newline at end of file diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-shell/pom.xml b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-shell/pom.xml index 52cb204201..9c379624d3 100644 --- a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-shell/pom.xml +++ b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/data-flow-shell/pom.xml @@ -12,7 +12,7 @@ parent-boot-1 com.baeldung 0.0.1-SNAPSHOT - ../../parent-boot-1 + ../../../parent-boot-1 diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/log-sink/pom.xml b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/log-sink/pom.xml index ecabb91a98..73fb82d79f 100644 --- a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/log-sink/pom.xml +++ b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/log-sink/pom.xml @@ -12,7 +12,7 @@ parent-boot-1 com.baeldung 0.0.1-SNAPSHOT - ../../parent-boot-1 + ../../../parent-boot-1 diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-processor/pom.xml b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-processor/pom.xml index de354ca698..28a9d3e6e0 100644 --- a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-processor/pom.xml +++ b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-processor/pom.xml @@ -12,7 +12,7 @@ parent-boot-1 com.baeldung 0.0.1-SNAPSHOT - ../../parent-boot-1 + ../../../parent-boot-1 diff --git a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-source/pom.xml b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-source/pom.xml index a4d06e13d2..3b748fd7df 100644 --- a/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-source/pom.xml +++ b/spring-cloud-data-flow/spring-cloud-data-flow-stream-processing/time-source/pom.xml @@ -12,7 +12,7 @@ parent-boot-1 com.baeldung 0.0.1-SNAPSHOT - ../../parent-boot-1 + ../../../parent-boot-1 diff --git a/spring-cloud/spring-cloud-task/springcloudtaskbatch/pom.xml b/spring-cloud/spring-cloud-task/springcloudtaskbatch/pom.xml index 89c9318c4e..b6b5a1cf0f 100644 --- a/spring-cloud/spring-cloud-task/springcloudtaskbatch/pom.xml +++ b/spring-cloud/spring-cloud-task/springcloudtaskbatch/pom.xml @@ -1,4 +1,5 @@ - 4.0.0 org.baeldung.cloud @@ -43,6 +44,11 @@ org.springframework.cloud spring-cloud-task-batch + + com.h2database + h2 + test + diff --git a/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/main/java/com/baeldung/task/TaskDemo.java b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/main/java/com/baeldung/task/TaskDemo.java index be2a173589..30e17cb956 100644 --- a/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/main/java/com/baeldung/task/TaskDemo.java +++ b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/main/java/com/baeldung/task/TaskDemo.java @@ -14,6 +14,13 @@ import org.springframework.cloud.task.configuration.EnableTask; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; +/** + * This Application requires: + * * a MySql instance running, that allows a root user with no password, and with a database named + * + * (e.g. with the following command `docker run -p 3306:3306 --name bael-mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=true -e MYSQL_DATABASE=springcloud mysql:latest`) + * + */ @SpringBootApplication @EnableTask @EnableBatchProcessing diff --git a/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/org/baeldung/SpringContextLiveTest.java b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/org/baeldung/SpringContextIntegrationTest.java similarity index 60% rename from spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/org/baeldung/SpringContextLiveTest.java rename to spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/org/baeldung/SpringContextIntegrationTest.java index ddbcbf65ea..0caa626c14 100644 --- a/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/org/baeldung/SpringContextLiveTest.java +++ b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/java/org/baeldung/SpringContextIntegrationTest.java @@ -10,18 +10,10 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import com.baeldung.task.JobConfiguration; import com.baeldung.task.TaskDemo; -/** - * This Live Test requires: - * * a MySql instance running, that allows a root user with no password, and with a database named - * - * (e.g. with the following command `docker run -p 3306:3306 --name bael-mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=true -e MYSQL_DATABASE=springcloud mysql:latest`) - * - */ @RunWith(SpringJUnit4ClassRunner.class) @SpringBootApplication -@ContextConfiguration(classes = { JobConfiguration.class, TaskDemo.class }, initializers = { - ConfigFileApplicationContextInitializer.class }) -public class SpringContextLiveTest { +@ContextConfiguration(classes = { JobConfiguration.class, TaskDemo.class }, initializers = { ConfigFileApplicationContextInitializer.class }) +public class SpringContextIntegrationTest { @Test public void whenSpringContextIsBootstrapped_thenNoExceptions() { diff --git a/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/resources/application.yml b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/resources/application.yml new file mode 100644 index 0000000000..794ac4d247 --- /dev/null +++ b/spring-cloud/spring-cloud-task/springcloudtaskbatch/src/test/resources/application.yml @@ -0,0 +1,11 @@ +spring: + datasource: + url: jdbc:h2:mem:springcloud + username: sa + password: + jpa: + hibernate: + ddl-auto: create-drop + properties: + hibernate: + dialect: org.hibernate.dialect.H2Dialect \ No newline at end of file From 0d648321dca8d224f4319b7622e0c090b679c31a Mon Sep 17 00:00:00 2001 From: Joel Juarez Date: Fri, 6 Sep 2019 15:17:21 +0200 Subject: [PATCH 27/34] Bael 3043 datastax cassandra (#7616) * BAEL-3043: Datastax Java Driver for Apache Cassandra * changed statement to use query builder * fixed concatenation vulnerability --- persistence-modules/java-cassandra/pom.xml | 5 +++ .../datastax/cassandra/Application.java | 2 +- .../repository/KeyspaceRepository.java | 20 ++++----- .../cassandra/repository/VideoRepository.java | 45 +++++++++++-------- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/persistence-modules/java-cassandra/pom.xml b/persistence-modules/java-cassandra/pom.xml index e7c93bc4e5..3f8367d130 100644 --- a/persistence-modules/java-cassandra/pom.xml +++ b/persistence-modules/java-cassandra/pom.xml @@ -35,6 +35,11 @@ java-driver-core ${datastax-cassandra.version} + + com.datastax.oss + java-driver-query-builder + ${datastax-cassandra.version} + io.netty diff --git a/persistence-modules/java-cassandra/src/main/java/com/baeldung/datastax/cassandra/Application.java b/persistence-modules/java-cassandra/src/main/java/com/baeldung/datastax/cassandra/Application.java index 23140e0455..f067ee8b73 100644 --- a/persistence-modules/java-cassandra/src/main/java/com/baeldung/datastax/cassandra/Application.java +++ b/persistence-modules/java-cassandra/src/main/java/com/baeldung/datastax/cassandra/Application.java @@ -26,7 +26,7 @@ public class Application { KeyspaceRepository keyspaceRepository = new KeyspaceRepository(session); - keyspaceRepository.createKeyspace("testKeyspace", "SimpleStrategy", 1); + keyspaceRepository.createKeyspace("testKeyspace", 1); keyspaceRepository.useKeyspace("testKeyspace"); VideoRepository videoRepository = new VideoRepository(session); diff --git a/persistence-modules/java-cassandra/src/main/java/com/baeldung/datastax/cassandra/repository/KeyspaceRepository.java b/persistence-modules/java-cassandra/src/main/java/com/baeldung/datastax/cassandra/repository/KeyspaceRepository.java index fd4581d055..899481738a 100644 --- a/persistence-modules/java-cassandra/src/main/java/com/baeldung/datastax/cassandra/repository/KeyspaceRepository.java +++ b/persistence-modules/java-cassandra/src/main/java/com/baeldung/datastax/cassandra/repository/KeyspaceRepository.java @@ -1,7 +1,11 @@ package com.baeldung.datastax.cassandra.repository; +import com.datastax.oss.driver.api.core.CqlIdentifier; import com.datastax.oss.driver.api.core.CqlSession; +import com.datastax.oss.driver.api.querybuilder.SchemaBuilder; +import com.datastax.oss.driver.api.querybuilder.schema.CreateKeyspace; + public class KeyspaceRepository { private final CqlSession session; @@ -9,19 +13,15 @@ public class KeyspaceRepository { this.session = session; } - public void createKeyspace(String keyspaceName, String replicationStrategy, int numberOfReplicas) { - StringBuilder sb = new StringBuilder("CREATE KEYSPACE IF NOT EXISTS ").append(keyspaceName) - .append(" WITH replication = {") - .append("'class':'").append(replicationStrategy) - .append("','replication_factor':").append(numberOfReplicas) - .append("};"); + public void createKeyspace(String keyspaceName, int numberOfReplicas) { + CreateKeyspace createKeyspace = SchemaBuilder.createKeyspace(keyspaceName) + .ifNotExists() + .withSimpleStrategy(numberOfReplicas); - final String query = sb.toString(); - - session.execute(query); + session.execute(createKeyspace.build()); } public void useKeyspace(String keyspace) { - session.execute("USE " + keyspace); + session.execute("USE " + CqlIdentifier.fromCql(keyspace)); } } diff --git a/persistence-modules/java-cassandra/src/main/java/com/baeldung/datastax/cassandra/repository/VideoRepository.java b/persistence-modules/java-cassandra/src/main/java/com/baeldung/datastax/cassandra/repository/VideoRepository.java index 9a09d77072..48eb000eba 100644 --- a/persistence-modules/java-cassandra/src/main/java/com/baeldung/datastax/cassandra/repository/VideoRepository.java +++ b/persistence-modules/java-cassandra/src/main/java/com/baeldung/datastax/cassandra/repository/VideoRepository.java @@ -7,6 +7,12 @@ import com.datastax.oss.driver.api.core.cql.BoundStatement; import com.datastax.oss.driver.api.core.cql.PreparedStatement; import com.datastax.oss.driver.api.core.cql.ResultSet; import com.datastax.oss.driver.api.core.cql.SimpleStatement; +import com.datastax.oss.driver.api.core.type.DataTypes; +import com.datastax.oss.driver.api.querybuilder.QueryBuilder; +import com.datastax.oss.driver.api.querybuilder.SchemaBuilder; +import com.datastax.oss.driver.api.querybuilder.insert.RegularInsert; +import com.datastax.oss.driver.api.querybuilder.schema.CreateTable; +import com.datastax.oss.driver.api.querybuilder.select.Select; import java.util.ArrayList; import java.util.List; @@ -27,15 +33,12 @@ public class VideoRepository { } public void createTable(String keyspace) { - StringBuilder sb = new StringBuilder("CREATE TABLE IF NOT EXISTS ").append(TABLE_NAME).append(" (") - .append("video_id UUID,") - .append("title TEXT,") - .append("creation_date TIMESTAMP,") - .append("PRIMARY KEY(video_id));"); + CreateTable createTable = SchemaBuilder.createTable(TABLE_NAME).ifNotExists() + .withPartitionKey("video_id", DataTypes.UUID) + .withColumn("title", DataTypes.TEXT) + .withColumn("creation_date", DataTypes.TIMESTAMP); - String query = sb.toString(); - - executeStatement(SimpleStatement.newInstance(query), keyspace); + executeStatement(createTable.build(), keyspace); } public UUID insertVideo(Video video) { @@ -47,17 +50,23 @@ public class VideoRepository { video.setId(videoId); - String absoluteTableName = keyspace != null ? keyspace + "." + TABLE_NAME: TABLE_NAME; + RegularInsert insertInto = QueryBuilder.insertInto(TABLE_NAME) + .value("video_id", QueryBuilder.bindMarker()) + .value("title", QueryBuilder.bindMarker()) + .value("creation_date", QueryBuilder.bindMarker()); - StringBuilder sb = new StringBuilder("INSERT INTO ").append(absoluteTableName) - .append("(video_id, title, creation_date) values (:video_id, :title, :creation_date)"); + SimpleStatement insertStatement = insertInto.build(); - PreparedStatement preparedStatement = session.prepare(sb.toString()); + if (keyspace != null) { + insertStatement = insertStatement.setKeyspace(keyspace); + } + + PreparedStatement preparedStatement = session.prepare(insertStatement); BoundStatement statement = preparedStatement.bind() - .setUuid("video_id", video.getId()) - .setString("title", video.getTitle()) - .setInstant("creation_date", video.getCreationDate()); + .setUuid(0, video.getId()) + .setString(1, video.getTitle()) + .setInstant(2, video.getCreationDate()); session.execute(statement); @@ -69,11 +78,9 @@ public class VideoRepository { } public List