diff --git a/pom.xml b/pom.xml index d27c4d8a3d..f40659bc16 100644 --- a/pom.xml +++ b/pom.xml @@ -1,18 +1,18 @@ + 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"> 4.0.0 com.baeldung parent-modules 1.0.0-SNAPSHOT - parent-modules + parent-modules pom - - quarkus - + + quarkus + @@ -57,11 +57,11 @@ test - org.junit.jupiter - junit-jupiter-api + org.junit.jupiter + junit-jupiter-api ${junit-jupiter.version} test - + org.hamcrest hamcrest-core @@ -123,22 +123,22 @@ - - org.junit.platform - junit-platform-surefire-provider - ${junit-platform.version} - - - org.junit.jupiter - junit-jupiter-engine - ${junit-jupiter.version} - - - org.junit.vintage - junit-vintage-engine - ${junit-jupiter.version} - - + + org.junit.platform + junit-platform-surefire-provider + ${junit-platform.version} + + + org.junit.jupiter + junit-jupiter-engine + ${junit-jupiter.version} + + + org.junit.vintage + junit-vintage-engine + ${junit-jupiter.version} + + org.apache.maven.plugins @@ -328,62 +328,62 @@ parent-boot-1 - parent-boot-2 - parent-spring-4 - parent-spring-5 - parent-java - parent-kotlin - - akka-streams - algorithms-genetic - algorithms-miscellaneous-1 - algorithms-miscellaneous-2 - algorithms-miscellaneous-3 - algorithms-sorting - animal-sniffer-mvn-plugin - annotations - antlr - apache-avro - apache-bval - apache-curator - apache-cxf - apache-fop - apache-geode - apache-meecrowave - apache-opennlp - apache-poi - apache-pulsar - apache-shiro - apache-solrj - apache-spark - apache-thrift - apache-tika - apache-velocity - apache-zookeeper - asciidoctor - asm - atomix - autovalue - aws - aws-lambda - axon - azure + parent-boot-2 + parent-spring-4 + parent-spring-5 + parent-java + parent-kotlin + + akka-streams + algorithms-genetic + algorithms-miscellaneous-1 + algorithms-miscellaneous-2 + algorithms-miscellaneous-3 + algorithms-sorting + animal-sniffer-mvn-plugin + annotations + antlr + apache-avro + apache-bval + apache-curator + apache-cxf + apache-fop + apache-geode + apache-meecrowave + apache-opennlp + apache-poi + apache-pulsar + apache-shiro + apache-solrj + apache-spark + apache-thrift + apache-tika + apache-velocity + apache-zookeeper + asciidoctor + asm + atomix + autovalue + aws + aws-lambda + axon + azure - blade + blade - bootique + bootique - cas - cdi - checker-plugin - core-groovy - core-groovy-2 - core-groovy-collections - - - - core-java-modules/core-java-8 - core-java-modules/core-java-8-2 + cas + cdi + checker-plugin + core-groovy + core-groovy-2 + core-groovy-collections + + + + core-java-modules/core-java-8 + core-java-modules/core-java-8-2 core-java-modules/core-java-lambdas @@ -475,84 +475,84 @@ jaxb - jee-7-security - jersey - JGit - jgroups - jhipster - jhipster-5 - jib - jjwt - jmeter - jmh - jni - jooby - jsf - json - json-path - jsoup - jta + jee-7-security + jersey + JGit + jgroups + jhipster + jhipster-5 + jib + jjwt + jmeter + jmh + jni + jooby + jsf + json + json-path + jsoup + jta - - kotlin-libraries - kotlin-libraries-2 + + kotlin-libraries + kotlin-libraries-2 - - libraries - libraries-2 - libraries-data - libraries-apache-commons - libraries-primitive - libraries-security - libraries-server - libraries-http - linkrest - logging-modules - lombok - lucene + + libraries + libraries-2 + libraries-data + libraries-apache-commons + libraries-primitive + libraries-security + libraries-server + libraries-http + linkrest + logging-modules + lombok + lucene - mapstruct - maven - maven-archetype - - maven-polyglot/maven-polyglot-json-extension - - mesos-marathon - metrics - - microprofile - msf4j - - mustache - mybatis + mapstruct + maven + maven-archetype + + maven-polyglot/maven-polyglot-json-extension + + mesos-marathon + metrics + + microprofile + msf4j + + mustache + mybatis - optaplanner - orika - osgi + optaplanner + orika + osgi - patterns - pdf - performance-tests - - protobuffer + patterns + pdf + performance-tests + + protobuffer - persistence-modules - quarkus + persistence-modules + quarkus - rabbitmq - - ratpack - reactor-core - rest-with-spark-java - resteasy - restx - - rule-engines + rabbitmq + + ratpack + reactor-core + rest-with-spark-java + resteasy + restx + + rule-engines rsocket - rxjava - rxjava-2 - software-security/sql-injection-samples + rxjava + rxjava-2 + software-security/sql-injection-samples tensorflow-java spring-boot-flowable @@ -563,239 +563,240 @@ - - default-second - - + + default-second + + - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - - 3 - true - - **/*IntegrationTest.java - **/*IntTest.java - **/*LongRunningUnitTest.java - **/*ManualTest.java - **/*JdbcTest.java - **/*LiveTest.java - - - + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + 3 + true + + **/*IntegrationTest.java + **/*IntTest.java + **/*LongRunningUnitTest.java + **/*ManualTest.java + **/*JdbcTest.java + **/*LiveTest.java + + + - - + + - - parent-boot-1 - parent-boot-2 - parent-spring-4 - parent-spring-5 - parent-java - parent-kotlin + + parent-boot-1 + parent-boot-2 + parent-spring-4 + parent-spring-5 + parent-java + parent-kotlin - saas - spark-java + saas + spark-java - spring-4 + spring-4 - spring-5 - spring-5-webflux - spring-5-data-reactive - spring-5-mvc - spring-5-reactive - spring-5-reactive-client - spring-5-reactive-oauth - spring-5-reactive-security - spring-5-security - spring-5-security-oauth - spring-5-security-cognito + spring-5 + spring-5-webflux + spring-5-data-reactive + spring-5-mvc + spring-5-reactive + spring-5-reactive-client + spring-5-reactive-oauth + spring-5-reactive-security + spring-5-security + spring-5-security-oauth + spring-5-security-cognito - spring-activiti - spring-akka - spring-all - spring-amqp - spring-amqp-simple - spring-aop - spring-apache-camel - spring-batch - spring-bom + spring-activiti + spring-akka + spring-all + spring-amqp + spring-amqp-simple + spring-aop + spring-apache-camel + spring-batch + spring-bom - spring-boot - spring-boot-admin - spring-boot-angular - spring-boot-angular-ecommerce - spring-boot-autoconfiguration - spring-boot-bootstrap - spring-boot-camel - - spring-boot-client + spring-boot + spring-boot-admin + spring-boot-angular + spring-boot-angular-ecommerce + spring-boot-autoconfiguration + spring-boot-bootstrap + spring-boot-camel + + spring-boot-client - spring-boot-crud - spring-boot-ctx-fluent - spring-boot-custom-starter - spring-boot-disable-console-logging - - spring-boot-jasypt - spring-boot-keycloak - spring-boot-logging-log4j2 - spring-boot-mvc - spring-boot-mvc-birt - spring-boot-ops - spring-boot-ops-2 - spring-boot-rest - spring-boot-data - spring-boot-parent - spring-boot-property-exp - spring-boot-security - spring-boot-testing - spring-boot-vue - spring-boot-libraries + spring-boot-crud + spring-boot-ctx-fluent + spring-boot-custom-starter + spring-boot-disable-console-logging + + spring-boot-jasypt + spring-boot-keycloak + spring-boot-kotlin + spring-boot-logging-log4j2 + spring-boot-mvc + spring-boot-mvc-birt + spring-boot-ops + spring-boot-ops-2 + spring-boot-rest + spring-boot-data + spring-boot-parent + spring-boot-property-exp + spring-boot-security + spring-boot-testing + spring-boot-vue + spring-boot-libraries - spring-cloud - spring-cloud-bus - - spring-cloud-data-flow + spring-cloud + spring-cloud-bus + + spring-cloud-data-flow - spring-core - spring-core-2 - spring-cucumber + spring-core + spring-core-2 + spring-cucumber - spring-data-rest - spring-data-rest-querydsl - spring-dispatcher-servlet - spring-drools + spring-data-rest + spring-data-rest-querydsl + spring-dispatcher-servlet + spring-drools - spring-ehcache - spring-ejb - spring-exceptions + spring-ehcache + spring-ejb + spring-exceptions - spring-freemarker + spring-freemarker - spring-groovy + spring-groovy - spring-integration + spring-integration - spring-jenkins-pipeline - spring-jersey - spring-jinq - spring-jms - spring-jooq + spring-jenkins-pipeline + spring-jersey + spring-jinq + spring-jms + spring-jooq - spring-kafka - spring-katharsis + spring-kafka + spring-katharsis - spring-ldap + spring-ldap - spring-mobile - spring-mockito - spring-mvc-forms-jsp - spring-mvc-forms-thymeleaf - spring-mvc-java - spring-mvc-kotlin - spring-mvc-simple - spring-mvc-simple-2 - spring-mvc-velocity - spring-mvc-webflow - spring-mvc-xml + spring-mobile + spring-mockito + spring-mvc-forms-jsp + spring-mvc-forms-thymeleaf + spring-mvc-java + spring-mvc-kotlin + spring-mvc-simple + spring-mvc-simple-2 + spring-mvc-velocity + spring-mvc-webflow + spring-mvc-xml - spring-protobuf - + spring-protobuf + - spring-quartz + spring-quartz - spring-reactive-kotlin - spring-reactor - spring-remoting - spring-rest - spring-rest-angular - spring-rest-full - spring-rest-hal-browser - spring-rest-query-language - spring-rest-shell - spring-rest-simple - spring-resttemplate - spring-roo - spring-security-acl - spring-security-angular/server - spring-security-cache-control + spring-reactive-kotlin + spring-reactor + spring-remoting + spring-rest + spring-rest-angular + spring-rest-full + spring-rest-hal-browser + spring-rest-query-language + spring-rest-shell + spring-rest-simple + spring-resttemplate + spring-roo + spring-security-acl + spring-security-angular/server + spring-security-cache-control - spring-security-client + spring-security-client - spring-security-core - spring-security-mvc-boot - spring-security-mvc-custom - spring-security-mvc-digest-auth + spring-security-core + spring-security-mvc-boot + spring-security-mvc-custom + spring-security-mvc-digest-auth spring-security-mvc-jsonview - spring-security-mvc-ldap - spring-security-mvc-login - spring-security-mvc-persisted-remember-me - spring-security-mvc-session - spring-security-mvc-socket - spring-security-openid - - spring-security-rest - spring-security-rest-basic-auth - spring-security-rest-custom - spring-security-sso - spring-security-stormpath - spring-security-thymeleaf - spring-security-x509 - spring-session - spring-sleuth - spring-soap - spring-social-login - spring-spel - spring-state-machine - spring-static-resources - spring-swagger-codegen + spring-security-mvc-ldap + spring-security-mvc-login + spring-security-mvc-persisted-remember-me + spring-security-mvc-session + spring-security-mvc-socket + spring-security-openid + + spring-security-rest + spring-security-rest-basic-auth + spring-security-rest-custom + spring-security-sso + spring-security-stormpath + spring-security-thymeleaf + spring-security-x509 + spring-session + spring-sleuth + spring-soap + spring-social-login + spring-spel + spring-state-machine + spring-static-resources + spring-swagger-codegen - spring-thymeleaf + spring-thymeleaf - spring-userservice + spring-userservice - spring-vault - spring-vertx + spring-vault + spring-vertx - spring-webflux-amqp + spring-webflux-amqp - spring-zuul + spring-zuul - static-analysis - stripe - structurizr - struts-2 + static-analysis + stripe + structurizr + struts-2 - testing-modules + testing-modules - twilio - Twitter4J + twilio + Twitter4J - undertow + undertow - vavr - vertx - vertx-and-rxjava - video-tutorials - vraptor + vavr + vertx + vertx-and-rxjava + video-tutorials + vraptor - wicket + wicket - xml - xmlunit-2 - xstream + xml + xmlunit-2 + xstream tensorflow-java spring-boot-flowable spring-security-kerberos morphia - + - + spring-context @@ -840,7 +841,7 @@ spring-boot-camel spring-boot-client spring-boot-custom-starter - greeter-spring-boot-autoconfigure + greeter-spring-boot-autoconfigure greeter-spring-boot-sample-app persistence-modules/spring-boot-h2/spring-boot-h2-database spring-boot-jasypt @@ -943,571 +944,571 @@ - - default-heavy - - + + default-heavy + + - - org.apache.maven.plugins - maven-surefire-plugin - ${maven-surefire-plugin.version} - - 3 - true - - **/*IntegrationTest.java - **/*IntTest.java - **/*LongRunningUnitTest.java - **/*ManualTest.java - **/*JdbcTest.java - **/*LiveTest.java - - - + + org.apache.maven.plugins + maven-surefire-plugin + ${maven-surefire-plugin.version} + + 3 + true + + **/*IntegrationTest.java + **/*IntTest.java + **/*LongRunningUnitTest.java + **/*ManualTest.java + **/*JdbcTest.java + **/*LiveTest.java + + + - - + + - - parent-boot-1 - parent-boot-2 - parent-spring-4 - parent-spring-5 - parent-java - parent-kotlin + + parent-boot-1 + parent-boot-2 + parent-spring-4 + parent-spring-5 + parent-java + parent-kotlin - core-java-modules/core-java-concurrency-advanced - core-kotlin - core-kotlin-2 - core-kotlin-io + core-java-modules/core-java-concurrency-advanced + core-kotlin + core-kotlin-2 + core-kotlin-io - jenkins/hello-world - jws + jenkins/hello-world + jws - libraries + libraries - persistence-modules/hibernate5 - persistence-modules/hibernate-mapping - persistence-modules/java-jpa - persistence-modules/java-mongodb - persistence-modules/jnosql + persistence-modules/hibernate5 + persistence-modules/hibernate-mapping + persistence-modules/java-jpa + persistence-modules/java-mongodb + persistence-modules/jnosql - vaadin - - + vaadin + + - - integration-lite-first + + integration-lite-first - - - - org.apache.maven.plugins - maven-surefire-plugin - - - **/*ManualTest.java - **/*LiveTest.java - - - **/*IntegrationTest.java - **/*IntTest.java - - - - - + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*ManualTest.java + **/*LiveTest.java + + + **/*IntegrationTest.java + **/*IntTest.java + + + + + - - parent-boot-1 - parent-boot-2 - parent-spring-4 - parent-spring-5 - parent-java - parent-kotlin - - akka-streams - algorithms-genetic - algorithms-miscellaneous-1 - algorithms-miscellaneous-2 - algorithms-miscellaneous-3 - algorithms-sorting - animal-sniffer-mvn-plugin - annotations - antlr - apache-avro - apache-bval - apache-curator - apache-cxf - apache-fop - apache-geode - apache-meecrowave - apache-opennlp - apache-poi - apache-pulsar - apache-shiro - apache-solrj - apache-spark - apache-thrift - apache-tika - apache-velocity - apache-zookeeper - asciidoctor - asm - atomix - autovalue - aws - aws-lambda - axon - azure + + parent-boot-1 + parent-boot-2 + parent-spring-4 + parent-spring-5 + parent-java + parent-kotlin + + akka-streams + algorithms-genetic + algorithms-miscellaneous-1 + algorithms-miscellaneous-2 + algorithms-miscellaneous-3 + algorithms-sorting + animal-sniffer-mvn-plugin + annotations + antlr + apache-avro + apache-bval + apache-curator + apache-cxf + apache-fop + apache-geode + apache-meecrowave + apache-opennlp + apache-poi + apache-pulsar + apache-shiro + apache-solrj + apache-spark + apache-thrift + apache-tika + apache-velocity + apache-zookeeper + asciidoctor + asm + atomix + autovalue + aws + aws-lambda + axon + azure - bootique + bootique - cas - cdi - checker-plugin - core-groovy - core-groovy-2 - core-groovy-collections - - - core-java-modules/core-java-8 - core-java-modules/core-java-8-2 - - - core-java-modules/core-java-arrays - core-java-modules/core-java-collections - core-java-modules/core-java-collections-list - core-java-modules/core-java-collections-list-2 - core-java-modules/core-java-collections-array-list - core-java-modules/core-java-collections-set - core-java-modules/core-java-concurrency-basic - core-java-modules/core-java-concurrency-collections - core-java-modules/core-java-io - core-java-modules/core-java-nio - core-java-modules/core-java-security - core-java-modules/core-java-lang-syntax - core-java-modules/core-java-lang - core-java-modules/core-java-lang-oop - core-java-modules/core-java-lang-oop-2 - core-java-modules - core-java-modules/core-java-networking - core-java-modules/core-java-perf - core-java-modules/core-java-sun - core-scala - couchbase - custom-pmd + cas + cdi + checker-plugin + core-groovy + core-groovy-2 + core-groovy-collections + + + core-java-modules/core-java-8 + core-java-modules/core-java-8-2 + + + core-java-modules/core-java-arrays + core-java-modules/core-java-collections + core-java-modules/core-java-collections-list + core-java-modules/core-java-collections-list-2 + core-java-modules/core-java-collections-array-list + core-java-modules/core-java-collections-set + core-java-modules/core-java-concurrency-basic + core-java-modules/core-java-concurrency-collections + core-java-modules/core-java-io + core-java-modules/core-java-nio + core-java-modules/core-java-security + core-java-modules/core-java-lang-syntax + core-java-modules/core-java-lang + core-java-modules/core-java-lang-oop + core-java-modules/core-java-lang-oop-2 + core-java-modules + core-java-modules/core-java-networking + core-java-modules/core-java-perf + core-java-modules/core-java-sun + core-scala + couchbase + custom-pmd - dagger - data-structures - ddd - deeplearning4j - disruptor - dozer - drools - dubbo + dagger + data-structures + ddd + deeplearning4j + disruptor + dozer + drools + dubbo - ethereum + ethereum - feign - flyway-cdi-extension + feign + flyway-cdi-extension - geotools - google-cloud - google-web-toolkit - - - graphql/graphql-java - grpc - gson - guava - guava-collections - guava-modules - - guice + geotools + google-cloud + google-web-toolkit + + + graphql/graphql-java + grpc + gson + guava + guava-collections + guava-modules + + guice - hazelcast - helidon - httpclient - httpclient-simple - hystrix + hazelcast + helidon + httpclient + httpclient-simple + hystrix - image-processing - immutables + image-processing + immutables - jackson - jackson-2 - jackson-simple - java-collections-conversions - java-collections-maps - java-collections-maps-2 - - java-ee-8-security-api - java-lite - java-numbers - java-rmi - java-spi - java-streams - - java-strings - java-strings-2 - java-vavr-stream - java-websocket - javafx - javax-servlets - javaxval - jaxb - + java-ee-8-security-api + java-lite + java-numbers + java-rmi + java-spi + java-streams + + java-strings + java-strings-2 + java-vavr-stream + java-websocket + javafx + javax-servlets + javaxval + jaxb + - jee-7-security - jersey - JGit - jgroups - jhipster - jhipster-5 - jib - jjwt - jmeter - jmh - jni - jooby - jsf - json - json-path - jsoup - jta + jee-7-security + jersey + JGit + jgroups + jhipster + jhipster-5 + jib + jjwt + jmeter + jmh + jni + jooby + jsf + json + json-path + jsoup + jta - - kotlin-libraries + + kotlin-libraries - - libraries - libraries-data - libraries-apache-commons - libraries-security - libraries-server - libraries-http - linkrest - logging-modules - lombok - lucene + + libraries + libraries-data + libraries-apache-commons + libraries-security + libraries-server + libraries-http + linkrest + logging-modules + lombok + lucene - mapstruct - maven - - maven-archetype - - maven-polyglot/maven-polyglot-json-extension - - mesos-marathon - metrics - - microprofile - msf4j - - mustache - mybatis + mapstruct + maven + + maven-archetype + + maven-polyglot/maven-polyglot-json-extension + + mesos-marathon + metrics + + microprofile + msf4j + + mustache + mybatis - optaplanner - orika - osgi + optaplanner + orika + osgi - patterns - pdf - performance-tests - - protobuffer + patterns + pdf + performance-tests + + protobuffer - persistence-modules + persistence-modules - rabbitmq - - ratpack - reactor-core - rest-with-spark-java - resteasy - restx - - rule-engines - rsocket - rxjava - rxjava-2 + rabbitmq + + ratpack + reactor-core + rest-with-spark-java + resteasy + restx + + rule-engines + rsocket + rxjava + rxjava-2 - + - + - - integration-lite-second + + integration-lite-second - - - - org.apache.maven.plugins - maven-surefire-plugin - - - **/*ManualTest.java - **/*LiveTest.java - - - **/*IntegrationTest.java - **/*IntTest.java - - - - - + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*ManualTest.java + **/*LiveTest.java + + + **/*IntegrationTest.java + **/*IntTest.java + + + + + - - parent-boot-1 - parent-boot-2 - parent-spring-4 - parent-spring-5 - parent-java - parent-kotlin + + parent-boot-1 + parent-boot-2 + parent-spring-4 + parent-spring-5 + parent-java + parent-kotlin - saas - spark-java + saas + spark-java - spring-4 + spring-4 - spring-5 - spring-5-data-reactive - spring-5-mvc - spring-5-reactive - spring-5-reactive-client - spring-5-reactive-oauth - spring-5-reactive-security - spring-5-security - spring-5-security-oauth - spring-5-security-cognito - spring-activiti - spring-akka - spring-all - spring-amqp - spring-amqp-simple - spring-aop - spring-apache-camel - spring-batch - spring-bom + spring-5 + spring-5-data-reactive + spring-5-mvc + spring-5-reactive + spring-5-reactive-client + spring-5-reactive-oauth + spring-5-reactive-security + spring-5-security + spring-5-security-oauth + spring-5-security-cognito + spring-activiti + spring-akka + spring-all + spring-amqp + spring-amqp-simple + spring-aop + spring-apache-camel + spring-batch + spring-bom - spring-boot - spring-boot-admin - spring-boot-angular - spring-boot-angular-ecommerce - spring-boot-autoconfiguration - spring-boot-bootstrap - spring-boot-camel - - spring-boot-client - spring-boot-crud - spring-boot-ctx-fluent - spring-boot-custom-starter - spring-boot-disable-console-logging - - spring-boot-jasypt - spring-boot-keycloak - spring-boot-logging-log4j2 - spring-boot-mvc - spring-boot-mvc-birt - spring-boot-ops - spring-boot-ops-2 - spring-boot-rest - spring-boot-data - spring-boot-parent - spring-boot-property-exp - spring-boot-security - spring-boot-vue + spring-boot + spring-boot-admin + spring-boot-angular + spring-boot-angular-ecommerce + spring-boot-autoconfiguration + spring-boot-bootstrap + spring-boot-camel + + spring-boot-client + spring-boot-crud + spring-boot-ctx-fluent + spring-boot-custom-starter + spring-boot-disable-console-logging + + spring-boot-jasypt + spring-boot-keycloak + spring-boot-logging-log4j2 + spring-boot-mvc + spring-boot-mvc-birt + spring-boot-ops + spring-boot-ops-2 + spring-boot-rest + spring-boot-data + spring-boot-parent + spring-boot-property-exp + spring-boot-security + spring-boot-vue - spring-cloud - spring-cloud-bus - - spring-cloud-data-flow + spring-cloud + spring-cloud-bus + + spring-cloud-data-flow - spring-core - spring-core-2 - spring-cucumber + spring-core + spring-core-2 + spring-cucumber - spring-data-rest - spring-data-rest-querydsl - spring-dispatcher-servlet - spring-drools + spring-data-rest + spring-data-rest-querydsl + spring-dispatcher-servlet + spring-drools spring-ehcache - spring-ejb - spring-exceptions + spring-ejb + spring-exceptions - spring-freemarker + spring-freemarker - spring-groovy + spring-groovy - spring-integration + spring-integration - spring-jenkins-pipeline - spring-jersey - spring-jinq - spring-jms - spring-jooq + spring-jenkins-pipeline + spring-jersey + spring-jinq + spring-jms + spring-jooq - spring-kafka - spring-katharsis + spring-kafka + spring-katharsis - spring-ldap + spring-ldap - spring-mobile - spring-mockito - spring-mvc-forms-jsp - spring-mvc-forms-thymeleaf - spring-mvc-java - spring-mvc-kotlin - spring-mvc-simple - spring-mvc-simple-2 - spring-mvc-velocity - spring-mvc-webflow - spring-mvc-xml + spring-mobile + spring-mockito + spring-mvc-forms-jsp + spring-mvc-forms-thymeleaf + spring-mvc-java + spring-mvc-kotlin + spring-mvc-simple + spring-mvc-simple-2 + spring-mvc-velocity + spring-mvc-webflow + spring-mvc-xml - spring-protobuf - + spring-protobuf + - spring-quartz + spring-quartz - spring-reactive-kotlin - spring-reactor - spring-remoting - spring-rest - spring-rest-angular - spring-rest-full - spring-rest-hal-browser - spring-rest-query-language - spring-rest-shell - spring-rest-simple - spring-resttemplate - spring-roo + spring-reactive-kotlin + spring-reactor + spring-remoting + spring-rest + spring-rest-angular + spring-rest-full + spring-rest-hal-browser + spring-rest-query-language + spring-rest-shell + spring-rest-simple + spring-resttemplate + spring-roo - spring-security-acl - spring-security-angular/server - spring-security-cache-control + spring-security-acl + spring-security-angular/server + spring-security-cache-control - spring-security-client + spring-security-client - spring-security-core - spring-security-mvc-boot - spring-security-mvc-custom - spring-security-mvc-digest-auth - spring-security-mvc-ldap - spring-security-mvc-login - spring-security-mvc-persisted-remember-me - spring-security-mvc-session - spring-security-mvc-socket - spring-security-openid - - spring-security-rest - spring-security-rest-basic-auth - spring-security-rest-custom - spring-security-sso - spring-security-stormpath - spring-security-thymeleaf - spring-security-x509 - spring-session - spring-sleuth - spring-soap - spring-social-login - spring-spel - spring-state-machine - spring-static-resources - spring-swagger-codegen + spring-security-core + spring-security-mvc-boot + spring-security-mvc-custom + spring-security-mvc-digest-auth + spring-security-mvc-ldap + spring-security-mvc-login + spring-security-mvc-persisted-remember-me + spring-security-mvc-session + spring-security-mvc-socket + spring-security-openid + + spring-security-rest + spring-security-rest-basic-auth + spring-security-rest-custom + spring-security-sso + spring-security-stormpath + spring-security-thymeleaf + spring-security-x509 + spring-session + spring-sleuth + spring-soap + spring-social-login + spring-spel + spring-state-machine + spring-static-resources + spring-swagger-codegen - spring-thymeleaf + spring-thymeleaf - spring-userservice + spring-userservice - spring-vault - spring-vertx + spring-vault + spring-vertx - spring-webflux-amqp + spring-webflux-amqp - spring-zuul + spring-zuul - static-analysis - stripe - structurizr - struts-2 + static-analysis + stripe + structurizr + struts-2 - testing-modules + testing-modules - twilio - Twitter4J + twilio + Twitter4J - undertow + undertow - vavr - vertx - vertx-and-rxjava - video-tutorials - vraptor + vavr + vertx + vertx-and-rxjava + video-tutorials + vraptor - wicket + wicket - xml - xmlunit-2 - xstream + xml + xmlunit-2 + xstream - + - + - - integration-heavy + + integration-heavy - - - - org.apache.maven.plugins - maven-surefire-plugin - - - **/*ManualTest.java - **/*LiveTest.java - - - **/*IntegrationTest.java - **/*IntTest.java - - - - - + + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*ManualTest.java + **/*LiveTest.java + + + **/*IntegrationTest.java + **/*IntTest.java + + + + + - - parent-boot-1 - parent-boot-2 - parent-spring-4 - parent-spring-5 - parent-java - parent-kotlin + + parent-boot-1 + parent-boot-2 + parent-spring-4 + parent-spring-5 + parent-java + parent-kotlin - core-java-modules/core-java - core-java-modules/core-java-concurrency-advanced - core-kotlin - core-kotlin-2 + core-java-modules/core-java + core-java-modules/core-java-concurrency-advanced + core-kotlin + core-kotlin-2 - jenkins/hello-world - jws + jenkins/hello-world + jws - libraries + libraries - persistence-modules/hibernate5 - persistence-modules/java-jpa - persistence-modules/java-mongodb - persistence-modules/jnosql + persistence-modules/hibernate5 + persistence-modules/java-jpa + persistence-modules/java-mongodb + persistence-modules/jnosql - vaadin - + vaadin + - + @@ -1541,7 +1542,7 @@ 1.1.7 - + 2.21.0 3.7.0 1.6.0 diff --git a/spring-boot-kotlin/README.md b/spring-boot-kotlin/README.md new file mode 100644 index 0000000000..dc50c24aa0 --- /dev/null +++ b/spring-boot-kotlin/README.md @@ -0,0 +1,2 @@ +### Relevant Articles: +- [Non-blocking Spring Boot with Kotlin Coroutines](http://www.baeldung.com/non-blocking-spring-boot-with-kotlin-coroutines) diff --git a/spring-boot-kotlin/pom.xml b/spring-boot-kotlin/pom.xml new file mode 100644 index 0000000000..25508c52b9 --- /dev/null +++ b/spring-boot-kotlin/pom.xml @@ -0,0 +1,166 @@ + + + 4.0.0 + spring-boot-kotlin + spring-boot-kotlin + jar + Demo project showing how to use non-blocking in Kotlin with Spring Boot + + + parent-kotlin + com.baeldung + 1.0.0-SNAPSHOT + ../parent-kotlin + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + + + + + + + org.springframework.boot + spring-boot-dependencies + ${spring-boot.version} + pom + import + + + + + + + spring-snapshots + Spring Snapshots + https://repo.spring.io/snapshot + + true + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + + + + + org.jetbrains.kotlin + kotlin-reflect + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + + + org.jetbrains.kotlinx + kotlinx-coroutines-core + ${kotlinx-coroutines.version} + + + org.jetbrains.kotlinx + kotlinx-coroutines-reactor + ${kotlinx-coroutines.version} + + + org.springframework.boot + spring-boot-starter-webflux + ${spring-boot.version} + + + com.fasterxml.jackson.module + jackson-module-kotlin + + + org.springframework.data + spring-data-r2dbc + ${r2dbc.version} + + + io.r2dbc + r2dbc-h2 + ${h2-r2dbc.version} + + + io.r2dbc + r2dbc-spi + ${r2dbc-spi.version} + + + org.springframework.boot + spring-boot-starter-test + test + + + junit + junit + + + + + org.junit.jupiter + junit-jupiter-api + test + + + org.junit.jupiter + junit-jupiter-engine + test + + + io.projectreactor + reactor-test + test + + + + + + + org.jetbrains.kotlin + kotlin-maven-plugin + + + -Xjsr305=strict + + + spring + + + + + org.jetbrains.kotlin + kotlin-maven-allopen + ${kotlin.version} + + + + + + + + 1.3.31 + 1.0.0.M1 + 1.0.0.M7 + 1.0.0.BUILD-SNAPSHOT + 1.2.1 + 2.2.0.M2 + + + diff --git a/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/SpringApplication.kt b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/SpringApplication.kt new file mode 100644 index 0000000000..23af4fe90b --- /dev/null +++ b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/SpringApplication.kt @@ -0,0 +1,11 @@ +package com.baeldung.nonblockingcoroutines + +import org.springframework.boot.SpringApplication.run +import org.springframework.boot.autoconfigure.SpringBootApplication + +@SpringBootApplication +class SpringApplication + +fun main(args: Array) { + run(SpringApplication::class.java, *args) +} diff --git a/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/DatastoreConfig.kt b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/DatastoreConfig.kt new file mode 100644 index 0000000000..52ef8a708b --- /dev/null +++ b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/DatastoreConfig.kt @@ -0,0 +1,32 @@ +package com.baeldung.nonblockingcoroutines.config + +import io.r2dbc.h2.H2ConnectionConfiguration +import io.r2dbc.h2.H2ConnectionFactory +import io.r2dbc.spi.ConnectionFactory +import org.springframework.beans.factory.annotation.Value +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration +import org.springframework.data.r2dbc.repository.config.EnableR2dbcRepositories + +@Configuration +@EnableR2dbcRepositories +class DatastoreConfig : AbstractR2dbcConfiguration() { + @Value("\${spring.datasource.username}") + private val userName: String = "" + + @Value("\${spring.datasource.password}") + private val password: String = "" + + @Value("\${spring.datasource.dbname}") + private val dbName: String = "" + + @Bean + override fun connectionFactory(): ConnectionFactory { + return H2ConnectionFactory(H2ConnectionConfiguration.builder() + .inMemory(dbName) + .username(userName) + .password(password) + .build()) + } +} \ No newline at end of file diff --git a/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/RouterConfiguration.kt b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/RouterConfiguration.kt new file mode 100644 index 0000000000..bda1d26278 --- /dev/null +++ b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/RouterConfiguration.kt @@ -0,0 +1,19 @@ +package com.baeldung.nonblockingcoroutines.config + +import com.baeldung.nonblockingcoroutines.handlers.ProductsHandler +import kotlinx.coroutines.FlowPreview +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.web.reactive.function.server.coRouter + +@Configuration +class RouterConfiguration { + + @FlowPreview + @Bean + fun productRoutes(productsHandler: ProductsHandler) = coRouter { + GET("/", productsHandler::findAll) + GET("/{id}", productsHandler::findOne) + GET("/{id}/stock", productsHandler::findOneInStock) + } +} \ No newline at end of file diff --git a/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/WebClientConfiguration.kt b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/WebClientConfiguration.kt new file mode 100644 index 0000000000..85938b8be2 --- /dev/null +++ b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/config/WebClientConfiguration.kt @@ -0,0 +1,12 @@ +package com.baeldung.nonblockingcoroutines.config + +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import org.springframework.web.reactive.function.client.WebClient + +@Configuration +class WebClientConfiguration { + + @Bean + fun webClient() = WebClient.builder().baseUrl("http://localhost:8080").build() +} \ No newline at end of file diff --git a/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductController.kt b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductController.kt new file mode 100644 index 0000000000..91b091859a --- /dev/null +++ b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductController.kt @@ -0,0 +1,49 @@ +package com.baeldung.nonblockingcoroutines.controller + +import com.baeldung.nonblockingcoroutines.model.Product +import com.baeldung.nonblockingcoroutines.repository.ProductRepository +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.http.MediaType +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.reactive.function.client.WebClient +import org.springframework.web.reactive.function.client.bodyToMono +import reactor.core.publisher.Flux +import reactor.core.publisher.Mono + +class ProductController { + @Autowired + lateinit var webClient: WebClient + @Autowired + lateinit var productRepository: ProductRepository + + @GetMapping("/{id}") + fun findOne(@PathVariable id: Int): Mono { + return productRepository + .getProductById(id) + } + + @GetMapping("/{id}/stock") + fun findOneInStock(@PathVariable id: Int): Mono { + val product = productRepository.getProductById(id) + + val stockQuantity = webClient.get() + .uri("/stock-service/product/$id/quantity") + .accept(MediaType.APPLICATION_JSON) + .retrieve() + .bodyToMono() + return product.zipWith(stockQuantity) { productInStock, stockQty -> + ProductStockView(productInStock, stockQty) + } + } + + @GetMapping("/stock-service/product/{id}/quantity") + fun getStockQuantity(): Mono { + return Mono.just(2) + } + + @GetMapping("/") + fun findAll(): Flux { + return productRepository.getAllProducts() + } +} diff --git a/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductControllerCoroutines.kt b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductControllerCoroutines.kt new file mode 100644 index 0000000000..d70d352cda --- /dev/null +++ b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductControllerCoroutines.kt @@ -0,0 +1,49 @@ +package com.baeldung.nonblockingcoroutines.controller + +import com.baeldung.nonblockingcoroutines.model.Product +import com.baeldung.nonblockingcoroutines.repository.ProductRepositoryCoroutines +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.async +import kotlinx.coroutines.flow.Flow +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.http.MediaType.APPLICATION_JSON +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import org.springframework.web.reactive.function.client.WebClient +import org.springframework.web.reactive.function.client.awaitBody +import org.springframework.web.reactive.function.client.awaitExchange + +class ProductControllerCoroutines { + @Autowired + lateinit var webClient: WebClient + + @Autowired + lateinit var productRepository: ProductRepositoryCoroutines + + @GetMapping("/{id}") + suspend fun findOne(@PathVariable id: Int): Product? { + return productRepository.getProductById(id) + } + + @GetMapping("/{id}/stock") + suspend fun findOneInStock(@PathVariable id: Int): ProductStockView { + val product: Deferred = GlobalScope.async { + productRepository.getProductById(id) + } + val quantity: Deferred = GlobalScope.async { + webClient.get() + .uri("/stock-service/product/$id/quantity") + .accept(APPLICATION_JSON) + .awaitExchange().awaitBody() + } + return ProductStockView(product.await()!!, quantity.await()) + } + + @FlowPreview + @GetMapping("/") + fun findAll(): Flow { + return productRepository.getAllProducts() + } +} \ No newline at end of file diff --git a/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductStockView.kt b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductStockView.kt new file mode 100644 index 0000000000..44611fd1de --- /dev/null +++ b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/controller/ProductStockView.kt @@ -0,0 +1,15 @@ +package com.baeldung.nonblockingcoroutines.controller + +import com.baeldung.nonblockingcoroutines.model.Product + +class ProductStockView(product: Product, var stockQuantity: Int) { + var id: Int = 0 + var name: String = "" + var price: Float = 0.0f + + init { + this.id = product.id + this.name = product.name + this.price = product.price + } +} \ No newline at end of file diff --git a/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/handlers/ProductsHandler.kt b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/handlers/ProductsHandler.kt new file mode 100644 index 0000000000..41c4510e0d --- /dev/null +++ b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/handlers/ProductsHandler.kt @@ -0,0 +1,49 @@ +package com.baeldung.nonblockingcoroutines.handlers + +import com.baeldung.nonblockingcoroutines.controller.ProductStockView +import com.baeldung.nonblockingcoroutines.model.Product +import com.baeldung.nonblockingcoroutines.repository.ProductRepositoryCoroutines +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.async +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.http.MediaType +import org.springframework.stereotype.Component +import org.springframework.web.reactive.function.client.WebClient +import org.springframework.web.reactive.function.client.awaitBody +import org.springframework.web.reactive.function.client.awaitExchange +import org.springframework.web.reactive.function.server.ServerRequest +import org.springframework.web.reactive.function.server.ServerResponse +import org.springframework.web.reactive.function.server.bodyAndAwait +import org.springframework.web.reactive.function.server.json + +@Component +class ProductsHandler( + @Autowired var webClient: WebClient, + @Autowired var productRepository: ProductRepositoryCoroutines) { + + @FlowPreview + suspend fun findAll(request: ServerRequest): ServerResponse = + ServerResponse.ok().json().bodyAndAwait(productRepository.getAllProducts()) + + suspend fun findOneInStock(request: ServerRequest): ServerResponse { + val id = request.pathVariable("id").toInt() + + val product: Deferred = GlobalScope.async { + productRepository.getProductById(id) + } + val quantity: Deferred = GlobalScope.async { + webClient.get() + .uri("/stock-service/product/$id/quantity") + .accept(MediaType.APPLICATION_JSON) + .awaitExchange().awaitBody() + } + return ServerResponse.ok().json().bodyAndAwait(ProductStockView(product.await()!!, quantity.await())) + } + + suspend fun findOne(request: ServerRequest): ServerResponse { + val id = request.pathVariable("id").toInt() + return ServerResponse.ok().json().bodyAndAwait(productRepository.getProductById(id)!!) + } +} \ No newline at end of file diff --git a/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/model/Product.kt b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/model/Product.kt new file mode 100644 index 0000000000..c6dcbdc9c4 --- /dev/null +++ b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/model/Product.kt @@ -0,0 +1,7 @@ +package com.baeldung.nonblockingcoroutines.model + +data class Product( + var id: Int = 0, + var name: String = "", + var price: Float = 0.0f +) diff --git a/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepository.kt b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepository.kt new file mode 100644 index 0000000000..20c3827c26 --- /dev/null +++ b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepository.kt @@ -0,0 +1,34 @@ +package com.baeldung.nonblockingcoroutines.repository + +import com.baeldung.nonblockingcoroutines.model.Product +import org.springframework.data.r2dbc.function.DatabaseClient +import org.springframework.stereotype.Repository +import reactor.core.publisher.Flux +import reactor.core.publisher.Mono + +@Repository +class ProductRepository(private val client: DatabaseClient) { + + fun getProductById(id: Int): Mono { + return client.execute().sql("SELECT * FROM products WHERE id = $1") + .bind(0, id) + .`as`(Product::class.java) + .fetch() + .one() + } + + fun addNewProduct(name: String, price: Float): Mono { + return client.execute() + .sql("INSERT INTO products (name, price) VALUES($1, $2)") + .bind(0, name) + .bind(1, price) + .then() + } + + fun getAllProducts(): Flux { + return client.select().from("products") + .`as`(Product::class.java) + .fetch() + .all() + } +} \ No newline at end of file diff --git a/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepositoryCoroutines.kt b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepositoryCoroutines.kt new file mode 100644 index 0000000000..60a19d4d00 --- /dev/null +++ b/spring-boot-kotlin/src/main/kotlin/com/baeldung/nonblockingcoroutines/repository/ProductRepositoryCoroutines.kt @@ -0,0 +1,40 @@ +package com.baeldung.nonblockingcoroutines.repository + + +import com.baeldung.nonblockingcoroutines.model.Product +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.reactive.awaitFirstOrNull +import kotlinx.coroutines.reactive.flow.asFlow +import org.springframework.data.r2dbc.function.DatabaseClient +import org.springframework.stereotype.Repository + +@Repository +class ProductRepositoryCoroutines(private val client: DatabaseClient) { + + suspend fun getProductById(id: Int): Product? = + client.execute().sql("SELECT * FROM products WHERE id = $1") + .bind(0, id) + .`as`(Product::class.java) + .fetch() + .one() + .awaitFirstOrNull() + + suspend fun addNewProduct(name: String, price: Float) = + client.execute() + .sql("INSERT INTO products (name, price) VALUES($1, $2)") + .bind(0, name) + .bind(1, price) + .then() + .awaitFirstOrNull() + + @FlowPreview + fun getAllProducts(): Flow = + client.select() + .from("products") + .`as`(Product::class.java) + .fetch() + .all() + .log() + .asFlow() +} \ No newline at end of file diff --git a/spring-boot-kotlin/src/main/resources/application.properties b/spring-boot-kotlin/src/main/resources/application.properties new file mode 100644 index 0000000000..0f84ff2d75 --- /dev/null +++ b/spring-boot-kotlin/src/main/resources/application.properties @@ -0,0 +1,8 @@ +logging.level.org.springframework.data.r2dbc=DEBUG +logging.level.org.springframework.web.reactive.function.client.ExchangeFunctions=TRACE +spring.http.log-request-details=true +spring.h2.console.enabled=true +spring.datasource.username=sa +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.password= +spring.datasource.dbname=testdb \ No newline at end of file diff --git a/spring-boot-kotlin/src/main/resources/logback.xml b/spring-boot-kotlin/src/main/resources/logback.xml new file mode 100644 index 0000000000..7d900d8ea8 --- /dev/null +++ b/spring-boot-kotlin/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/spring-boot-kotlin/src/test/kotlin/com/baeldung/nonblockingcoroutines/ProductHandlerTest.kt b/spring-boot-kotlin/src/test/kotlin/com/baeldung/nonblockingcoroutines/ProductHandlerTest.kt new file mode 100644 index 0000000000..53b1d50f21 --- /dev/null +++ b/spring-boot-kotlin/src/test/kotlin/com/baeldung/nonblockingcoroutines/ProductHandlerTest.kt @@ -0,0 +1,58 @@ +package com.baeldung.nonblockingcoroutines + +import com.baeldung.nonblockingcoroutines.config.RouterConfiguration +import com.baeldung.nonblockingcoroutines.handlers.ProductsHandler +import com.baeldung.nonblockingcoroutines.model.Product +import com.baeldung.nonblockingcoroutines.repository.ProductRepositoryCoroutines +import kotlinx.coroutines.FlowPreview +import kotlinx.coroutines.reactive.flow.asFlow +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.BDDMockito.given +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration +import org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration +import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest +import org.springframework.boot.test.mock.mockito.MockBean +import org.springframework.test.context.junit4.SpringRunner +import org.springframework.test.web.reactive.server.WebTestClient +import org.springframework.test.web.reactive.server.expectBodyList +import org.springframework.web.reactive.function.client.WebClient +import reactor.core.publisher.Flux +import org.springframework.test.context.ContextConfiguration + +@WebFluxTest( + excludeAutoConfiguration = [ReactiveUserDetailsServiceAutoConfiguration::class, ReactiveSecurityAutoConfiguration::class] +) +@RunWith(SpringRunner::class) +@ContextConfiguration(classes = [ProductsHandler::class, RouterConfiguration::class]) +class ProductHandlerTest { + + @Autowired + private lateinit var client: WebTestClient + + @MockBean + private lateinit var webClient: WebClient + + @MockBean + private lateinit var productsRepository: ProductRepositoryCoroutines + + + @FlowPreview + @Test + public fun `get all products`() { + val productsFlow = Flux.just( + Product(1, "product1", 1000.0F), + Product(2, "product2", 2000.0F), + Product(3, "product3", 3000.0F) + ).asFlow() + given(productsRepository.getAllProducts()).willReturn(productsFlow) + client.get() + .uri("/") + .exchange() + .expectStatus() + .isOk + .expectBodyList() + } + +}