├── .gitignore ├── README.md ├── course-catalog-service ├── build.gradle.kts ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src │ ├── main │ ├── kotlin │ │ └── com │ │ │ └── kotlinspring │ │ │ ├── CourseCatalogServiceApplication.kt │ │ │ ├── controller │ │ │ ├── CourseController.kt │ │ │ ├── GreetingController.kt │ │ │ └── InstructorController.kt │ │ │ ├── dto │ │ │ ├── CourseDTO.kt │ │ │ └── InstructorDTO.kt │ │ │ ├── entity │ │ │ ├── Course.kt │ │ │ └── Instructor.kt │ │ │ ├── exception │ │ │ ├── CourseNotFoundException.kt │ │ │ └── InstructorNotValidException.kt │ │ │ ├── exceptionhandler │ │ │ └── GlobalErrorHandler.kt │ │ │ ├── repository │ │ │ ├── CourseRepository.kt │ │ │ └── InstructorRepository.kt │ │ │ └── service │ │ │ ├── CourseService.kt │ │ │ ├── GreetingService.kt │ │ │ └── InstructorService.kt │ └── resources │ │ ├── application-prod.yml │ │ ├── application.yml │ │ └── curl-commands.txt │ └── test │ ├── intg │ └── com │ │ └── kotlinspring │ │ ├── controller │ │ ├── CourseControllerIntgTest.kt │ │ ├── GreetingControllerIntgTest.kt │ │ └── InstructorControllerIntgTest.kt │ │ └── repository │ │ └── CourseRepositoryIntgTest.kt │ └── unit │ └── com │ └── kotlinspring │ ├── controller │ ├── CourseControllerUnitTest.kt │ ├── GreetingControllerUnitTest.kt │ └── InstructorControllerUnitTest.kt │ └── util │ └── TestUtil.kt └── kotlin-playground ├── build.gradle.kts ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── src └── main └── kotlin └── com └── kotlinplayground ├── HelloKotlin.kt ├── HelloKotlinFile.kt ├── basics ├── Conditions.kt ├── LabelsAndReturn.kt ├── LoopsAndRanges.kt └── Variables.kt ├── cast └── ExploreCast.kt ├── classes ├── Authenticate.kt ├── Course.kt ├── Inheritance.kt ├── Instructor.kt ├── Item.kt └── Person.kt ├── collections ├── CollectionOperations.kt ├── CollectionOperationsUsingSequences.kt ├── ExploreArrays.kt ├── ExploreCollections.kt └── ExploreLambdas.kt ├── dataset └── DataHelper.kt ├── exceptions └── ExploreExceptions.kt ├── functions ├── Functions.kt └── Toplevel.kt ├── interfaces └── Interfaces.kt ├── nulls └── ExploreNulls.kt └── scopefunctions └── ExploreScopeFunctions.kt /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | /live-coding 26 | .DS_Store 27 | /code-zips 28 | /ssl 29 | .idea/ 30 | build/ 31 | .gradle/ 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # kotlin-spring 2 | This project holds the course code for kotlin and spring 3 | 4 | ## H2 Database 5 | 6 | - Access the h2 database in the following link - http://localhost:8080/h2-console 7 | -------------------------------------------------------------------------------- /course-catalog-service/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet 3 | 4 | plugins { 5 | id("org.springframework.boot") version "2.6.3" 6 | id("io.spring.dependency-management") version "1.0.11.RELEASE" 7 | kotlin("jvm") version "1.6.0" 8 | kotlin("plugin.spring") version "1.6.0" 9 | //id("org.jetbrains.kotlin.plugin.spring") version "1.6.0" 10 | kotlin("plugin.jpa") version "1.6.0" 11 | } 12 | 13 | group = "com.koltinspring" 14 | version = "0.0.1-SNAPSHOT" 15 | java.sourceCompatibility = JavaVersion.VERSION_11 16 | 17 | repositories { 18 | mavenCentral() 19 | } 20 | 21 | dependencies { 22 | 23 | //web 24 | implementation("org.springframework.boot:spring-boot-starter-web") 25 | 26 | //web 27 | implementation("org.springframework.boot:spring-boot-starter-validation") 28 | 29 | //kotlin 30 | implementation("com.fasterxml.jackson.module:jackson-module-kotlin") 31 | implementation("org.jetbrains.kotlin:kotlin-reflect") 32 | implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8") 33 | 34 | //validator 35 | implementation("org.springframework.boot:spring-boot-starter-validation") 36 | 37 | //logging 38 | implementation("io.github.microutils:kotlin-logging-jvm:2.0.11") 39 | 40 | 41 | //db 42 | implementation("org.springframework.boot:spring-boot-starter-data-jpa") 43 | runtimeOnly("com.h2database:h2") 44 | // runtimeOnly("org.postgresql:postgresql") 45 | 46 | testImplementation("org.springframework.boot:spring-boot-starter-test") 47 | testImplementation("org.springframework.boot:spring-boot-starter-webflux") 48 | testImplementation("io.mockk:mockk:1.10.4") 49 | testImplementation("com.ninja-squad:springmockk:3.0.1") 50 | 51 | 52 | } 53 | 54 | tasks.withType { 55 | kotlinOptions { 56 | freeCompilerArgs = listOf("-Xjsr305=strict") 57 | jvmTarget = "11" 58 | } 59 | } 60 | 61 | tasks.withType { 62 | useJUnitPlatform() 63 | } 64 | 65 | 66 | sourceSets { 67 | test { 68 | java { 69 | setSrcDirs(listOf("src/test/intg", "src/test/unit")) 70 | } 71 | } 72 | 73 | /*test { 74 | withConvention(KotlinSourceSet::class) { 75 | kotlin.srcDir(listOf("src/test/intg", "src/test/unit")) 76 | } 77 | }*/ 78 | 79 | } 80 | -------------------------------------------------------------------------------- /course-catalog-service/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dilipsundarraj1/kotlin-springboot/d773a4c728de6cc1817af68e26b77dd65301da02/course-catalog-service/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /course-catalog-service/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /course-catalog-service/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MSYS* | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /course-catalog-service/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/CourseCatalogServiceApplication.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring 2 | 3 | import org.springframework.boot.autoconfigure.SpringBootApplication 4 | import org.springframework.boot.runApplication 5 | 6 | @SpringBootApplication 7 | class CourseCatalogServiceApplication 8 | 9 | fun main(args: Array) { 10 | runApplication(*args) 11 | } 12 | 13 | -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/controller/CourseController.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.controller 2 | 3 | import com.kotlinspring.dto.CourseDTO 4 | import com.kotlinspring.service.CourseService 5 | import org.springframework.http.HttpStatus 6 | import org.springframework.validation.annotation.Validated 7 | import org.springframework.web.bind.annotation.* 8 | import javax.validation.Valid 9 | 10 | 11 | @RestController 12 | @RequestMapping("/v1/courses") 13 | @Validated 14 | class CourseController(val courseService :CourseService) { 15 | 16 | @PostMapping 17 | @ResponseStatus(HttpStatus.CREATED) 18 | fun addCourse(@RequestBody @Valid courseDTO: CourseDTO): CourseDTO { 19 | return courseService.addCourse(courseDTO) 20 | } 21 | 22 | @GetMapping 23 | @ResponseStatus(HttpStatus.OK) 24 | fun retrieveAllCourses(@RequestParam("course_name") courseName : String?): List 25 | = courseService.retrieveAllCourses(courseName) 26 | 27 | 28 | @PutMapping("/{course_id}") 29 | @ResponseStatus(HttpStatus.OK) 30 | fun updateCourse(@RequestBody courseDTO: CourseDTO, 31 | @PathVariable("course_id") courseId : Int): CourseDTO = courseService.updateCourse(courseId, courseDTO) 32 | 33 | @DeleteMapping("/{course_id}") 34 | @ResponseStatus(HttpStatus.NO_CONTENT) 35 | fun deleteCourse(@PathVariable("course_id") courseId : Int){ 36 | courseService.deleteCourse(courseId) 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/controller/GreetingController.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.controller 2 | 3 | import com.kotlinspring.service.GreetingService 4 | import mu.KLogging 5 | import org.springframework.web.bind.annotation.GetMapping 6 | import org.springframework.web.bind.annotation.PathVariable 7 | import org.springframework.web.bind.annotation.RequestMapping 8 | import org.springframework.web.bind.annotation.RestController 9 | 10 | @RestController 11 | @RequestMapping("/v1/greetings") 12 | class GreetingController(val greetingService: GreetingService) { 13 | 14 | companion object : KLogging() 15 | @GetMapping("/{name}") 16 | fun retrieveGreeting(@PathVariable("name") name : String): String { 17 | logger.info("Name is : $name") 18 | return greetingService.retrieveGreeting(name) 19 | } 20 | /*: String { 21 | return "Hello $name" 22 | }*/ 23 | } -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/controller/InstructorController.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.controller 2 | 3 | import com.kotlinspring.dto.InstructorDTO 4 | import com.kotlinspring.entity.Instructor 5 | import com.kotlinspring.repository.InstructorRepository 6 | import com.kotlinspring.service.InstructorService 7 | import org.springframework.http.HttpStatus 8 | import org.springframework.validation.annotation.Validated 9 | import org.springframework.web.bind.annotation.* 10 | import javax.validation.Valid 11 | 12 | @RestController 13 | @RequestMapping("/v1/instructors") 14 | @Validated 15 | class InstructorController(val instructorService: InstructorService) { 16 | 17 | @PostMapping 18 | @ResponseStatus(HttpStatus.CREATED) 19 | fun createInstructor( @Valid @RequestBody instructorDTO: InstructorDTO): InstructorDTO 20 | = instructorService.addNewInstructor(instructorDTO) 21 | 22 | } -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/dto/CourseDTO.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.dto 2 | 3 | import javax.validation.constraints.NotBlank 4 | import javax.validation.constraints.NotNull 5 | 6 | data class CourseDTO( 7 | val id: Int?, 8 | @get:NotBlank(message = "courseDTO.name must not be blank") 9 | val name: String, 10 | @get:NotBlank(message = "courseDTO.category must not be blank") 11 | val category: String, 12 | @get:NotNull(message = "courseDTO.instructorId must not be null") 13 | val instructorId: Int? = null 14 | 15 | ) -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/dto/InstructorDTO.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.dto 2 | 3 | import javax.validation.constraints.NotBlank 4 | 5 | data class InstructorDTO( 6 | val id: Int?, 7 | @get:NotBlank(message = "instructorDTO.name must not be blank") 8 | val name: String 9 | ) -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/entity/Course.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.entity 2 | 3 | import javax.persistence.* 4 | 5 | 6 | @Entity 7 | @Table(name = "COURSES") 8 | data class Course( 9 | @Id 10 | @GeneratedValue(strategy = GenerationType.AUTO) 11 | var id: Int?, 12 | /* val name: String, 13 | val category: String*/ 14 | var name: String, 15 | var category: String, 16 | @ManyToOne( 17 | fetch = FetchType.LAZY 18 | ) 19 | @JoinColumn(name = "INSTRUCTOR_ID", nullable = false) 20 | val instructor: Instructor? = null 21 | ){ 22 | 23 | override fun toString(): String { 24 | return "Course(id=$id, name='$name', category='$category', instructor=${instructor!!.id})" 25 | } 26 | } -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/entity/Instructor.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.entity 2 | 3 | import javax.persistence.* 4 | 5 | @Entity 6 | @Table(name="INSTRUCTORS") 7 | data class Instructor( 8 | @Id 9 | @GeneratedValue(strategy= GenerationType.AUTO) 10 | var id: Int?, 11 | var name: String, 12 | @OneToMany( 13 | mappedBy = "instructor", 14 | cascade = [CascadeType.ALL], 15 | orphanRemoval = true 16 | ) 17 | var courses : List = mutableListOf() 18 | ) -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/exception/CourseNotFoundException.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.exception 2 | 3 | class CourseNotFoundException(message: String) : RuntimeException(message) 4 | -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/exception/InstructorNotValidException.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.exception 2 | 3 | class InstructorNotValidException(message: String) : RuntimeException(message) { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/exceptionhandler/GlobalErrorHandler.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.exceptionhandler 2 | 3 | import com.kotlinspring.exception.InstructorNotValidException 4 | import mu.KLogging 5 | import org.springframework.http.HttpHeaders 6 | import org.springframework.http.HttpStatus 7 | import org.springframework.http.ResponseEntity 8 | import org.springframework.lang.Nullable 9 | import org.springframework.stereotype.Component 10 | import org.springframework.web.bind.MethodArgumentNotValidException 11 | import org.springframework.web.bind.annotation.ControllerAdvice 12 | import org.springframework.web.bind.annotation.ExceptionHandler 13 | import org.springframework.web.context.request.WebRequest 14 | import org.springframework.web.servlet.ModelAndView 15 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler 16 | import java.time.LocalDateTime 17 | import javax.servlet.http.HttpServletRequest 18 | import javax.servlet.http.HttpServletResponse 19 | 20 | @Component 21 | @ControllerAdvice 22 | class GlobalErrorHandler : ResponseEntityExceptionHandler() { 23 | 24 | companion object : KLogging() 25 | 26 | override fun handleMethodArgumentNotValid( 27 | ex: MethodArgumentNotValidException, 28 | headers: HttpHeaders, 29 | status: HttpStatus, 30 | request: WebRequest 31 | ): ResponseEntity { 32 | logger.error("MethodArgumentNotValidException observed : ${ex.message}", ex) 33 | val errors = ex.bindingResult.allErrors 34 | .map { error -> error.defaultMessage!! } 35 | .sorted() 36 | 37 | return ResponseEntity.status(HttpStatus.BAD_REQUEST) 38 | .body( 39 | errors.joinToString(", ") { it } 40 | ) 41 | } 42 | 43 | @ExceptionHandler(InstructorNotValidException::class) 44 | fun handleInputRequestError(ex: InstructorNotValidException, request: WebRequest): ResponseEntity { 45 | logger.info("Exception occurred: ${ex.message} on request: $request") 46 | return ResponseEntity.status(HttpStatus.BAD_REQUEST) 47 | .body( 48 | ex.message 49 | ) 50 | } 51 | 52 | @ExceptionHandler(java.lang.Exception::class) 53 | fun handleAllExceptions(ex: java.lang.Exception, request: WebRequest): ResponseEntity { 54 | logger.info("Exception occurred: ${ex.message} on request: $request", ex) 55 | return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) 56 | .body( 57 | ex.message 58 | ) 59 | } 60 | } -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/repository/CourseRepository.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.repository 2 | 3 | import com.kotlinspring.entity.Course 4 | import com.kotlinspring.entity.Instructor 5 | import org.springframework.data.jpa.repository.Query 6 | import org.springframework.data.repository.CrudRepository 7 | 8 | interface CourseRepository : CrudRepository { 9 | 10 | fun findByNameContaining(courseName : String) : List 11 | 12 | @Query(value = "SELECT * FROM COURSES WHERE name like %?1%", nativeQuery = true) 13 | fun findCoursesByName(courseName : String) : List 14 | 15 | } -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/repository/InstructorRepository.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.repository 2 | 3 | import com.kotlinspring.entity.Instructor 4 | import org.springframework.data.repository.CrudRepository 5 | 6 | interface InstructorRepository : CrudRepository { 7 | 8 | fun findInstructorByName(name : String) : Instructor 9 | } -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/service/CourseService.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.service 2 | 3 | import com.kotlinspring.dto.CourseDTO 4 | import com.kotlinspring.entity.Course 5 | import com.kotlinspring.exception.CourseNotFoundException 6 | import com.kotlinspring.exception.InstructorNotValidException 7 | import com.kotlinspring.repository.CourseRepository 8 | import mu.KLogging 9 | import org.springframework.stereotype.Service 10 | 11 | @Service 12 | class CourseService(val courseRepository: CourseRepository, 13 | val instructorService: InstructorService) { 14 | 15 | companion object : KLogging() 16 | 17 | fun addCourse(courseDTO: CourseDTO): CourseDTO { 18 | 19 | val instructor = instructorService.findInstructorById(courseDTO.instructorId!!) 20 | if(!instructor.isPresent){ 21 | throw InstructorNotValidException("Instructor Id is not Valid!") 22 | } 23 | 24 | val courseEntity = courseDTO.let { 25 | Course(null, it.name, it.category, instructor.get()) 26 | } 27 | 28 | courseRepository.save(courseEntity) 29 | 30 | logger.info("Saved Course is : $courseEntity") 31 | 32 | return courseEntity.let { 33 | //CourseDTO(it.id!!, it.name, it.category) 34 | CourseDTO(it.id, it.name, it.category,it.instructor?.id) 35 | } 36 | } 37 | 38 | fun retrieveAllCourses(courseName: String?): List { 39 | 40 | val courses = courseName?.let { 41 | courseRepository.findCoursesByName(courseName) 42 | } ?: courseRepository.findAll() 43 | 44 | return courses.map { 45 | //CourseDTO(it.id, it.name, it.category) 46 | CourseDTO(it.id, it.name, it.category,it.instructor?.id) 47 | } 48 | 49 | } 50 | 51 | 52 | fun updateCourse(courseId: Int, courseDTO: CourseDTO): CourseDTO { 53 | 54 | val existingCourse = courseRepository.findById(courseId) 55 | 56 | return if (existingCourse.isPresent) { 57 | existingCourse.get() 58 | .let { 59 | it.category = courseDTO.category 60 | it.name = courseDTO.name 61 | courseRepository.save(it) 62 | // CourseDTO(it.id, it.name, it.category) 63 | CourseDTO(it.id, it.name, it.category, it.instructor?.id) 64 | } 65 | } else { 66 | throw CourseNotFoundException("No Course Found for the passed in Id $courseId") 67 | } 68 | 69 | } 70 | 71 | fun deleteCourse(courseId: Int) { 72 | val existingCourse = courseRepository.findById(courseId) 73 | if (existingCourse.isPresent) { 74 | existingCourse.get() 75 | .let { 76 | courseRepository.deleteById(courseId) 77 | } 78 | } else { 79 | throw CourseNotFoundException("No Course Found for the passed in Id $courseId") 80 | } 81 | 82 | 83 | } 84 | 85 | 86 | } -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/service/GreetingService.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.service 2 | 3 | import org.springframework.beans.factory.annotation.Value 4 | import org.springframework.stereotype.Service 5 | 6 | @Service 7 | class GreetingService { 8 | 9 | @Value("\${message}") 10 | lateinit var message: String 11 | 12 | fun retrieveGreeting(name: String) = "$name, $message" 13 | } -------------------------------------------------------------------------------- /course-catalog-service/src/main/kotlin/com/kotlinspring/service/InstructorService.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.service 2 | 3 | import com.kotlinspring.dto.InstructorDTO 4 | import com.kotlinspring.entity.Instructor 5 | import com.kotlinspring.repository.InstructorRepository 6 | import org.springframework.stereotype.Service 7 | import java.util.* 8 | 9 | @Service 10 | class InstructorService(val instructorRepository: InstructorRepository) { 11 | 12 | fun addNewInstructor(instructorDTO: InstructorDTO): InstructorDTO { 13 | 14 | val instructorEntity = instructorDTO.let { 15 | Instructor(it.id, it.name) 16 | } 17 | 18 | instructorRepository.save(instructorEntity) 19 | 20 | return instructorEntity.let { 21 | InstructorDTO(it.id, it.name) 22 | } 23 | } 24 | 25 | fun findInstructorById(instructorId: Int): Optional { 26 | 27 | return instructorRepository.findById(instructorId) 28 | } 29 | } -------------------------------------------------------------------------------- /course-catalog-service/src/main/resources/application-prod.yml: -------------------------------------------------------------------------------- 1 | message: Hello from prod profile 2 | -------------------------------------------------------------------------------- /course-catalog-service/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: course-catalog-service 4 | datasource: 5 | url: jdbc:h2:mem:testdb 6 | driver-class-name: org.h2.Driver 7 | username: sa 8 | password: password 9 | jpa: 10 | database: h2 11 | database-platform: org.hibernate.dialect.H2Dialect 12 | generate-ddl: true 13 | show-sql: true 14 | h2: 15 | console: 16 | enabled: true 17 | message: Hello from default profile 18 | 19 | --- 20 | #spring: 21 | # config: 22 | # activate: 23 | # on-profile: prod 24 | #message: Hello from prod profile -------------------------------------------------------------------------------- /course-catalog-service/src/main/resources/curl-commands.txt: -------------------------------------------------------------------------------- 1 | Greeting Controller: 2 | ==================== 3 | curl -i http://localhost:8080/v1/greetings/dilip 4 | 5 | =================== 6 | Course Controller: | 7 | =================== 8 | 9 | CREATE COURSE: 10 | ============== 11 | curl -i \ 12 | -d '{"id":null, "name":"Build Restful APIs using Kotlin and SpringBoot", "category": "Development"}' \ 13 | -H "Content-Type: application/json" \ 14 | -X POST http://localhost:8080/v1/courses 15 | 16 | 17 | curl -i \ 18 | -d '{"id":null, "name":"Build Reactive Microservices using Spring WebFlux/SpringBoot ", "category": "Development"}' \ 19 | -H "Content-Type: application/json" \ 20 | -X POST http://localhost:8080/v1/courses 21 | 22 | GET COURSES: 23 | ============== 24 | curl -i http://localhost:8080/v1/courses 25 | 26 | UPDATE COURSE: 27 | ============== 28 | curl -i \ 29 | -d '{"id":null, "name":"Build Restful APIs using Kotlin & SpringBoot2", "category": "Development"}' \ 30 | -H "Content-Type: application/json" \ 31 | -X PUT http://localhost:8080/v1/courses/1 32 | 33 | 34 | DELETE COURSE: 35 | ============== 36 | curl -i -X DELETE http://localhost:8080/v1/courses/1 37 | 38 | 39 | ======================= 40 | Instructor Controller: | 41 | ======================= 42 | CREATE INSTRUCTOR: 43 | ================== 44 | curl -i \ 45 | -d '{"id":null, "name":"Dilip Sundarraj"}' \ 46 | -H "Content-Type: application/json" \ 47 | -X POST http://localhost:8080/v1/instructors 48 | 49 | 50 | CREATE COURSE WITH INSTRUCTOR: 51 | ================== 52 | curl -i \ 53 | -d '{"id":null, "name":"Build Restful APIs using Kotlin and SpringBoot", "category": "Development", "instructorId": 1}' \ 54 | -H "Content-Type: application/json" \ 55 | -X POST http://localhost:8080/v1/courses 56 | -------------------------------------------------------------------------------- /course-catalog-service/src/test/intg/com/kotlinspring/controller/CourseControllerIntgTest.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.controller 2 | 3 | import com.kotlinspring.dto.CourseDTO 4 | import com.kotlinspring.entity.Course 5 | import com.kotlinspring.repository.CourseRepository 6 | import com.kotlinspring.repository.InstructorRepository 7 | import com.kotlinspring.util.courseEntityList 8 | import com.kotlinspring.util.instructorEntity 9 | import org.junit.jupiter.api.Test 10 | 11 | import org.junit.jupiter.api.Assertions.* 12 | import org.junit.jupiter.api.BeforeEach 13 | import org.springframework.beans.factory.annotation.Autowired 14 | import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient 15 | import org.springframework.boot.test.context.SpringBootTest 16 | import org.springframework.test.context.ActiveProfiles 17 | import org.springframework.test.web.reactive.server.WebTestClient 18 | import org.springframework.web.util.UriComponentsBuilder 19 | 20 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 21 | @ActiveProfiles("test") 22 | @AutoConfigureWebTestClient 23 | internal class CourseControllerIntgTest { 24 | 25 | @Autowired 26 | lateinit var webTestClient: WebTestClient 27 | 28 | @Autowired 29 | lateinit var courseRepository: CourseRepository 30 | 31 | @Autowired 32 | lateinit var instructorRepository: InstructorRepository 33 | 34 | @BeforeEach 35 | fun setUp(){ 36 | courseRepository.deleteAll() 37 | instructorRepository.deleteAll() 38 | 39 | val instructor = instructorEntity() 40 | instructorRepository.save(instructor) 41 | 42 | val courses = courseEntityList(instructor) 43 | courseRepository.saveAll(courses) 44 | } 45 | 46 | @Test 47 | fun addInstructor() { 48 | 49 | val instructor = instructorRepository.findInstructorByName("Dilip Sundarraj") 50 | 51 | //given 52 | val courseDTO = CourseDTO(null, 53 | "Build RestFul APis using Spring Boot and Kotlin", "Dilip Sundarraj", 54 | instructor.id ) 55 | 56 | //when 57 | val savedCourseDTO = webTestClient 58 | .post() 59 | .uri("/v1/courses") 60 | .bodyValue(courseDTO) 61 | .exchange() 62 | .expectStatus().isCreated 63 | .expectBody(CourseDTO::class.java) 64 | .returnResult() 65 | .responseBody 66 | 67 | //then 68 | assertTrue { 69 | savedCourseDTO!!.id!=null 70 | } 71 | } 72 | 73 | 74 | @Test 75 | fun addCourse_InvlaidOInstructorId() { 76 | 77 | //given 78 | val courseDTO = CourseDTO(null, 79 | "Build RestFul APis using Spring Boot and Kotlin", "Dilip Sundarraj", 80 | 999 ) 81 | 82 | //when 83 | val response = webTestClient 84 | .post() 85 | .uri("/v1/courses") 86 | .bodyValue(courseDTO) 87 | .exchange() 88 | .expectStatus().isBadRequest 89 | .expectBody(String::class.java) 90 | .returnResult() 91 | .responseBody 92 | 93 | //then 94 | assertEquals("Instructor Id is not Valid!", response) 95 | } 96 | 97 | @Test 98 | fun retrieveAllCourses() { 99 | 100 | 101 | val courseDTOs = webTestClient 102 | .get() 103 | .uri("/v1/courses") 104 | .exchange() 105 | .expectStatus().isOk 106 | .expectBodyList(CourseDTO::class.java) 107 | .returnResult() 108 | .responseBody 109 | 110 | println("courseDTOs : $courseDTOs") 111 | 112 | assertEquals(3, courseDTOs!!.size) 113 | 114 | } 115 | 116 | @Test 117 | fun retrieveAllCourses_ByName() { 118 | 119 | val uri = UriComponentsBuilder.fromUriString("/v1/courses") 120 | .queryParam("course_name", "SpringBoot") 121 | .toUriString() 122 | 123 | val courseDTOs = webTestClient 124 | .get() 125 | .uri(uri) 126 | .exchange() 127 | .expectStatus().isOk 128 | .expectBodyList(CourseDTO::class.java) 129 | .returnResult() 130 | .responseBody 131 | 132 | println("courseDTOs : $courseDTOs") 133 | 134 | assertEquals(2, courseDTOs!!.size) 135 | 136 | } 137 | 138 | @Test 139 | fun updateCourse() { 140 | 141 | val instructor = instructorRepository.findInstructorByName("Dilip Sundarraj") 142 | val courseEntity = Course(null, 143 | "Apache Kafka for Developers using Spring Boot", "Development", 144 | instructor) 145 | courseRepository.save(courseEntity) 146 | val updatedCourseEntity = Course(null, 147 | "Apache Kafka for Developers using Spring Boot1", "Development" ) 148 | 149 | val updatedCourseDTO = webTestClient 150 | .put() 151 | .uri("/v1/courses/{courseId}", courseEntity.id) 152 | .bodyValue(updatedCourseEntity) 153 | .exchange() 154 | .expectStatus().isOk 155 | .expectBody(CourseDTO::class.java) 156 | .returnResult() 157 | .responseBody 158 | 159 | assertEquals("Apache Kafka for Developers using Spring Boot1", updatedCourseDTO?.name) 160 | 161 | } 162 | 163 | @Test 164 | fun deleteCourse() { 165 | 166 | val instructor = instructorRepository.findInstructorByName("Dilip Sundarraj") 167 | val courseEntity = Course(null, 168 | "Apache Kafka for Developers using Spring Boot", "Development" , 169 | instructor) 170 | 171 | courseRepository.save(courseEntity) 172 | webTestClient 173 | .delete() 174 | .uri("/v1/courses/{courseId}", courseEntity.id) 175 | .exchange() 176 | .expectStatus().isNoContent 177 | 178 | } 179 | } -------------------------------------------------------------------------------- /course-catalog-service/src/test/intg/com/kotlinspring/controller/GreetingControllerIntgTest.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.controller 2 | 3 | import org.junit.jupiter.api.Assertions 4 | import org.junit.jupiter.api.Test 5 | import org.springframework.beans.factory.annotation.Autowired 6 | import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient 7 | import org.springframework.boot.test.context.SpringBootTest 8 | import org.springframework.test.context.ActiveProfiles 9 | import org.springframework.test.web.reactive.server.WebTestClient 10 | 11 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 12 | @ActiveProfiles("test") 13 | @AutoConfigureWebTestClient 14 | class GreetingControllerIntgTest { 15 | 16 | @Autowired 17 | lateinit var webTestClient: WebTestClient 18 | 19 | @Test 20 | fun retrieveGreeting() { 21 | 22 | val name = "dilip" 23 | 24 | val result =webTestClient.get() 25 | .uri("/v1/greetings/{name}", name) 26 | .exchange() 27 | .expectStatus().is2xxSuccessful 28 | .expectBody(String::class.java) 29 | .returnResult() 30 | 31 | Assertions.assertEquals("$name, Hello from default profile", result.responseBody) 32 | 33 | } 34 | 35 | 36 | } -------------------------------------------------------------------------------- /course-catalog-service/src/test/intg/com/kotlinspring/controller/InstructorControllerIntgTest.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.controller 2 | 3 | import com.kotlinspring.dto.InstructorDTO 4 | import org.junit.jupiter.api.Assertions 5 | import org.junit.jupiter.api.Test 6 | import org.springframework.beans.factory.annotation.Autowired 7 | import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient 8 | import org.springframework.boot.test.context.SpringBootTest 9 | import org.springframework.test.context.ActiveProfiles 10 | import org.springframework.test.web.reactive.server.WebTestClient 11 | 12 | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) 13 | @ActiveProfiles("test") 14 | @AutoConfigureWebTestClient 15 | class InstructorControllerIntgTest { 16 | 17 | @Autowired 18 | lateinit var webTestClient: WebTestClient 19 | 20 | @Test 21 | fun addInstructor() { 22 | 23 | val instructorDTO = InstructorDTO(null, "Dilip Sundarraj") 24 | 25 | 26 | //when 27 | val savedInstructorDTO = webTestClient 28 | .post() 29 | .uri("/v1/instructors") 30 | .bodyValue(instructorDTO) 31 | .exchange() 32 | .expectStatus().isCreated 33 | .expectBody(InstructorDTO::class.java) 34 | .returnResult() 35 | .responseBody 36 | 37 | //then 38 | Assertions.assertTrue { 39 | savedInstructorDTO!!.id != null 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /course-catalog-service/src/test/intg/com/kotlinspring/repository/CourseRepositoryIntgTest.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.repository 2 | 3 | import com.kotlinspring.util.courseEntityList 4 | import com.kotlinspring.util.instructorEntity 5 | import org.junit.jupiter.api.Assertions.assertEquals 6 | import org.junit.jupiter.api.BeforeEach 7 | import org.junit.jupiter.api.Test 8 | import org.junit.jupiter.params.ParameterizedTest 9 | import org.junit.jupiter.params.provider.Arguments 10 | import org.junit.jupiter.params.provider.MethodSource 11 | import org.springframework.beans.factory.annotation.Autowired 12 | import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest 13 | import org.springframework.test.context.ActiveProfiles 14 | import java.util.stream.Stream 15 | 16 | @DataJpaTest 17 | @ActiveProfiles("test") 18 | class CourseRepositoryIntgTest { 19 | 20 | @Autowired 21 | lateinit var courseRepository: CourseRepository 22 | 23 | 24 | @Autowired 25 | lateinit var instructorRepository: InstructorRepository 26 | 27 | 28 | 29 | @BeforeEach 30 | fun setUp(){ 31 | instructorRepository.deleteAll() 32 | courseRepository.deleteAll() 33 | 34 | val instructor = instructorEntity() 35 | instructorRepository.save(instructor) 36 | 37 | val courses = courseEntityList(instructor) 38 | courses.forEach { 39 | courseRepository.save(it) 40 | } 41 | 42 | } 43 | 44 | @Test 45 | fun findByNameContaining() { 46 | 47 | val courses = courseRepository.findByNameContaining("SpringBoot") 48 | 49 | println("courses : $courses") 50 | assertEquals(2, courses.size) 51 | 52 | } 53 | 54 | @Test 55 | fun findCoursesByName() { 56 | 57 | val courses = courseRepository.findCoursesByName("SpringBoot") 58 | 59 | println("courses : $courses") 60 | assertEquals(2, courses.size) 61 | 62 | } 63 | 64 | 65 | @ParameterizedTest 66 | @MethodSource("courseAndSize") 67 | fun findCoursesByName_approach2(name: String, expectedSize: Int) { 68 | 69 | val courses = courseRepository.findCoursesByName(name) 70 | 71 | println("courses : $courses") 72 | assertEquals(expectedSize, courses.size) 73 | 74 | } 75 | 76 | 77 | 78 | companion object { 79 | @JvmStatic 80 | fun courseAndSize(): Stream { 81 | return Stream.of(Arguments.arguments("SpringBoot", 2), 82 | Arguments.arguments("Wiremock", 1)) 83 | 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /course-catalog-service/src/test/unit/com/kotlinspring/controller/CourseControllerUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.controller 2 | 3 | import com.kotlinspring.dto.CourseDTO 4 | import com.kotlinspring.entity.Course 5 | import com.kotlinspring.service.CourseService 6 | import com.kotlinspring.util.courseDTO 7 | import com.ninjasquad.springmockk.MockkBean 8 | import io.mockk.every 9 | import io.mockk.just 10 | import io.mockk.runs 11 | import io.mockk.verify 12 | import org.junit.jupiter.api.Assertions 13 | import org.junit.jupiter.api.Assertions.assertEquals 14 | import org.junit.jupiter.api.Test 15 | import org.springframework.beans.factory.annotation.Autowired 16 | import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient 17 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest 18 | import org.springframework.http.MediaType 19 | import org.springframework.test.web.reactive.server.WebTestClient 20 | 21 | @WebMvcTest(CourseController::class) 22 | @AutoConfigureWebTestClient 23 | class CourseControllerUnitTest { 24 | 25 | @Autowired 26 | lateinit var webTestClient: WebTestClient 27 | 28 | @MockkBean 29 | lateinit var courseServiceMock: CourseService 30 | 31 | 32 | @Test 33 | fun addCourse() { 34 | //given 35 | val courseDTO = courseDTO() 36 | 37 | every { courseServiceMock.addCourse(any()) } returns courseDTO(id=1) 38 | 39 | //when 40 | val savedCourseDTO = webTestClient 41 | .post() 42 | .uri("/v1/courses") 43 | .contentType(MediaType.APPLICATION_JSON) 44 | .bodyValue(courseDTO) 45 | .exchange() 46 | .expectStatus().isCreated 47 | .expectBody(CourseDTO::class.java) 48 | .returnResult() 49 | .responseBody 50 | 51 | //then 52 | Assertions.assertTrue { 53 | savedCourseDTO!!.id != null 54 | } 55 | } 56 | 57 | @Test 58 | fun addCourse_validation() { 59 | //given 60 | val courseDTO = courseDTO(name = "", category = "") 61 | 62 | every { courseServiceMock.addCourse(any()) } returns courseDTO(id=1) 63 | 64 | //when 65 | val response = webTestClient 66 | .post() 67 | .uri("/v1/courses") 68 | .contentType(MediaType.APPLICATION_JSON) 69 | .bodyValue(courseDTO) 70 | .exchange() 71 | .expectStatus().isBadRequest 72 | .expectBody(String::class.java) 73 | .returnResult() 74 | .responseBody 75 | 76 | println("response : $response") 77 | assertEquals("courseDTO.category must not be blank, courseDTO.name must not be blank" 78 | , response) 79 | } 80 | 81 | @Test 82 | fun addCourse_runtime_exception() { 83 | //given 84 | val courseDTO = courseDTO() 85 | val errorMessage = "Unexpected Error Occurred!" 86 | every { courseServiceMock.addCourse(any()) } throws RuntimeException(errorMessage) 87 | 88 | //when 89 | val response = webTestClient 90 | .post() 91 | .uri("/v1/courses") 92 | .contentType(MediaType.APPLICATION_JSON) 93 | .bodyValue(courseDTO) 94 | .exchange() 95 | .expectStatus().is5xxServerError 96 | .expectBody(String::class.java) 97 | .returnResult() 98 | .responseBody 99 | 100 | assertEquals(errorMessage 101 | , response) 102 | } 103 | 104 | 105 | 106 | @Test 107 | fun retrieveAllCourses() { 108 | 109 | every { courseServiceMock.retrieveAllCourses(any()) }.returnsMany( 110 | listOf( 111 | CourseDTO(1, 112 | "Build RestFul APis using Spring Boot and Kotlin", "Development" , 113 | 1), 114 | CourseDTO(2, 115 | "Build Reactive Microservices using Spring WebFlux/SpringBoot", "Development" , 116 | 1) 117 | ) 118 | ) 119 | 120 | 121 | val courseDTOs = webTestClient 122 | .get() 123 | .uri("/v1/courses") 124 | .exchange() 125 | .expectStatus().isOk 126 | .expectBodyList(CourseDTO::class.java) 127 | .returnResult() 128 | .responseBody 129 | 130 | println("courseDTOs : $courseDTOs") 131 | 132 | Assertions.assertEquals(2, courseDTOs!!.size) 133 | 134 | } 135 | 136 | @Test 137 | fun updateCourse() { 138 | 139 | val updatedCourseEntity = Course(null, 140 | "Apache Kafka for Developers using Spring Boot1", "Development" ) 141 | 142 | every { courseServiceMock.updateCourse(any(), any()) } returns CourseDTO(100, 143 | "Apache Kafka for Developers using Spring Boot1", "Development" , 144 | 1) 145 | 146 | 147 | val updatedCourseDTO = webTestClient 148 | .put() 149 | .uri("/v1/courses/{courseId}", 100) 150 | .bodyValue(updatedCourseEntity) 151 | .exchange() 152 | .expectStatus().isOk 153 | .expectBody(CourseDTO::class.java) 154 | .returnResult() 155 | .responseBody 156 | 157 | Assertions.assertEquals("Apache Kafka for Developers using Spring Boot1", updatedCourseDTO?.name) 158 | 159 | } 160 | 161 | @Test 162 | fun deleteCourse() { 163 | 164 | every { courseServiceMock.deleteCourse(any()) } just runs 165 | 166 | webTestClient 167 | .delete() 168 | .uri("/v1/courses/{courseId}", 100) 169 | .exchange() 170 | .expectStatus().isNoContent 171 | 172 | verify(exactly = 1) { courseServiceMock.deleteCourse(any()) } 173 | 174 | } 175 | 176 | } -------------------------------------------------------------------------------- /course-catalog-service/src/test/unit/com/kotlinspring/controller/GreetingControllerUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.controller 2 | 3 | import com.kotlinspring.service.GreetingService 4 | import com.ninjasquad.springmockk.MockkBean 5 | import io.mockk.every 6 | import org.junit.jupiter.api.Assertions.assertEquals 7 | import org.junit.jupiter.api.Test 8 | import org.mockito.Mockito 9 | import org.springframework.beans.factory.annotation.Autowired 10 | import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient 11 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest 12 | import org.springframework.boot.test.mock.mockito.MockBean 13 | import org.springframework.test.web.reactive.server.WebTestClient 14 | 15 | 16 | @WebMvcTest(controllers = [GreetingController::class]) 17 | @AutoConfigureWebTestClient 18 | class GreetingControllerUnitTest { 19 | 20 | @MockkBean 21 | lateinit var greetingServiceMock: GreetingService 22 | 23 | @Autowired 24 | lateinit var webTestClient: WebTestClient 25 | 26 | 27 | @Test 28 | fun retrieveGreeting() { 29 | 30 | val name = "dilip" 31 | 32 | every { greetingServiceMock.retrieveGreeting(any()) } returns "$name, Hello from default profile" 33 | 34 | val result =webTestClient.get() 35 | .uri("/v1/greetings/{name}", name) 36 | .exchange() 37 | .expectStatus().is2xxSuccessful 38 | .expectBody(String::class.java) 39 | .returnResult() 40 | 41 | assertEquals("$name, Hello from default profile", result.responseBody) 42 | 43 | } 44 | } -------------------------------------------------------------------------------- /course-catalog-service/src/test/unit/com/kotlinspring/controller/InstructorControllerUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.controller 2 | 3 | import com.kotlinspring.dto.InstructorDTO 4 | import com.kotlinspring.service.InstructorService 5 | import com.ninjasquad.springmockk.MockkBean 6 | import io.mockk.every 7 | import org.junit.jupiter.api.Assertions 8 | import org.junit.jupiter.api.Assertions.assertEquals 9 | import org.junit.jupiter.api.Test 10 | import org.springframework.beans.factory.annotation.Autowired 11 | import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient 12 | import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest 13 | import org.springframework.test.web.reactive.server.WebTestClient 14 | 15 | @WebMvcTest(InstructorController::class) 16 | @AutoConfigureWebTestClient 17 | class InstructorControllerUnitTest { 18 | 19 | @Autowired 20 | lateinit var webTestClient: WebTestClient 21 | 22 | @MockkBean 23 | lateinit var instructorServiceMock: InstructorService 24 | 25 | 26 | @Test 27 | fun addInstructor() { 28 | //given 29 | val instructorDTO = InstructorDTO(null, "Dilip Sundarraj") 30 | 31 | every { instructorServiceMock.addNewInstructor(any()) } returns InstructorDTO(1, "Dilip Sundarraj") 32 | 33 | val savedInstructorDTO = webTestClient 34 | .post() 35 | .uri("/v1/instructors") 36 | .bodyValue(instructorDTO) 37 | .exchange() 38 | .expectStatus().isCreated 39 | .expectBody(InstructorDTO::class.java) 40 | .returnResult() 41 | .responseBody 42 | 43 | //then 44 | Assertions.assertTrue { 45 | savedInstructorDTO!!.id != null 46 | } 47 | } 48 | 49 | @Test 50 | fun addInstructor_Validation() { 51 | //given 52 | val instructorDTO = InstructorDTO(null, "") 53 | 54 | every { instructorServiceMock.addNewInstructor(any()) } returns InstructorDTO(1, "Dilip Sundarraj") 55 | 56 | val response = webTestClient 57 | .post() 58 | .uri("/v1/instructors") 59 | .bodyValue(instructorDTO) 60 | .exchange() 61 | .expectStatus().isBadRequest 62 | .expectBody(String::class.java) 63 | .returnResult() 64 | .responseBody 65 | 66 | //then 67 | assertEquals("instructorDTO.name must not be blank",response) 68 | } 69 | } -------------------------------------------------------------------------------- /course-catalog-service/src/test/unit/com/kotlinspring/util/TestUtil.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinspring.util 2 | 3 | import com.kotlinspring.dto.CourseDTO 4 | import com.kotlinspring.entity.Course 5 | import com.kotlinspring.entity.Instructor 6 | 7 | /*fun courseDTO( 8 | id: Int? = null, 9 | name: String = "Build RestFul APis using Spring Boot and Kotlin", 10 | category: String = "Dilip Sundarraj", 11 | ) = CourseDTO( 12 | id, 13 | name, 14 | category 15 | )*/ 16 | 17 | 18 | fun courseEntityList() = listOf( 19 | Course(null, 20 | "Build RestFul APis using SpringBoot and Kotlin", "Development"), 21 | Course(null, 22 | "Build Reactive Microservices using Spring WebFlux/SpringBoot", "Development" 23 | , 24 | ), 25 | Course(null, 26 | "Wiremock for Java Developers", "Development" , 27 | ) 28 | ) 29 | 30 | fun courseDTO( 31 | id: Int? = null, 32 | name: String = "Build RestFul APis using Spring Boot and Kotlin", 33 | category: String = "Development", 34 | instructorId: Int? = 1 35 | ) = CourseDTO( 36 | id, 37 | name, 38 | category, 39 | instructorId 40 | ) 41 | 42 | fun courseEntityList(instructor: Instructor? = null) = listOf( 43 | Course(null, 44 | "Build RestFul APis using SpringBoot and Kotlin", "Development", 45 | instructor), 46 | Course(null, 47 | "Build Reactive Microservices using Spring WebFlux/SpringBoot", "Development" 48 | ,instructor 49 | ), 50 | Course(null, 51 | "Wiremock for Java Developers", "Development" , 52 | instructor) 53 | ) 54 | 55 | fun instructorEntity(name : String = "Dilip Sundarraj") 56 | = Instructor(null, name) 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /kotlin-playground/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") version "1.5.10" 3 | java 4 | } 5 | 6 | version = "unspecified" 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | implementation(kotlin("stdlib")) 14 | testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.0") 15 | testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine") 16 | } 17 | 18 | tasks.getByName("test") { 19 | useJUnitPlatform() 20 | } -------------------------------------------------------------------------------- /kotlin-playground/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dilipsundarraj1/kotlin-springboot/d773a4c728de6cc1817af68e26b77dd65301da02/kotlin-playground/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /kotlin-playground/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /kotlin-playground/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MSYS* | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /kotlin-playground/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/HelloKotlin.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground 2 | 3 | fun main() { 4 | 5 | println("Hello Kotlin!") 6 | 7 | } 8 | -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/HelloKotlinFile.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground 2 | 3 | fun abc(){ 4 | println("abc") 5 | } 6 | 7 | fun main() { 8 | println("Hello Kotlin") 9 | abc() 10 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/basics/Conditions.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.basics 2 | 3 | fun main() { 4 | 5 | var name = "Alex" 6 | name = "Chloe" 7 | val result = if (name.length == 4) { 8 | println("Name is Four Characters") 9 | // name 10 | } else { 11 | println("Name is Not Four Characters") 12 | // name 13 | } 14 | println("result: $result") 15 | 16 | //1 -> GOLD, 2-> SILVER, 3 -> BRONZE 17 | var position = 1 18 | val medal = if (position == 1) { 19 | "GOLD" 20 | } else if (position == 2) { 21 | "SILVER" 22 | } else if (position == 3) { 23 | "BRONZE" 24 | } else { 25 | "NO MEDAL" 26 | } 27 | println("medal : $medal") 28 | 29 | position = 3 30 | val medal1 = when (position) { 31 | 1 -> "GOLD" 32 | 2 -> "SILVER" 33 | 3 -> { 34 | println("Inside position 3") 35 | "BRONZE" 36 | } 37 | else -> "NO MEDAL" 38 | } 39 | 40 | println("medal1 : $medal1") 41 | 42 | // Different Logic for Different Conditions 43 | when { 44 | position == 1 -> { 45 | println("Gold Medal") 46 | } 47 | name == "ALEX" -> { 48 | println("Name is ALex") 49 | } 50 | 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/basics/LabelsAndReturn.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.basics 2 | 3 | fun main() { 4 | 5 | for(i in 1..5){ 6 | println("i is $i ") 7 | if(i==3) break 8 | } 9 | 10 | label() 11 | 12 | /* for (i in 1..10) { 13 | if(i==3) return 14 | println("Value before return : $i") 15 | }*/ 16 | 17 | listOf(1,2,3,4,5).forEach each@{ 18 | //if(it==3) return@forEach // implicit label 19 | if(it==3) return@each // explicit label 20 | } 21 | 22 | println("End of program") 23 | 24 | } 25 | 26 | fun label() { 27 | loop@ for(i in 1..5){ 28 | println("i in label $i: ") 29 | innerLoop@ for (j in 1..10){ 30 | if(j==2) break@innerLoop // this is just equivalent to the continue 31 | // if(j==2) break@loop 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/basics/LoopsAndRanges.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.basics 2 | 3 | fun main() { 4 | val range = 1..10 5 | for (i in range){ 6 | println(i) 7 | } 8 | 9 | val reverseRange = 10 downTo 1 10 | for (i in reverseRange){ 11 | println(i) 12 | } 13 | for (i in reverseRange step 2){ 14 | println(i) 15 | } 16 | exploreWhile() 17 | exploreDoWhile() 18 | 19 | for (i in range){ 20 | if(i==3) break 21 | println("Value before break : $i") 22 | } 23 | } 24 | 25 | 26 | fun exploreDoWhile() { 27 | var i = 0 28 | do { 29 | println("Inside do while : $i") 30 | i++ 31 | }while (i < 5) 32 | } 33 | 34 | fun exploreWhile() { 35 | var x = 1 36 | while(x < 5){ 37 | println("Value of x is $x") 38 | x++ 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/basics/Variables.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.basics 2 | 3 | import com.kotlinplayground.functions.courseName 4 | import com.kotlinplayground.functions.topLevelFunction 5 | 6 | 7 | fun main() { 8 | 9 | //val name : String = "Dilip" 10 | val name = "Dilip" 11 | 12 | //name = "d" // this is not allowed for a variable thats declared as val type 13 | println(name) 14 | 15 | var age : Int = 33 16 | age = 34 17 | println(age) 18 | 19 | val salary = 30000L 20 | println(salary) 21 | 22 | val num : Double = 30000.056667 23 | println(num) 24 | 25 | val course = "Kotlin Spring" 26 | println("course : $course and the length of the course is ${course.length}") 27 | 28 | val multiLine = "ABC \n DEF" 29 | println("multiLine : $multiLine") 30 | 31 | 32 | val multiLine1 =""" 33 | ABC 34 | DEF 35 | """.trimIndent() 36 | 37 | println("multiLine1 : $multiLine1") 38 | 39 | topLevelFunction() 40 | println("courseName : $courseName") 41 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/cast/ExploreCast.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.cast 2 | 3 | import com.kotlinplayground.classes.Course 4 | 5 | fun checkType(type: Any) { 6 | 7 | when (type) { 8 | is Course -> { 9 | println("The type is Course") 10 | //val course = type as Course // This is redundant 11 | println(type.copy()) 12 | } 13 | is String -> { 14 | println("The type is Course ") 15 | println(type.lowercase()) 16 | } 17 | } 18 | } 19 | 20 | fun castNumber(any: Any) { 21 | 22 | when (any) { 23 | any as? Double -> println("Value is Double") 24 | any as? Int -> println("Value is Int") 25 | } 26 | } 27 | 28 | 29 | fun main() { 30 | 31 | val course = Course( 32 | 1, 33 | "Reactive Programming in Modern Java using Project Reactor", 34 | "DILIP" 35 | ) 36 | 37 | checkType(course) 38 | checkType("Dilip") 39 | 40 | castNumber(1.0) 41 | castNumber(1) 42 | 43 | //Number Conversions 44 | val number : Int = 1 45 | val numDouble = number.toDouble() 46 | println(numDouble) 47 | 48 | 49 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/classes/Authenticate.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.classes 2 | 3 | object Authenticate { 4 | fun authenticate(userName : String, password: String){ 5 | println("User Authenticated for userName : $userName") 6 | } 7 | } 8 | 9 | fun main() { 10 | Authenticate.authenticate("Dilip", "abc") 11 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/classes/Course.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.classes 2 | 3 | data class Course( 4 | val id: Int, 5 | val name: String, 6 | val author: String, 7 | var courseCategory: CourseCategory = CourseCategory.DEVELOPEMENT 8 | ) 9 | 10 | enum class CourseCategory{ 11 | DEVELOPEMENT, 12 | BUSINESS, 13 | DESIGN, 14 | MARKETING 15 | } 16 | 17 | fun main() { 18 | 19 | val course = Course(1, "Reactive Programming in Modern Java using Project Reactor", "Dilip") 20 | val course1 = Course(1, "Reactive Programming in Modern Java using Project Reactor", "Dilip") 21 | println("Is Course Equal ? : ${course == course1}") 22 | 23 | val course2 = course1.copy( 24 | id=2 25 | ) 26 | println("Course 2 : $course2") 27 | 28 | val marketingCourse = Course(1, "FaceBook Marketing", "Dilip", CourseCategory.MARKETING) 29 | println("marketingCourse : $marketingCourse") 30 | 31 | } 32 | -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/classes/Inheritance.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.classes 2 | 3 | 4 | open class User( 5 | val name: String, 6 | val age: Int = 0 7 | ) { 8 | open val isLoggedIn : Boolean = true 9 | open fun login() { 10 | println("Inside user login") 11 | } 12 | 13 | private fun secret(){ 14 | 15 | } 16 | 17 | protected open fun logout(){ 18 | println("Inside user logout") 19 | 20 | } 21 | } 22 | 23 | class Student( 24 | name: String, 25 | age: Int = 0 26 | ) : User(name, age) { 27 | 28 | override var isLoggedIn : Boolean = false 29 | 30 | companion object { 31 | const val noOfEnrolledCourses = 10 32 | 33 | fun country(): String { 34 | return "USA" 35 | } 36 | } 37 | 38 | fun secret(){ 39 | 40 | } 41 | 42 | override fun login() { 43 | super.login() 44 | println("Inside Student login") 45 | isLoggedIn = true 46 | } 47 | 48 | override fun logout() { 49 | super.logout() 50 | println("Inside Student logout") 51 | isLoggedIn = false 52 | } 53 | } 54 | 55 | class Instructor(name: String) : User(name) { 56 | override fun login() { 57 | println("Inside Instructor login") 58 | } 59 | } 60 | 61 | fun main() { 62 | 63 | val student = Student("Dilip") 64 | student.login() 65 | 66 | val instructor = Instructor("Dilip") 67 | instructor.login() 68 | 69 | Student.country() 70 | println("noOfEnrolledCourses: ${Student.noOfEnrolledCourses}") 71 | Student.country() 72 | 73 | val user = User("Dilip") 74 | 75 | //user. 76 | 77 | /*val instructor = Instructor("Dilip") 78 | instructor.login()*/ 79 | } 80 | -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/classes/Instructor.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.classes 2 | 3 | data class Employee( val id: Int, 4 | val name: String,) 5 | 6 | fun main() { 7 | 8 | val employee = Employee(1, "Alex") 9 | println("employee : $employee") 10 | 11 | val employee1 = Employee(1, "Alex") 12 | 13 | println("Object Equality : ${employee==employee1}") 14 | 15 | val employee2 = employee1.copy( 16 | id = 2 17 | ) 18 | println("employee2 : $employee2") 19 | 20 | } 21 | -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/classes/Item.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.classes 2 | 3 | class Item() { 4 | var name: String = "" 5 | var price: Double = 0.0 6 | get() { 7 | println("Inside Getter") 8 | return field 9 | } 10 | set(value) { 11 | if (value >= 0.0) { 12 | field = value 13 | } else { 14 | throw IllegalArgumentException("Negative Price is not Allowed!") 15 | } 16 | } 17 | 18 | constructor(_name: String) : this() { 19 | name = _name 20 | } 21 | } 22 | 23 | fun main() { 24 | val item = Item("Iphone") 25 | println("Item name is ${item.name}") 26 | item.price = 1.0 27 | println(item.price) 28 | 29 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/classes/Person.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.classes 2 | 3 | class Person( 4 | val name: String = "", 5 | val age: Int = 0 6 | ) { 7 | 8 | 9 | var email: String = "" 10 | var nameLength: Int = 0 11 | private var bankBalance: Double = 0.0 12 | 13 | init { 14 | println("Inside Init Block") 15 | nameLength = name.length 16 | } 17 | 18 | constructor( 19 | _email: String, 20 | _name: String = "", 21 | _age: Int = 0 22 | ) : this(_name, _age) { 23 | email = _email 24 | } 25 | 26 | fun action() { 27 | println("Person Walks") 28 | } 29 | 30 | private fun personalDetails() { 31 | println("Hanldes behavior tied to personal Details") 32 | bankBalance = 10000.0 33 | } 34 | 35 | } 36 | 37 | fun main() { 38 | 39 | val person = Person("Alex", 25) // new keyword is not needed 40 | person.action() 41 | println("Name : ${person.name} and the age is : ${person.age}") 42 | println("Length Of the name : ${person.nameLength}") 43 | 44 | val person1 = Person() // new keyword is not needed 45 | //person1.action() 46 | 47 | val person2 = Person(_email = "abc@gmail.com", "Alex", 25) // new keyword is not needed 48 | person1.action() 49 | println("Email is : ${person2.email}") 50 | 51 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/collections/CollectionOperations.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.collections 2 | 3 | import com.kotlinplayground.dataset.Course 4 | import com.kotlinplayground.dataset.CourseCategory 5 | import com.kotlinplayground.dataset.KAFKA 6 | import com.kotlinplayground.dataset.courseList 7 | 8 | 9 | fun exploreHashMap() { 10 | 11 | val nameAgeMutableMap = mutableMapOf("dilip" to 33, "scooby" to 4) 12 | 13 | nameAgeMutableMap 14 | .forEach { (k, v) -> 15 | println("key: $k , value : $v") 16 | } 17 | 18 | val value = nameAgeMutableMap.getOrElse("dilip1") { "abc" } 19 | println("HashMap value : $value") 20 | 21 | val result = nameAgeMutableMap.containsKey("abc") 22 | println("HashMap result : $result") 23 | 24 | val filteredMap = nameAgeMutableMap.filterKeys { it.length > 5 } 25 | .map { it.key.uppercase() } 26 | println("HashMap filteredMap : $filteredMap") 27 | 28 | val maxAge = nameAgeMutableMap 29 | //.maxByOrNull { // This returns the whole entry of the map 30 | .maxOfOrNull { // This returns the value 31 | it.value 32 | } 33 | println("HashMap maxAge : $maxAge") 34 | 35 | 36 | } 37 | 38 | fun main() { 39 | 40 | val devPredicate = { course: Course -> course.category == CourseCategory.DEVELOPEMENT } 41 | val desPredicate = { course: Course -> course.category == CourseCategory.DESIGN } 42 | 43 | 44 | val list = listOf(listOf(1,2,3),listOf(4,5,6) ) 45 | 46 | val mapResult = list.map { 47 | it.map { 48 | it.toDouble() 49 | } 50 | } 51 | println("mapResult : $mapResult") 52 | 53 | val flatmapResult = list.flatMap { outerList -> 54 | outerList.map { 55 | it.toDouble() 56 | } 57 | } 58 | println("flatmapResult : $flatmapResult") 59 | 60 | 61 | val courseList = courseList() 62 | val developmentCourses = exploreFilter(courseList, devPredicate) 63 | println("developmentCourses : $developmentCourses") 64 | 65 | /* val topicsCoveredUsingMap = developmentCourses.map { 66 | it.topicsCovered 67 | } 68 | println("topicsCoveredUsingMap : $topicsCoveredUsingMap") 69 | 70 | val topicsCoveredUsingFlatMap = developmentCourses.flatMap { 71 | it.topicsCovered 72 | } 73 | println("topicsCoveredUsingFlatMap : $topicsCoveredUsingFlatMap")*/ 74 | 75 | exploreMap(courseList, desPredicate) 76 | 77 | val kafkaCourses = exploreFlatMap(courseList, KAFKA) 78 | println("kafkaCourses : $kafkaCourses") 79 | 80 | exploreHashMap() 81 | } 82 | private fun collections_nullability() { 83 | val list: List? = null /*?: listOf()*/ 84 | 85 | list?.forEach { 86 | 87 | } 88 | val list1: List = listOf("alex", null, "adam") 89 | 90 | list1 91 | .forEach { 92 | println(it?.length) 93 | } 94 | } 95 | private fun exploreMap( 96 | courseList: MutableList, 97 | desPredicate: (Course) -> Boolean 98 | ) { 99 | val designCourses = courseList.filter { 100 | //devPredicate 101 | desPredicate.invoke(it) 102 | 103 | }.map { 104 | //it.name 105 | "${it.name} - ${it.category}" 106 | } 107 | println("designCourses : $designCourses") 108 | } 109 | 110 | private fun exploreFilter( 111 | courseList: MutableList, 112 | devPredicate: (Course) -> Boolean 113 | ): List { 114 | val developmentCourses = courseList.filter { 115 | //devPredicate 116 | devPredicate.invoke(it) 117 | 118 | } 119 | println("developmentCourses : $developmentCourses") 120 | return developmentCourses 121 | } 122 | 123 | private fun exploreFlatMap(developmentCourses: List, topic: String): List { 124 | val kafkaCourses = developmentCourses 125 | .flatMap { course -> 126 | val courseName = course.name 127 | course.topicsCovered.filter { 128 | it == topic 129 | }.map { 130 | courseName 131 | } 132 | } 133 | 134 | return kafkaCourses 135 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/collections/CollectionOperationsUsingSequences.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.collections 2 | 3 | import com.kotlinplayground.dataset.Course 4 | import com.kotlinplayground.dataset.CourseCategory 5 | import com.kotlinplayground.dataset.courseList 6 | import kotlin.time.ExperimentalTime 7 | import kotlin.time.measureTime 8 | 9 | fun main() { 10 | 11 | 12 | val namesListUsingSequence = listOf("alex", "ben", "chloe") 13 | .asSequence() 14 | .filter { it.length >= 4 } // ["alex","chloe"] 15 | .map { it.uppercase() } // ["ALEX","CHLOE"] 16 | .toList() 17 | 18 | println("namesListUsingSequence : $namesListUsingSequence") 19 | 20 | val developmentCourses = filterCourses(courseList(), CourseCategory.DEVELOPEMENT) 21 | println("developmentCourses : $developmentCourses and devcourses size : ${developmentCourses.size}") 22 | 23 | val range = 1..1000_000_000 24 | range 25 | //.asSequence() 26 | .map { it.toDouble() } 27 | .take(40) 28 | .forEach { 29 | println("Value is : $it") 30 | } 31 | } 32 | 33 | 34 | private fun filterCourses(courseList: MutableList, courseCategory: CourseCategory): List { 35 | val courses = courseList 36 | .asSequence() 37 | .filter { 38 | it.category == courseCategory 39 | } 40 | .toList() 41 | return courses 42 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/collections/ExploreArrays.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.collections 2 | 3 | fun main() { 4 | 5 | val namesArray = arrayOf("alex","ben", "chloe") 6 | val newNamesArray = namesArray.plus("adam") 7 | println("namesArray : ${namesArray.size}") 8 | println("newNamesArray : ${newNamesArray.size}") 9 | 10 | val filteredArray = namesArray.filter { 11 | it.length >= 4 12 | } 13 | println("filteredArray : $filteredArray") 14 | 15 | val toArray = filteredArray.toTypedArray() 16 | println("toArray : $toArray") 17 | 18 | 19 | val emptyArray= emptyArray() 20 | val newArray = emptyArray.plus("abc") 21 | 22 | 23 | emptyArray.forEach { 24 | println("Value is : $it") 25 | } 26 | println("emptyArray : $emptyArray") 27 | 28 | newArray.forEach { 29 | println("Value is : $it") 30 | } 31 | println("newArray : $newArray") 32 | 33 | 34 | 35 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/collections/ExploreCollections.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.collections 2 | 3 | import com.kotlinplayground.dataset.courseList 4 | 5 | 6 | fun main() { 7 | 8 | val names = listOf("Alex", "Ben", "Chloe") 9 | println("names : $names") 10 | val namesMutableList = mutableListOf("Alex", "Ben", "Chloe") 11 | 12 | namesMutableList.add("Adam") 13 | println("namesMutableList : $namesMutableList") 14 | 15 | 16 | val nameAgeMap = mapOf("dilip" to 33, "scooby" to 4) 17 | println("nameAgeMap : $nameAgeMap") 18 | 19 | val nameAgeMutableMap = mutableMapOf("dilip" to 33, "scooby" to 4) 20 | nameAgeMutableMap["abc"] = 100 21 | println("nameAgeMutableMap : $nameAgeMutableMap") 22 | 23 | val set = setOf("adam", "ben", "chloe") 24 | println("set: $set") 25 | 26 | val mutableSet = mutableSetOf("adam", "ben", "chloe") 27 | mutableSet.add("adam1") 28 | println("mutableSet : $mutableSet") 29 | 30 | val add = { x: Int -> x + x } 31 | 32 | fun add(x:Int) = x+x 33 | 34 | listOf(1, 2, 3) 35 | .forEach { 36 | val result = add(it) 37 | println(result) 38 | } 39 | 40 | listOf(1, 2, 3) 41 | .forEach { 42 | val result = add(it) 43 | println(result) 44 | } 45 | 46 | 47 | val courses = courseList() 48 | courses 49 | .forEach { course -> 50 | // println("course : $course") 51 | } 52 | 53 | courses 54 | .forEach { 55 | // println("it : $it") 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/collections/ExploreLambdas.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.collections 2 | 3 | /** 4 | * Higher Order Function 5 | */ 6 | fun calculate(x: Int, y: Int, op: (x: Int, y: Int) -> Int): Int { 7 | return op(x, y) 8 | } 9 | 10 | fun main() { 11 | 12 | val addLambda = { x: Int -> x * x } 13 | 14 | val addResult = addLambda(3) 15 | println(addResult) 16 | 17 | 18 | val multiplyLambda = { x: Int, y: Int -> 19 | println("Input arguments are x: $x and y : $y") 20 | x * y 21 | } 22 | 23 | val multiplyResult = multiplyLambda(2, 3) 24 | println(multiplyResult) 25 | 26 | val numbers = listOf(1, 2, 3) 27 | numbers 28 | .forEach { 29 | println("it in first line: ${addLambda(it)}") 30 | println("it second line : $it") 31 | } 32 | 33 | val result = calculate(2, 3) { a, b -> a * b } 34 | println("Result : $result") 35 | 36 | val add = calculate(2, 3) { a, b -> a + b } 37 | println("add : $add") 38 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/dataset/DataHelper.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.dataset 2 | 3 | 4 | const val KAFKA = "Kafka" 5 | const val ADVERTISING = "Adversting" 6 | const val BUSINESS_ANALYTICS = "Business Analytics" 7 | const val USER_EXPERIENCE_DESIGN = "User Experience Design" 8 | const val SPRING_BOOT = "SpringBoot" 9 | const val JAVA = "java" 10 | const val REACTIVE_PROGRAMMING = "Reactive Programming" 11 | const val MULTI_THREADING = "MultiThreading" 12 | const val INTEGRATION_TESTING = "Integraion Testing" 13 | 14 | data class Course( 15 | val id: Int, 16 | val name: String, 17 | val category: CourseCategory, 18 | val topicsCovered: List 19 | ) 20 | 21 | enum class CourseCategory{ 22 | DEVELOPEMENT, 23 | BUSINESS, 24 | DESIGN, 25 | MARKETING 26 | } 27 | 28 | data class Instructor( 29 | val name: String, 30 | val age: Int, 31 | val noOfCourses : Int, 32 | val coursesTaught : List 33 | ) 34 | 35 | 36 | fun courseList(): MutableList { 37 | 38 | return mutableListOf( 39 | Course( 40 | 1, 41 | "Apache Kafka for Developers using SpringBoot", 42 | CourseCategory.DEVELOPEMENT, 43 | mutableListOf(KAFKA, JAVA, SPRING_BOOT) 44 | ), 45 | Course( 46 | 2, 47 | "Apache Kafka for Beginners", 48 | CourseCategory.DEVELOPEMENT, 49 | mutableListOf(KAFKA, JAVA) 50 | ), 51 | Course( 52 | 3, 53 | "Multithreading, Parallel and Asynchronous Coding Modern Java ", 54 | CourseCategory.DEVELOPEMENT, 55 | mutableListOf(JAVA, MULTI_THREADING) 56 | ), 57 | Course( 58 | 4, 59 | "Modern Java - Learn Java 8 Features By coding it", 60 | CourseCategory.DEVELOPEMENT, 61 | mutableListOf(JAVA) 62 | ), 63 | Course( 64 | 5, 65 | "Reactive Programming in Modern Java using Project Reactor", 66 | CourseCategory.DEVELOPEMENT, 67 | mutableListOf(REACTIVE_PROGRAMMING, JAVA) 68 | ), 69 | Course( 70 | 6, 71 | "Build Reactive MicroServices using Spring WebFlux/SpringBoot", 72 | CourseCategory.DEVELOPEMENT, 73 | mutableListOf(REACTIVE_PROGRAMMING, JAVA, SPRING_BOOT) 74 | ), 75 | Course( 76 | 7, 77 | "Wiremock for Java Developers", 78 | CourseCategory.DEVELOPEMENT, 79 | mutableListOf(JAVA, INTEGRATION_TESTING) 80 | ), 81 | Course( 82 | 8, 83 | "FaceBook Marketing", 84 | CourseCategory.MARKETING, 85 | mutableListOf(ADVERTISING) 86 | ), 87 | Course( 88 | 9, 89 | "Product Management", 90 | CourseCategory.BUSINESS, 91 | mutableListOf(BUSINESS_ANALYTICS) 92 | ), 93 | Course( 94 | 11, 95 | "UI/UX Design", 96 | CourseCategory.DESIGN, 97 | mutableListOf(USER_EXPERIENCE_DESIGN) 98 | ) 99 | 100 | ) 101 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/exceptions/ExploreExceptions.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.exceptions 2 | 3 | import java.io.File 4 | import java.io.FileInputStream 5 | 6 | 7 | fun returnNothing(): Nothing { 8 | throw RuntimeException("Exception") 9 | } 10 | 11 | fun nameLength(name: String?) = try { 12 | name!!.length 13 | } catch (ex: Exception) { 14 | println("Exception is : $ex") 15 | null 16 | } 17 | 18 | 19 | fun main() { 20 | 21 | try { 22 | returnNothing() 23 | } catch (ex: Exception) { 24 | println("Exception is $ex") 25 | } finally { 26 | println("Finally Block") 27 | } 28 | 29 | println("Name Length is : ${nameLength("alex")}") 30 | println("Name Length is : ${nameLength(null)}") 31 | 32 | val file = File("file.txt") 33 | val stream = FileInputStream(file) 34 | 35 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/functions/Functions.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.functions 2 | 3 | import java.time.LocalDate 4 | 5 | //fun printHello(){ 6 | fun printHello() : Unit { 7 | println("Hello!") 8 | } 9 | 10 | 11 | fun returnNothing() : Nothing { 12 | throw RuntimeException("Exception") 13 | } 14 | 15 | fun printName(name: String){ 16 | println("Name is $name") 17 | } 18 | 19 | fun addition(x: Int, y : Int): Int { 20 | return x+y 21 | } 22 | 23 | /** 24 | * Use this only if the whole method is an expression 25 | * This is concise and you can avoid the redundant return statement 26 | */ 27 | fun addition_approach1(x: Int, y : Int) = x+y 28 | 29 | fun printPersonDetails(name : String, email : String = "", dob : LocalDate = LocalDate.now()){ 30 | 31 | println("Name is $name and the email is $email and the dob is $dob") 32 | } 33 | 34 | 35 | /** 36 | * 37 | * This just accepts arbitary number of arguments 38 | */ 39 | fun printMultipleThings(vararg alphabets: String){ 40 | println("strings : $alphabets") 41 | for(alphabet in alphabets ){ 42 | println(alphabet) 43 | } 44 | 45 | //val alphabetList = listOf(alphabets) 46 | val alphabetList = listOf(*alphabets) // this is also called spread operator 47 | println("alphabetList : $alphabetList") 48 | 49 | } 50 | 51 | fun main() { 52 | printHello() 53 | printName("Dilip") 54 | val result = addition(2,3) 55 | println("Result is $result") 56 | 57 | val result2 = addition_approach1(2,3) 58 | println("Result is $result2") 59 | printMultipleThings("A", "B", "C") 60 | printPersonDetails("Dilip", "abc@gmail.com" , LocalDate.parse("2000-01-01") ) 61 | printPersonDetails("Dilip") 62 | printPersonDetails("Dilip", dob = LocalDate.parse("2000-01-01") ) 63 | printPersonDetails(dob = LocalDate.parse("2000-01-01") , name = "Dilip", email = "abc@gmail.com") 64 | 65 | returnNothing() 66 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/functions/Toplevel.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.functions 2 | 3 | const val courseName = "Kotlin Programming" 4 | 5 | fun topLevelFunction(): Int { 6 | return (0..100).random() 7 | } 8 | 9 | fun main() { 10 | val num = topLevelFunction() 11 | println("num : $num") 12 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/interfaces/Interfaces.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.interfaces 2 | 3 | import com.kotlinplayground.classes.Course 4 | 5 | interface CourseRepository { 6 | val isCoursePersisted: Boolean 7 | get() = false 8 | 9 | fun getById(id: Int): Course 10 | 11 | fun save(course: Course): Int { 12 | println("course : $course") 13 | return course.id 14 | } 15 | } 16 | 17 | interface Repository { 18 | 19 | fun getAll() : Any 20 | } 21 | 22 | class SqlCourseRepository : CourseRepository, Repository { 23 | 24 | override var isCoursePersisted: Boolean = false 25 | get() { 26 | return true 27 | } 28 | 29 | 30 | override fun getById(id: Int): Course { 31 | return Course( 32 | id = id, 33 | "Kafka For Developers using Spring Boot", 34 | "Dilip Sundarraj" 35 | ) 36 | } 37 | 38 | override fun save(course: Course): Int { 39 | println("course in SqlCourseRepository : $course") 40 | isCoursePersisted = true 41 | return course.id 42 | } 43 | 44 | override fun getAll(): Any { 45 | TODO("Not yet implemented") 46 | } 47 | 48 | } 49 | 50 | class NoSqlCourseRepository : CourseRepository { 51 | override fun getById(id: Int): Course { 52 | return Course( 53 | id = id, 54 | "Kafka For Developers using Spring Boot", 55 | "Dilip Sundarraj" 56 | ) 57 | } 58 | 59 | override fun save(course: Course): Int { 60 | println("course in SqlCourseRepository : $course") 61 | return course.id 62 | } 63 | 64 | } 65 | 66 | interface A { 67 | fun doSomething() { 68 | println("Do Something in A") 69 | } 70 | } 71 | 72 | interface B { 73 | fun doSomething() { 74 | println("Do Something in B") 75 | } 76 | } 77 | 78 | class AB : A, B { 79 | override fun doSomething() { 80 | super.doSomething() 81 | super.doSomething() 82 | println("Do something in AB") 83 | } 84 | 85 | } 86 | 87 | //INT9145453 88 | 89 | fun main() { 90 | 91 | val course = Course( 92 | 1, 93 | "Kafka For Developers using Spring Boot", 94 | "Dilip Sundarraj" 95 | ) 96 | 97 | val sqlCourseRepository = SqlCourseRepository() 98 | sqlCourseRepository.save(course) 99 | 100 | val noSqlCourseRepository = NoSqlCourseRepository() 101 | noSqlCourseRepository.save(course) 102 | 103 | val ab = AB() 104 | ab.doSomething() 105 | } -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/nulls/ExploreNulls.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.nulls 2 | 3 | data class Movie( 4 | val id: Int?, 5 | val name: String 6 | ) 7 | 8 | fun printName(name: String) { 9 | println("Name is : $name") 10 | } 11 | 12 | fun printName1(name: String?) { 13 | println("Name is : $name") 14 | } 15 | 16 | 17 | fun main() { 18 | 19 | var nameNullable: String? = null 20 | println(nameNullable?.length) // ? is the safeCall Operator 21 | nameNullable = "Alex" 22 | nameNullable?.run { 23 | printName(nameNullable!!) 24 | } 25 | 26 | 27 | val length = nameNullable?.length ?: 0 // ?: is the elvis Operator 28 | println(length) 29 | 30 | nameNullable = "alex" 31 | val length1 = nameNullable.length.toLong() 32 | println("Length of the name is : $length1") 33 | 34 | val nameNonNull: String = "Dilip" 35 | //val nameNonNull = "Dilip" 36 | 37 | println(nameNonNull) 38 | printName1(nameNonNull) 39 | 40 | val movie = saveMovie(Movie(null, "Avengers")) 41 | println(movie.id!!) 42 | } 43 | 44 | fun saveMovie(movie: Movie): Movie = 45 | movie.copy(id = 1) 46 | //movie.copy(id = null) -------------------------------------------------------------------------------- /kotlin-playground/src/main/kotlin/com/kotlinplayground/scopefunctions/ExploreScopeFunctions.kt: -------------------------------------------------------------------------------- 1 | package com.kotlinplayground.scopefunctions 2 | 3 | import com.kotlinplayground.classes.Course 4 | import com.kotlinplayground.classes.CourseCategory 5 | 6 | 7 | fun main() { 8 | 9 | exploreApply() 10 | exploreAlso() 11 | exploreLet() 12 | exploreWith() 13 | exploreRun() 14 | 15 | 16 | } 17 | 18 | fun exploreRun() { 19 | 20 | var numbers : MutableList? = null 21 | val result = numbers.run { 22 | println("Inside run") 23 | numbers = mutableListOf(1,2,3) 24 | numbers?.sum() 25 | } 26 | println("result in Run : $result") 27 | 28 | } 29 | 30 | fun exploreWith() { 31 | val numbers = mutableListOf(1, 2, 3, 4, 5) 32 | 33 | val result = with(numbers) { 34 | println("Size is ${size}") 35 | plus(6) 36 | numbers.sum() 37 | } 38 | println("With result is : $result") 39 | 40 | } 41 | 42 | fun exploreLet() { 43 | val numbers = mutableListOf(1, 2, 3, 4, 5) 44 | val result = numbers.map { it * 2 }.filter { it > 5 }.let { 45 | println(it) 46 | it.sum() 47 | //println(it) 48 | } 49 | println("result: $result") 50 | 51 | var name: String? = null 52 | name = "Dilip" 53 | val result1 = name?.let { value -> 54 | println("Name is : $name") 55 | //it.length 56 | println("Length is ${value.length}") 57 | value.uppercase() 58 | } 59 | println("result1 : $result1") 60 | 61 | 62 | } 63 | 64 | fun exploreAlso() { 65 | 66 | val course = Course( 67 | 1, 68 | "Design Thinking in Kotlin", 69 | "Dilip" 70 | ) 71 | .apply { 72 | //this.courseCategory = CourseCategory.DESIGN 73 | courseCategory = CourseCategory.DESIGN 74 | } 75 | .also { 76 | println("Object is ready $it") 77 | } 78 | 79 | println("course is : $course") 80 | 81 | } 82 | 83 | private fun exploreApply() { 84 | val course = Course( 85 | 1, 86 | "Design Thinking in Kotlin", 87 | "Dilip" 88 | ) 89 | .apply { 90 | this.courseCategory = CourseCategory.DESIGN 91 | } 92 | 93 | println("course is : $course") 94 | } --------------------------------------------------------------------------------