remove remaining kotlin code
This commit is contained in:
parent
e677f682f1
commit
9624056752
|
@ -1,3 +0,0 @@
|
||||||
### Relevant Articles:
|
|
||||||
|
|
||||||
- [Introduction to Supervised Learning in Kotlin](https://www.baeldung.com/kotlin-supervised-learning)
|
|
|
@ -1,163 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project
|
|
||||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>machine-learning</artifactId>
|
|
||||||
<version>1.0-SNAPSHOT</version>
|
|
||||||
<name>machine-learning</name>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>parent-modules</artifactId>
|
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.nd4j</groupId>
|
|
||||||
<artifactId>nd4j-native-platform</artifactId>
|
|
||||||
<version>${dl4j.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.deeplearning4j</groupId>
|
|
||||||
<artifactId>deeplearning4j-core</artifactId>
|
|
||||||
<version>${dl4j.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-test</artifactId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<sourceDirectory>src/main/kotlin</sourceDirectory>
|
|
||||||
<testSourceDirectory>src/test</testSourceDirectory>
|
|
||||||
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
|
|
||||||
<plugins>
|
|
||||||
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-clean-plugin</artifactId>
|
|
||||||
<version>${clean.plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-resources-plugin</artifactId>
|
|
||||||
<version>${resources.plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<version>${compiler.plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-surefire-plugin</artifactId>
|
|
||||||
<version>${surefire.plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<version>${jar.plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-install-plugin</artifactId>
|
|
||||||
<version>${install.plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-deploy-plugin</artifactId>
|
|
||||||
<version>${deploy.plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-site-plugin</artifactId>
|
|
||||||
<version>${site.plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
|
||||||
<version>${report.plugin.version}</version>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</pluginManagement>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-maven-plugin</artifactId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>compile</id>
|
|
||||||
<phase>compile</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>compile</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
<execution>
|
|
||||||
<id>test-compile</id>
|
|
||||||
<phase>test-compile</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>test-compile</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<configuration>
|
|
||||||
<jvmTarget>1.8</jvmTarget>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>compile</id>
|
|
||||||
<phase>compile</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>compile</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
<execution>
|
|
||||||
<id>testCompile</id>
|
|
||||||
<phase>test-compile</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>testCompile</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
<maven.compiler.source>1.7</maven.compiler.source>
|
|
||||||
<maven.compiler.target>1.7</maven.compiler.target>
|
|
||||||
<kotlin.version>1.3.50</kotlin.version>
|
|
||||||
<dl4j.version>0.9.1</dl4j.version>
|
|
||||||
<clean.plugin.version>3.1.0</clean.plugin.version>
|
|
||||||
<resources.plugin.version>3.0.2</resources.plugin.version>
|
|
||||||
<jar.plugin.version>3.0.2</jar.plugin.version>
|
|
||||||
<compiler.plugin.version>3.8.0</compiler.plugin.version>
|
|
||||||
<surefire.plugin.version>2.22.1</surefire.plugin.version>
|
|
||||||
<install.plugin.version>2.5.2</install.plugin.version>
|
|
||||||
<deploy.plugin.version>2.8.2</deploy.plugin.version>
|
|
||||||
<site.plugin.version>3.7.1</site.plugin.version>
|
|
||||||
<report.plugin.version>3.0.0</report.plugin.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,117 +0,0 @@
|
||||||
package com.baeldung.cnn
|
|
||||||
|
|
||||||
import org.datavec.api.records.reader.impl.collection.ListStringRecordReader
|
|
||||||
import org.datavec.api.split.ListStringSplit
|
|
||||||
import org.deeplearning4j.datasets.datavec.RecordReaderDataSetIterator
|
|
||||||
import org.deeplearning4j.eval.Evaluation
|
|
||||||
import org.deeplearning4j.nn.conf.NeuralNetConfiguration
|
|
||||||
import org.deeplearning4j.nn.conf.inputs.InputType
|
|
||||||
import org.deeplearning4j.nn.conf.layers.*
|
|
||||||
import org.deeplearning4j.nn.multilayer.MultiLayerNetwork
|
|
||||||
import org.deeplearning4j.nn.weights.WeightInit
|
|
||||||
import org.nd4j.linalg.activations.Activation
|
|
||||||
import org.nd4j.linalg.learning.config.Adam
|
|
||||||
import org.nd4j.linalg.lossfunctions.LossFunctions
|
|
||||||
|
|
||||||
object ConvolutionalNeuralNetwork {
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
fun main(args: Array<String>) {
|
|
||||||
val dataset = ZalandoMNISTDataSet().load()
|
|
||||||
dataset.shuffle()
|
|
||||||
val trainDatasetIterator = createDatasetIterator(dataset.subList(0, 50_000))
|
|
||||||
val testDatasetIterator = createDatasetIterator(dataset.subList(50_000, 60_000))
|
|
||||||
|
|
||||||
val cnn = buildCNN()
|
|
||||||
learning(cnn, trainDatasetIterator)
|
|
||||||
testing(cnn, testDatasetIterator)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createDatasetIterator(dataset: MutableList<List<String>>): RecordReaderDataSetIterator {
|
|
||||||
val listStringRecordReader = ListStringRecordReader()
|
|
||||||
listStringRecordReader.initialize(ListStringSplit(dataset))
|
|
||||||
return RecordReaderDataSetIterator(listStringRecordReader, 128, 28 * 28, 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildCNN(): MultiLayerNetwork {
|
|
||||||
val multiLayerNetwork = MultiLayerNetwork(NeuralNetConfiguration.Builder()
|
|
||||||
.seed(123)
|
|
||||||
.l2(0.0005)
|
|
||||||
.updater(Adam())
|
|
||||||
.weightInit(WeightInit.XAVIER)
|
|
||||||
.list()
|
|
||||||
.layer(0, buildInitialConvolutionLayer())
|
|
||||||
.layer(1, buildBatchNormalizationLayer())
|
|
||||||
.layer(2, buildPoolingLayer())
|
|
||||||
.layer(3, buildConvolutionLayer())
|
|
||||||
.layer(4, buildBatchNormalizationLayer())
|
|
||||||
.layer(5, buildPoolingLayer())
|
|
||||||
.layer(6, buildDenseLayer())
|
|
||||||
.layer(7, buildBatchNormalizationLayer())
|
|
||||||
.layer(8, buildDenseLayer())
|
|
||||||
.layer(9, buildOutputLayer())
|
|
||||||
.setInputType(InputType.convolutionalFlat(28, 28, 1))
|
|
||||||
.backprop(true)
|
|
||||||
.build())
|
|
||||||
multiLayerNetwork.init()
|
|
||||||
return multiLayerNetwork
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildOutputLayer(): OutputLayer? {
|
|
||||||
return OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
|
|
||||||
.nOut(10)
|
|
||||||
.activation(Activation.SOFTMAX)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildDenseLayer(): DenseLayer? {
|
|
||||||
return DenseLayer.Builder().activation(Activation.RELU)
|
|
||||||
.nOut(500)
|
|
||||||
.dropOut(0.5)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildPoolingLayer(): SubsamplingLayer? {
|
|
||||||
return SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.MAX)
|
|
||||||
.kernelSize(2, 2)
|
|
||||||
.stride(2, 2)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildBatchNormalizationLayer() = BatchNormalization.Builder().build()
|
|
||||||
|
|
||||||
private fun buildConvolutionLayer(): ConvolutionLayer? {
|
|
||||||
return ConvolutionLayer.Builder(5, 5)
|
|
||||||
.stride(1, 1) // nIn need not specified in later layers
|
|
||||||
.nOut(50)
|
|
||||||
.activation(Activation.IDENTITY)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildInitialConvolutionLayer(): ConvolutionLayer? {
|
|
||||||
return ConvolutionLayer.Builder(5, 5)
|
|
||||||
.nIn(1)
|
|
||||||
.stride(1, 1)
|
|
||||||
.nOut(20)
|
|
||||||
.activation(Activation.IDENTITY)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun learning(cnn: MultiLayerNetwork, trainSet: RecordReaderDataSetIterator) {
|
|
||||||
for (i in 0 until 10) {
|
|
||||||
cnn.fit(trainSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun testing(cnn: MultiLayerNetwork, testSet: RecordReaderDataSetIterator) {
|
|
||||||
val evaluation = Evaluation(10)
|
|
||||||
while (testSet.hasNext()) {
|
|
||||||
val next = testSet.next()
|
|
||||||
val output = cnn.output(next.features)
|
|
||||||
evaluation.eval(next.labels, output)
|
|
||||||
}
|
|
||||||
|
|
||||||
println(evaluation.stats())
|
|
||||||
println(evaluation.confusionToString())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
package com.baeldung.cnn
|
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
import java.nio.ByteBuffer
|
|
||||||
import java.util.*
|
|
||||||
import java.util.stream.Collectors
|
|
||||||
import kotlin.streams.asStream
|
|
||||||
|
|
||||||
class ZalandoMNISTDataSet {
|
|
||||||
private val OFFSET_SIZE = 4 //in bytes
|
|
||||||
private val NUM_ITEMS_OFFSET = 4
|
|
||||||
private val ITEMS_SIZE = 4
|
|
||||||
private val ROWS = 28
|
|
||||||
private val COLUMNS = 28
|
|
||||||
private val IMAGE_OFFSET = 16
|
|
||||||
private val IMAGE_SIZE = ROWS * COLUMNS
|
|
||||||
|
|
||||||
fun load(): MutableList<List<String>> {
|
|
||||||
val labelsFile = File("machine-learning/src/main/resources/train-labels-idx1-ubyte")
|
|
||||||
val imagesFile = File("machine-learning/src/main/resources/train-images-idx3-ubyte")
|
|
||||||
|
|
||||||
val labelBytes = labelsFile.readBytes()
|
|
||||||
val imageBytes = imagesFile.readBytes()
|
|
||||||
|
|
||||||
val byteLabelCount = Arrays.copyOfRange(labelBytes, NUM_ITEMS_OFFSET, NUM_ITEMS_OFFSET + ITEMS_SIZE)
|
|
||||||
val numberOfLabels = ByteBuffer.wrap(byteLabelCount).int
|
|
||||||
|
|
||||||
val list = mutableListOf<List<String>>()
|
|
||||||
|
|
||||||
for (i in 0 until numberOfLabels) {
|
|
||||||
val label = labelBytes[OFFSET_SIZE + ITEMS_SIZE + i]
|
|
||||||
val startBoundary = i * IMAGE_SIZE + IMAGE_OFFSET
|
|
||||||
val endBoundary = i * IMAGE_SIZE + IMAGE_OFFSET + IMAGE_SIZE
|
|
||||||
val imageData = Arrays.copyOfRange(imageBytes, startBoundary, endBoundary)
|
|
||||||
|
|
||||||
val imageDataList = imageData.iterator()
|
|
||||||
.asSequence()
|
|
||||||
.asStream().map { b -> b.toString() }
|
|
||||||
.collect(Collectors.toList())
|
|
||||||
imageDataList.add(label.toString())
|
|
||||||
list.add(imageDataList)
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
package com.baeldung.simplelinearregression
|
|
||||||
|
|
||||||
import kotlin.math.pow
|
|
||||||
|
|
||||||
class SimpleLinearRegression(private val xs: List<Int>, private val ys: List<Int>) {
|
|
||||||
var slope: Double = 0.0
|
|
||||||
var yIntercept: Double = 0.0
|
|
||||||
|
|
||||||
init {
|
|
||||||
val covariance = calculateCovariance(xs, ys)
|
|
||||||
val variance = calculateVariance(xs)
|
|
||||||
slope = calculateSlope(covariance, variance)
|
|
||||||
yIntercept = calculateYIntercept(ys, slope, xs)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun predict(independentVariable: Double) = slope * independentVariable + yIntercept
|
|
||||||
|
|
||||||
fun calculateRSquared(): Double {
|
|
||||||
val sst = ys.sumByDouble { y -> (y - ys.average()).pow(2) }
|
|
||||||
val ssr = xs.zip(ys) { x, y -> (y - predict(x.toDouble())).pow(2) }.sum()
|
|
||||||
return (sst - ssr) / sst
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun calculateYIntercept(ys: List<Int>, slope: Double, xs: List<Int>) = ys.average() - slope * xs.average()
|
|
||||||
|
|
||||||
private fun calculateSlope(covariance: Double, variance: Double) = covariance / variance
|
|
||||||
|
|
||||||
private fun calculateCovariance(xs: List<Int>, ys: List<Int>) = xs.zip(ys) { x, y -> (x - xs.average()) * (y - ys.average()) }.sum()
|
|
||||||
|
|
||||||
private fun calculateVariance(xs: List<Int>) = xs.sumByDouble { x -> (x - xs.average()).pow(2) }
|
|
||||||
}
|
|
Binary file not shown.
|
@ -1,40 +0,0 @@
|
||||||
package com.baeldung.simplelinearregression
|
|
||||||
|
|
||||||
import org.junit.Assert.assertEquals
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
|
|
||||||
class SimpleLinearRegressionUnitTest {
|
|
||||||
@Test
|
|
||||||
fun givenAProperDataSetWhenFedToASimpleLinearRegressionModelThenItPredictsCorrectly() {
|
|
||||||
val xs = arrayListOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
|
|
||||||
val ys = arrayListOf(25, 35, 49, 60, 75, 90, 115, 130, 150, 200)
|
|
||||||
|
|
||||||
val model = SimpleLinearRegression(xs, ys)
|
|
||||||
|
|
||||||
val predictionOne = model.predict(2.5)
|
|
||||||
assertEquals(38.99, predictionOne, 0.01)
|
|
||||||
|
|
||||||
val predictionTwo = model.predict(7.5)
|
|
||||||
assertEquals(128.84, predictionTwo, 0.01)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun givenAPredictableDataSetWhenCalculatingTheLossFunctionThenTheModelIsConsideredReliable() {
|
|
||||||
val xs = arrayListOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
|
|
||||||
val ys = arrayListOf(25, 35, 49, 60, 75, 90, 115, 130, 150, 200)
|
|
||||||
|
|
||||||
val model = SimpleLinearRegression(xs, ys)
|
|
||||||
|
|
||||||
assertEquals(0.95, model.calculateRSquared(), 0.01)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun givenAnUnpredictableDataSetWhenCalculatingTheLossFunctionThenTheModelIsConsideredUnreliable() {
|
|
||||||
val xs = arrayListOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
|
|
||||||
val ys = arrayListOf(200, 0, 200, 0, 0, 0, -115, 1000, 0, 1)
|
|
||||||
|
|
||||||
val model = SimpleLinearRegression(xs, ys)
|
|
||||||
|
|
||||||
assertEquals(0.01, model.calculateRSquared(), 0.01)
|
|
||||||
}
|
|
||||||
}
|
|
2
pom.xml
2
pom.xml
|
@ -498,7 +498,6 @@
|
||||||
<module>lombok-custom</module>
|
<module>lombok-custom</module>
|
||||||
<module>lucene</module>
|
<module>lucene</module>
|
||||||
|
|
||||||
<module>machine-learning</module>
|
|
||||||
<module>mapstruct</module>
|
<module>mapstruct</module>
|
||||||
|
|
||||||
<module>maven-modules</module>
|
<module>maven-modules</module>
|
||||||
|
@ -996,7 +995,6 @@
|
||||||
<module>lombok-custom</module>
|
<module>lombok-custom</module>
|
||||||
<module>lucene</module>
|
<module>lucene</module>
|
||||||
|
|
||||||
<module>machine-learning</module>
|
|
||||||
<module>mapstruct</module>
|
<module>mapstruct</module>
|
||||||
|
|
||||||
<module>maven-modules</module>
|
<module>maven-modules</module>
|
||||||
|
|
|
@ -6,7 +6,6 @@ This module contains articles about reactive Spring 5 Data
|
||||||
The "REST With Spring" Classes: http://bit.ly/restwithspring
|
The "REST With Spring" Classes: http://bit.ly/restwithspring
|
||||||
|
|
||||||
### Relevant Articles
|
### Relevant Articles
|
||||||
- [Reactive Flow with MongoDB, Kotlin, and Spring WebFlux](https://www.baeldung.com/kotlin-mongodb-spring-webflux)
|
|
||||||
- [Spring Data Reactive Repositories with MongoDB](https://www.baeldung.com/spring-data-mongodb-reactive)
|
- [Spring Data Reactive Repositories with MongoDB](https://www.baeldung.com/spring-data-mongodb-reactive)
|
||||||
- [Spring Data MongoDB Tailable Cursors](https://www.baeldung.com/spring-data-mongodb-tailable-cursors)
|
- [Spring Data MongoDB Tailable Cursors](https://www.baeldung.com/spring-data-mongodb-tailable-cursors)
|
||||||
- [A Quick Look at R2DBC with Spring Data](https://www.baeldung.com/spring-data-r2dbc)
|
- [A Quick Look at R2DBC with Spring Data](https://www.baeldung.com/spring-data-r2dbc)
|
||||||
|
|
|
@ -31,18 +31,6 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.module</groupId>
|
|
||||||
<artifactId>jackson-module-kotlin</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-reflect</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
|
@ -52,12 +40,6 @@
|
||||||
<artifactId>reactor-test</artifactId>
|
<artifactId>reactor-test</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-test</artifactId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.reactivex.rxjava2</groupId>
|
<groupId>io.reactivex.rxjava2</groupId>
|
||||||
<artifactId>rxjava</artifactId>
|
<artifactId>rxjava</artifactId>
|
||||||
|
@ -128,53 +110,6 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<artifactId>kotlin-maven-plugin</artifactId>
|
|
||||||
<version>${kotlin-maven-plugin.version}</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>compile</id>
|
|
||||||
<goals>
|
|
||||||
<goal>compile</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<sourceDirs>
|
|
||||||
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
|
|
||||||
<sourceDir>${project.basedir}/src/main/java</sourceDir>
|
|
||||||
</sourceDirs>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
<execution>
|
|
||||||
<id>test-compile</id>
|
|
||||||
<goals>
|
|
||||||
<goal>test-compile</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<sourceDirs>
|
|
||||||
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
|
|
||||||
<sourceDir>${project.basedir}/src/test/java</sourceDir>
|
|
||||||
</sourceDirs>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<configuration>
|
|
||||||
<args>
|
|
||||||
<arg>-Xjsr305=strict</arg>
|
|
||||||
</args>
|
|
||||||
<compilerPlugins>
|
|
||||||
<plugin>spring</plugin>
|
|
||||||
</compilerPlugins>
|
|
||||||
<jvmTarget>1.8</jvmTarget>
|
|
||||||
</configuration>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-maven-allopen</artifactId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
@ -215,8 +150,6 @@
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<kotlin.version>1.2.40</kotlin.version>
|
|
||||||
<kotlin-maven-plugin.version>1.2.40</kotlin-maven-plugin.version>
|
|
||||||
<spring-tx.version>5.2.2.RELEASE</spring-tx.version>
|
<spring-tx.version>5.2.2.RELEASE</spring-tx.version>
|
||||||
<spring-data-r2dbc.version>1.0.0.RELEASE</spring-data-r2dbc.version>
|
<spring-data-r2dbc.version>1.0.0.RELEASE</spring-data-r2dbc.version>
|
||||||
<r2dbc-h2.version>0.8.1.RELEASE</r2dbc-h2.version>
|
<r2dbc-h2.version>0.8.1.RELEASE</r2dbc-h2.version>
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
package com.baeldung
|
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
|
||||||
import org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration
|
|
||||||
|
|
||||||
@SpringBootApplication(exclude = arrayOf(MongoReactiveDataAutoConfiguration::class))
|
|
||||||
class Application
|
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
|
||||||
SpringApplication.run(Application::class.java, *args)
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
package com.baeldung
|
|
||||||
|
|
||||||
import org.springframework.data.mongodb.core.mapping.Document
|
|
||||||
|
|
||||||
@Document
|
|
||||||
data class Event(val id: String, val name: String)
|
|
|
@ -1,6 +0,0 @@
|
||||||
package com.baeldung
|
|
||||||
|
|
||||||
import org.springframework.data.mongodb.core.mapping.Document
|
|
||||||
import org.springframework.data.mongodb.repository.ReactiveMongoRepository
|
|
||||||
|
|
||||||
interface EventRepository : ReactiveMongoRepository<Event, String>
|
|
|
@ -1,25 +0,0 @@
|
||||||
package com.baeldung
|
|
||||||
|
|
||||||
import com.mongodb.reactivestreams.client.MongoClient
|
|
||||||
import com.mongodb.reactivestreams.client.MongoClients
|
|
||||||
import org.springframework.context.annotation.Bean
|
|
||||||
import org.springframework.context.annotation.Configuration
|
|
||||||
import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration
|
|
||||||
import org.springframework.data.mongodb.core.ReactiveMongoTemplate
|
|
||||||
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories
|
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableReactiveMongoRepositories(basePackageClasses = arrayOf(EventRepository::class))
|
|
||||||
class MongoConfig : AbstractReactiveMongoConfiguration() {
|
|
||||||
|
|
||||||
override fun reactiveMongoClient(): MongoClient = mongoClient()
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
fun mongoClient(): MongoClient = MongoClients.create()
|
|
||||||
|
|
||||||
override fun getDatabaseName(): String = "mongoDatabase"
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
override fun reactiveMongoTemplate(): ReactiveMongoTemplate = ReactiveMongoTemplate(mongoClient(), databaseName)
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package com.baeldung
|
|
||||||
|
|
||||||
import org.springframework.http.MediaType
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam
|
|
||||||
import org.springframework.web.bind.annotation.RestController
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
class SendEmitter(val eventRepository: EventRepository) {
|
|
||||||
|
|
||||||
@GetMapping(value = "/save", produces = arrayOf(MediaType.TEXT_EVENT_STREAM_VALUE))
|
|
||||||
fun executeExample(@RequestParam("eventName") eventName: String) =
|
|
||||||
eventRepository.save(Event(UUID.randomUUID().toString(), eventName)).flux()
|
|
||||||
}
|
|
|
@ -1,39 +0,0 @@
|
||||||
<html>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<!-- Save new event -->
|
|
||||||
<form method="get" action="/save">
|
|
||||||
<input type="text" name="eventName">
|
|
||||||
<button type="submit">Save new event</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Receive saved event -->
|
|
||||||
<div id="content"></div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
|
|
||||||
let source = new EventSource("save");
|
|
||||||
|
|
||||||
source.addEventListener('message', function (e) {
|
|
||||||
console.log('New message is received');
|
|
||||||
const index = JSON.parse(e.data);
|
|
||||||
const content = `New event added: ${index.name}<br>`;
|
|
||||||
document.getElementById("content").innerHTML += content;
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
source.addEventListener('open', function(e) {
|
|
||||||
console.log('The connection has been opened');
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
source.addEventListener('error', function(e) {
|
|
||||||
if (e.readyState == EventSource.CLOSED){
|
|
||||||
console.log('The connection has been closed');
|
|
||||||
}
|
|
||||||
}, false);
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
<html>
|
|
|
@ -3,7 +3,6 @@
|
||||||
This module contains articles about Spring 5 model-view-controller (MVC) pattern
|
This module contains articles about Spring 5 model-view-controller (MVC) pattern
|
||||||
|
|
||||||
### Relevant Articles:
|
### Relevant Articles:
|
||||||
- [Spring Boot and Kotlin](https://www.baeldung.com/spring-boot-kotlin)
|
|
||||||
- [Spring MVC Streaming and SSE Request Processing](https://www.baeldung.com/spring-mvc-sse-streams)
|
- [Spring MVC Streaming and SSE Request Processing](https://www.baeldung.com/spring-mvc-sse-streams)
|
||||||
- [Interface Driven Controllers in Spring](https://www.baeldung.com/spring-interface-driven-controllers)
|
- [Interface Driven Controllers in Spring](https://www.baeldung.com/spring-interface-driven-controllers)
|
||||||
- [Returning Plain HTML From a Spring MVC Controller](https://www.baeldung.com/spring-mvc-return-html)
|
- [Returning Plain HTML From a Spring MVC Controller](https://www.baeldung.com/spring-mvc-return-html)
|
||||||
|
|
|
@ -42,22 +42,6 @@
|
||||||
<groupId>org.slf4j</groupId>
|
<groupId>org.slf4j</groupId>
|
||||||
<artifactId>jcl-over-slf4j</artifactId>
|
<artifactId>jcl-over-slf4j</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!--kotlin deps -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-stdlib-jre8</artifactId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-reflect</artifactId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.module</groupId>
|
|
||||||
<artifactId>jackson-module-kotlin</artifactId>
|
|
||||||
<version>${jackson.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<!-- runtime and test scoped -->
|
<!-- runtime and test scoped -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
@ -103,77 +87,11 @@
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<artifactId>kotlin-maven-plugin</artifactId>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
<configuration>
|
|
||||||
<compilerPlugins>
|
|
||||||
<plugin>spring</plugin>
|
|
||||||
</compilerPlugins>
|
|
||||||
<jvmTarget>${java.version}</jvmTarget>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>compile</id>
|
|
||||||
<phase>compile</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>compile</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
<execution>
|
|
||||||
<id>test-compile</id>
|
|
||||||
<phase>test-compile</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>test-compile</goal>
|
|
||||||
</goals>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-maven-allopen</artifactId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>build-helper-maven-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>generate-sources</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>add-source</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<sources>
|
|
||||||
<source>${basedir}/src/main/java</source>
|
|
||||||
<source>${basedir}/src/main/kotlin</source>
|
|
||||||
</sources>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
<execution>
|
|
||||||
<id>test-compile</id>
|
|
||||||
<phase>test-compile</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>add-test-source</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<sources>
|
|
||||||
<source>${basedir}/src/test/java</source>
|
|
||||||
<source>${basedir}/src/test/kotlin</source>
|
|
||||||
</sources>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<jayway-rest-assured.version>2.9.0</jayway-rest-assured.version>
|
<jayway-rest-assured.version>2.9.0</jayway-rest-assured.version>
|
||||||
<kotlin.version>1.2.71</kotlin.version> <!-- Same as spring-boot-dependencies:2.1.7.RELEASE -->
|
|
||||||
<httpclient.version>4.5.8</httpclient.version>
|
<httpclient.version>4.5.8</httpclient.version>
|
||||||
<start-class>com.baeldung.Spring5Application</start-class>
|
<start-class>com.baeldung.Spring5Application</start-class>
|
||||||
<javafaker.version>0.18</javafaker.version>
|
<javafaker.version>0.18</javafaker.version>
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
package com.baeldung.springbootkotlin
|
|
||||||
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
|
||||||
import org.springframework.web.bind.annotation.RestController
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
class HelloController(val helloService: HelloService) {
|
|
||||||
|
|
||||||
@GetMapping("/hello")
|
|
||||||
fun helloKotlin(): String {
|
|
||||||
return "hello world"
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/hello-service")
|
|
||||||
fun helloKotlinService(): String {
|
|
||||||
return helloService.getHello()
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/hello-dto")
|
|
||||||
fun helloDto(): HelloDto {
|
|
||||||
return HelloDto("Hello from the dto")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
package com.baeldung.springbootkotlin
|
|
||||||
|
|
||||||
data class HelloDto(val greeting: String)
|
|
|
@ -1,11 +0,0 @@
|
||||||
package com.baeldung.springbootkotlin
|
|
||||||
|
|
||||||
import org.springframework.stereotype.Service
|
|
||||||
|
|
||||||
@Service
|
|
||||||
class HelloService {
|
|
||||||
|
|
||||||
fun getHello(): String {
|
|
||||||
return "hello service"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
package com.baeldung.springbootkotlin
|
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
|
||||||
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
|
|
||||||
|
|
||||||
@SpringBootApplication(scanBasePackages = arrayOf("com.baeldung.springbootkotlin"), exclude = arrayOf(SecurityAutoConfiguration::class))
|
|
||||||
class KotlinDemoApplication
|
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
|
||||||
SpringApplication.run(KotlinDemoApplication::class.java, *args)
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
package com.baeldung.springbootkotlin
|
|
||||||
|
|
||||||
import org.junit.Assert.assertEquals
|
|
||||||
import org.junit.Assert.assertNotNull
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest
|
|
||||||
import org.springframework.boot.test.web.client.TestRestTemplate
|
|
||||||
import org.springframework.http.HttpStatus
|
|
||||||
import org.springframework.test.context.junit4.SpringRunner
|
|
||||||
|
|
||||||
@RunWith(SpringRunner::class)
|
|
||||||
@SpringBootTest(
|
|
||||||
classes = arrayOf(KotlinDemoApplication::class),
|
|
||||||
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
|
||||||
class KotlinDemoApplicationIntegrationTest {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
lateinit var testRestTemplate: TestRestTemplate
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun whenCalled_thenShouldReturnHello() {
|
|
||||||
val result = testRestTemplate.withBasicAuth("user", "pass")
|
|
||||||
.getForEntity("/hello", String::class.java)
|
|
||||||
|
|
||||||
assertNotNull(result)
|
|
||||||
assertEquals(HttpStatus.OK, result?.statusCode)
|
|
||||||
assertEquals("hello world", result?.body)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun whenCalled_thenShouldReturnHelloService() {
|
|
||||||
val result = testRestTemplate.withBasicAuth("user", "pass")
|
|
||||||
.getForEntity("/hello-service", String::class.java)
|
|
||||||
|
|
||||||
assertNotNull(result)
|
|
||||||
assertEquals(HttpStatus.OK, result?.statusCode)
|
|
||||||
assertEquals(result?.body, "hello service")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun whenCalled_thenShouldReturnJson() {
|
|
||||||
val result = testRestTemplate.withBasicAuth("user", "pass")
|
|
||||||
.getForEntity("/hello-dto", HelloDto::class.java)
|
|
||||||
|
|
||||||
assertNotNull(result)
|
|
||||||
assertEquals(HttpStatus.OK, result?.statusCode)
|
|
||||||
assertEquals(result?.body, HelloDto("Hello from the dto"))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -38,7 +38,6 @@
|
||||||
<module>spring-security-oauth2-sso</module>
|
<module>spring-security-oauth2-sso</module>
|
||||||
<module>spring-security-web-thymeleaf</module>
|
<module>spring-security-web-thymeleaf</module>
|
||||||
<module>spring-security-web-x509</module>
|
<module>spring-security-web-x509</module>
|
||||||
<module>spring-security-kotlin-dsl</module>
|
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
### Relevant Articles:
|
|
||||||
|
|
||||||
- [Spring Security with Kotlin DSL](https://www.baeldung.com/kotlin/spring-security-dsl)
|
|
|
@ -1,87 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>parent-boot-2</artifactId>
|
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
|
||||||
<relativePath>../../parent-boot-2</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<groupId>com.baeldung.spring.security.dsl</groupId>
|
|
||||||
<artifactId>spring-security-kotlin-dsl</artifactId>
|
|
||||||
<version>1.0</version>
|
|
||||||
<name>spring-security-kotlin-dsl</name>
|
|
||||||
<description>Spring Security Kotlin DSL</description>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.module</groupId>
|
|
||||||
<artifactId>jackson-module-kotlin</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-reflect</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-stdlib-jdk8</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.projectlombok</groupId>
|
|
||||||
<artifactId>lombok</artifactId>
|
|
||||||
<optional>true</optional>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
|
|
||||||
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-maven-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<args>
|
|
||||||
<arg>-Xjsr305=strict</arg>
|
|
||||||
</args>
|
|
||||||
<compilerPlugins>
|
|
||||||
<plugin>spring</plugin>
|
|
||||||
</compilerPlugins>
|
|
||||||
</configuration>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jetbrains.kotlin</groupId>
|
|
||||||
<artifactId>kotlin-maven-allopen</artifactId>
|
|
||||||
<version>${kotlin.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<java.version>11</java.version>
|
|
||||||
<kotlin.version>1.3.72</kotlin.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -1,71 +0,0 @@
|
||||||
package com.baeldung.security.kotlin.dsl
|
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
|
||||||
import org.springframework.boot.runApplication
|
|
||||||
import org.springframework.context.annotation.Configuration
|
|
||||||
import org.springframework.context.support.beans
|
|
||||||
import org.springframework.core.annotation.Order
|
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
|
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
|
|
||||||
import org.springframework.security.config.web.servlet.invoke
|
|
||||||
import org.springframework.security.core.userdetails.User
|
|
||||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager
|
|
||||||
import org.springframework.web.servlet.function.ServerResponse
|
|
||||||
import org.springframework.web.servlet.function.router
|
|
||||||
|
|
||||||
@EnableWebSecurity
|
|
||||||
@SpringBootApplication
|
|
||||||
class SpringSecurityKotlinApplication
|
|
||||||
|
|
||||||
@Order(1)
|
|
||||||
@Configuration
|
|
||||||
class AdminSecurityConfiguration : WebSecurityConfigurerAdapter() {
|
|
||||||
override fun configure(http: HttpSecurity?) {
|
|
||||||
http {
|
|
||||||
authorizeRequests {
|
|
||||||
authorize("/greetings/**", hasAuthority("ROLE_ADMIN"))
|
|
||||||
}
|
|
||||||
httpBasic {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
class BasicSecurityConfiguration : WebSecurityConfigurerAdapter() {
|
|
||||||
override fun configure(http: HttpSecurity?) {
|
|
||||||
http {
|
|
||||||
authorizeRequests {
|
|
||||||
authorize("/**", permitAll)
|
|
||||||
}
|
|
||||||
httpBasic {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
|
||||||
runApplication<SpringSecurityKotlinApplication>(*args) {
|
|
||||||
addInitializers( beans {
|
|
||||||
bean {
|
|
||||||
fun user(user: String, password: String, vararg roles: String) =
|
|
||||||
User
|
|
||||||
.withDefaultPasswordEncoder()
|
|
||||||
.username(user)
|
|
||||||
.password(password)
|
|
||||||
.roles(*roles)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
InMemoryUserDetailsManager(user("user", "password", "USER")
|
|
||||||
, user("admin", "password", "USER", "ADMIN"))
|
|
||||||
}
|
|
||||||
|
|
||||||
bean {
|
|
||||||
router {
|
|
||||||
GET("/greetings") {
|
|
||||||
request -> request.principal().map { it.name }.map { ServerResponse.ok().body(mapOf("greeting" to "Hello $it")) }.orElseGet { ServerResponse.badRequest().build() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,35 +0,0 @@
|
||||||
package com.spring.security.kotlin.dsl
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired
|
|
||||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest
|
|
||||||
import org.springframework.security.test.context.support.WithMockUser
|
|
||||||
import org.springframework.test.context.junit4.SpringRunner
|
|
||||||
import org.springframework.test.web.servlet.MockMvc
|
|
||||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.*
|
|
||||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user
|
|
||||||
import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic
|
|
||||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated
|
|
||||||
import org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.unauthenticated
|
|
||||||
import org.springframework.test.web.servlet.get
|
|
||||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*
|
|
||||||
import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
|
|
||||||
|
|
||||||
@RunWith(SpringRunner::class)
|
|
||||||
@SpringBootTest
|
|
||||||
@AutoConfigureMockMvc
|
|
||||||
class SpringSecurityKotlinApplicationTests {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private lateinit var mockMvc: MockMvc
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `ordinary user not permitted to access the endpoint`() {
|
|
||||||
this.mockMvc
|
|
||||||
.perform(get("/greetings")
|
|
||||||
.with(httpBasic("user", "password")))
|
|
||||||
.andExpect(unauthenticated())
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue