From 962012d0c3338abe010a438406603bd6db0f75ba Mon Sep 17 00:00:00 2001 From: rybalkinsd Date: Wed, 25 Oct 2017 13:35:21 +0300 Subject: [PATCH 01/89] lecture05 --- build.gradle | 111 ------------------------------------------------ settings.gradle | 0 2 files changed, 111 deletions(-) delete mode 100644 build.gradle delete mode 100644 settings.gradle diff --git a/build.gradle b/build.gradle deleted file mode 100644 index 77cfa67b56..0000000000 --- a/build.gradle +++ /dev/null @@ -1,111 +0,0 @@ -plugins { - id 'org.springframework.boot' version '1.5.8.RELEASE' - id 'com.github.kt3k.coveralls' version '2.6.3' -} - -springBoot { - mainClass = "ru.atom.chat.ChatApplication" -} - -// constants declaration -ext { - jdkVersion = 1.8 - - junitVersion = "4.12" - log4jVersion = "2.7" - jetbrainsAnnotationVersion = "15.0" - okhttpVersion = "3.6.0" - gsonjVersion = "2.7" - postgresVersion = "9.4-1200-jdbc41" - jetbrainsAnnotationVersion = "15.0" - hibernateVersion = "5.1.10.Final" - jolVersion = "0.8" -} - -allprojects { - group = "technoatom" - version = "1.0-SNAPSHOT" - - apply plugin: 'java' - apply plugin: 'checkstyle' - apply plugin: 'jacoco' - - repositories { - mavenCentral() - } - - sourceCompatibility = jdkVersion - targetCompatibility = jdkVersion -} - -subprojects { - if (!project.name.equals('bomberman/frontend')) - apply plugin: 'org.springframework.boot' - - - checkstyle { - ignoreFailures = false - toolVersion = '7.5' - configFile = rootProject.file('config/checkstyle/checkstyle.xml') - } - - tasks.withType(Checkstyle) { - reports { - xml.enabled false - html.destination "$rootProject.buildDir/report/${project.name}.html" - html.stylesheet resources.text.fromFile(rootProject.file('config/checkstyle/checkstyle-custom.xsl')) - } - } - -} - -// common libraries declaration -ext.libraries = [ - spring_boot : [ - "org.springframework.boot:spring-boot-starter-web", - "org.springframework.boot:spring-boot-starter-actuator", - ], - - spring_boot_test : "org.springframework.boot:spring-boot-starter-test", - - spring_boot_websocket: "org.springframework.boot:spring-boot-starter-websocket", - spring_boot_jpa: "org.springframework.boot:spring-boot-starter-data-jpa", - - junit: "junit:junit:$junitVersion", - log4j: [ - "org.apache.logging.log4j:log4j-api:$log4jVersion", - "org.apache.logging.log4j:log4j-core:$log4jVersion" - ], - jetbrainsAnnotations: "org.jetbrains:annotations:$jetbrainsAnnotationVersion", - okhttp: "com.squareup.okhttp3:okhttp:$okhttpVersion", - gson: "com.google.code.gson:gson:$gsonjVersion", - postgres: "org.postgresql:postgresql:$postgresVersion", - hibernate: "org.hibernate:hibernate-core:$hibernateVersion", - jol: "org.openjdk.jol:jol-core:$jolVersion", - jol_samples: "org.openjdk.jol:jol-samples:$jolVersion" -] - -// code coverage settings -jacocoTestReport { - additionalSourceDirs = files(subprojects.sourceSets.main.allSource.srcDirs) - sourceDirectories = files(subprojects.sourceSets.main.allSource.srcDirs) - classDirectories = files(subprojects.sourceSets.main.output) - executionData = files(subprojects.jacocoTestReport.executionData) - onlyIf = { - true - } - - reports { - xml.enabled = true - html.enabled = true - } - doFirst { - executionData = files(executionData.findAll { - it.exists() - }) - } -} - -coveralls { - sourceDirs = files(subprojects.sourceSets.main.allSource.srcDirs).files.absolutePath -} diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index e69de29bb2..0000000000 From f592dc2cac63289100b967303b0a133b685184a4 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Tue, 20 Mar 2018 22:26:30 +0300 Subject: [PATCH 02/89] rm HelloWorld --- lecture05/build.gradle | 46 +++-- lecture05/gradlew | 172 ++++++++++++++++++ lecture05/gradlew.bat | 84 +++++++++ .../java/ru/atom/boot/hw/HelloController.java | 21 --- .../java/ru/atom/boot/hw/HelloSpringBoot.java | 13 -- .../src/main/resources/application.properties | 4 +- .../atom/annotation/AnnotationDemoTest.java | 6 - .../ru/atom/boot/hw/HelloControllerTest.java | 34 ---- 8 files changed, 285 insertions(+), 95 deletions(-) create mode 100755 lecture05/gradlew create mode 100644 lecture05/gradlew.bat delete mode 100644 lecture05/src/main/java/ru/atom/boot/hw/HelloController.java delete mode 100644 lecture05/src/main/java/ru/atom/boot/hw/HelloSpringBoot.java delete mode 100644 lecture05/src/test/java/ru/atom/boot/hw/HelloControllerTest.java diff --git a/lecture05/build.gradle b/lecture05/build.gradle index 84ad1078c1..898ad8eb59 100644 --- a/lecture05/build.gradle +++ b/lecture05/build.gradle @@ -1,26 +1,32 @@ -dependencies { - compile rootProject.libraries.spring_boot - compile rootProject.libraries.log4j - - - testCompile rootProject.libraries.junit - testCompile rootProject.libraries.spring_boot_test +plugins { + id 'org.springframework.boot' version '2.0.0.RELEASE' } -springBoot { - mainClass = "ru.atom.boot.hw.HelloSpringBoot" +repositories { + mavenCentral() } +apply plugin: 'java' +apply plugin: 'checkstyle' -sourceSets { - main { - java { - srcDirs = ['src/main/java'] - } - } - test { - java { - srcDirs = ['src/test/java'] - } - } +dependencies { + // https://mvnrepository.com/artifact/org.slf4j/slf4j-api + compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25' + // https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl + //compile group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.10.0' + // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web + compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.0.RELEASE' + // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator + compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator', version: '2.0.0.RELEASE' + + // https://mvnrepository.com/artifact/junit/junit + testCompile group: 'junit', name: 'junit', version: '4.4' + // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test + testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.0.0.RELEASE' } + +checkstyle { + ignoreFailures = false + toolVersion = '7.5' + configFile = new File('../config/checkstyle/checkstyle.xml') +} \ No newline at end of file diff --git a/lecture05/gradlew b/lecture05/gradlew new file mode 100755 index 0000000000..cccdd3d517 --- /dev/null +++ b/lecture05/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/lecture05/gradlew.bat b/lecture05/gradlew.bat new file mode 100644 index 0000000000..e95643d6a2 --- /dev/null +++ b/lecture05/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/lecture05/src/main/java/ru/atom/boot/hw/HelloController.java b/lecture05/src/main/java/ru/atom/boot/hw/HelloController.java deleted file mode 100644 index 7d77c102e8..0000000000 --- a/lecture05/src/main/java/ru/atom/boot/hw/HelloController.java +++ /dev/null @@ -1,21 +0,0 @@ -package ru.atom.boot.hw; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; - -@Controller -@RequestMapping("hello") -public class HelloController { - - /** - * curl test - * - * curl -i localhost:8080/hello/world - */ - @RequestMapping("world") - @ResponseBody - public String hi() { - return "Hello, Spring-boot World!"; - } -} diff --git a/lecture05/src/main/java/ru/atom/boot/hw/HelloSpringBoot.java b/lecture05/src/main/java/ru/atom/boot/hw/HelloSpringBoot.java deleted file mode 100644 index ec907a58e0..0000000000 --- a/lecture05/src/main/java/ru/atom/boot/hw/HelloSpringBoot.java +++ /dev/null @@ -1,13 +0,0 @@ -package ru.atom.boot.hw; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class HelloSpringBoot { - - public static void main(String[] args) { - SpringApplication.run(HelloSpringBoot.class, args); - } - -} diff --git a/lecture05/src/main/resources/application.properties b/lecture05/src/main/resources/application.properties index ad1a7e46c0..d4efc55086 100644 --- a/lecture05/src/main/resources/application.properties +++ b/lecture05/src/main/resources/application.properties @@ -1 +1,3 @@ -management.security.enabled=false \ No newline at end of file +server.port = 8080 +management.server.port = 7001 +management.endpoints.web.exposure.include=* \ No newline at end of file diff --git a/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java b/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java index 2ccd5a4f40..b111db1611 100644 --- a/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java +++ b/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java @@ -15,12 +15,6 @@ public void countOverride() throws Exception { ru.atom.boot.mm.ConnectionController.class, Override.class)).isEqualTo(0); } - @Test - public void countRequestMapping() throws Exception { - assertThat(AnnotationDemo.getNumberOfAnnotatedMethods( - ru.atom.boot.hw.HelloController.class, RequestMapping.class)).isEqualTo(1); - } - @Test public void countResponseStatus() throws Exception { assertThat(AnnotationDemo.getNumberOfAnnotatedMethods( diff --git a/lecture05/src/test/java/ru/atom/boot/hw/HelloControllerTest.java b/lecture05/src/test/java/ru/atom/boot/hw/HelloControllerTest.java deleted file mode 100644 index a74e350934..0000000000 --- a/lecture05/src/test/java/ru/atom/boot/hw/HelloControllerTest.java +++ /dev/null @@ -1,34 +0,0 @@ -package ru.atom.boot.hw; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.test.web.servlet.MockMvc; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; - -@RunWith(SpringRunner.class) -@WebMvcTest -public class HelloControllerTest { - - - /** - * This is Dependency Injection usage - */ - @Autowired - private MockMvc mockMvc; - - @Test - public void hiTest() throws Exception { - mockMvc.perform(get("/hello/world")) - .andDo(print()) - .andExpect(status().isOk()) - .andExpect(content().string("Hello, Spring-boot World!")); - } - -} \ No newline at end of file From 5ebe2dd355d7e7d217f94e71ac1296265fa1a074 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Tue, 20 Mar 2018 22:29:20 +0300 Subject: [PATCH 03/89] tests fixes --- .../src/test/java/ru/atom/annotation/AnnotationDemoTest.java | 1 - .../test/java/ru/atom/boot/mm/ConnectionControllerTest.java | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java b/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java index b111db1611..ff7ca325f6 100644 --- a/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java +++ b/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java @@ -1,7 +1,6 @@ package ru.atom.annotation; import org.junit.Test; -import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseStatus; import static org.assertj.core.api.Assertions.assertThat; diff --git a/lecture05/src/test/java/ru/atom/boot/mm/ConnectionControllerTest.java b/lecture05/src/test/java/ru/atom/boot/mm/ConnectionControllerTest.java index d08cd51c42..11cc769e31 100644 --- a/lecture05/src/test/java/ru/atom/boot/mm/ConnectionControllerTest.java +++ b/lecture05/src/test/java/ru/atom/boot/mm/ConnectionControllerTest.java @@ -4,6 +4,7 @@ import org.junit.Test; import static org.assertj.core.api.Java6Assertions.assertThat; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class ConnectionControllerTest { @@ -12,13 +13,13 @@ public class ConnectionControllerTest { @Ignore public void connect() throws Exception { ConnectionController connectionHandler = new ConnectionController(); - assertThat(connectionHandler.list()).isEmpty(); + assertTrue(connectionHandler.list().isEmpty()); connectionHandler.connect(1, "a"); connectionHandler.connect(2, "b"); connectionHandler.connect(3, "c"); - assertThat(connectionHandler.list()).isNotEmpty(); + assertFalse(connectionHandler.list().isEmpty()); } @Test From 884cde3ad236f1df97568a42556c199393f4276a Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Tue, 20 Mar 2018 22:30:39 +0300 Subject: [PATCH 04/89] presentation --- lecture05/presentation/PITCHME.md | 102 +++++++++++++++--------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/lecture05/presentation/PITCHME.md b/lecture05/presentation/PITCHME.md index df4e10b3ba..bda5eca3e9 100644 --- a/lecture05/presentation/PITCHME.md +++ b/lecture05/presentation/PITCHME.md @@ -1,15 +1,15 @@ -#HSLIDE +--- # Java lecture 5 ## Web server -#HSLIDE +--- ## Отметьтесь на портале https://atom.mail.ru/ -#HSLIDE +--- ### get ready ```bash > git fetch upstream @@ -19,14 +19,14 @@ https://atom.mail.ru/ Refresh gradle project -#HSLIDE +--- ### Поиграем в web-server Any questions on HTTP? **You must understand HTTP!** -#HSLIDE +--- ### Agenda 1. Threads 1. Annotations @@ -35,7 +35,7 @@ Any questions on HTTP? 1. Spring -#HSLIDE +--- ### Threads 1. **[Threads]** 1. Annotations @@ -43,7 +43,7 @@ Any questions on HTTP? 1. HTTP Web Server 1. Spring -#HSLIDE +--- ### Threads intro As we go into the land of servers, we face multi-threaded environment. @@ -52,30 +52,30 @@ So this gentle introduction only covers basics that are necessary so far. We will have deeper topics on concurrency further in the course. -#HSLIDE +--- ### Why do we need parallel execution? -#HSLIDE +--- ### Concurrency vs parallelism **Concurrency** - contention on shared resources **Parallelism** is possible without concurrency -#HSLIDE +--- ### Process vs Thread **Process** has dedicated resources (memory) **Threads** share memory space -#HSLIDE +--- ### Process vs Thread process -#HSLIDE +--- ### Operating System role 1. Creates threads (clone syscall) 1. Schedules threads (context switch) @@ -84,7 +84,7 @@ We will have deeper topics on concurrency further in the course. Behaviour of multithreaded program is (inter alia) dependent on OS scheduling -#HSLIDE +--- ### interface Runnable ```java @FunctionalInterface @@ -94,7 +94,7 @@ interface Runnable { ``` -#HSLIDE +--- ### class Thread ```java class Thread implements Runnable { @@ -108,7 +108,7 @@ class Thread implements Runnable { ``` -#HSLIDE +--- ### Start and Run ```java new Thread().start(); @@ -117,11 +117,11 @@ new Thread( runnable ).start(); ``` -#HSLIDE +--- ### Start and Run exception -#HSLIDE +--- ### Thread instantiation @See ru.atom.thread.instantiation and tests @@ -132,7 +132,7 @@ new Thread( runnable ).start(); - Thread::sleep -#HSLIDE +--- ### Waiting for thread termination @See ru.atom.thread.join and tests @@ -140,7 +140,7 @@ new Thread( runnable ).start(); - Thread::interrupt -#HSLIDE +--- ### jstack Util to observe java process stack state. @@ -152,7 +152,7 @@ Util to observe java process stack state. > less report.info ``` -#HSLIDE +--- ### Queue Queue is a shared resource in a multi-threaded environment. @@ -174,12 +174,12 @@ interface BlockingQueue implements java.util.Queue { ``` -#HSLIDE +--- ### Queue queue -#HSLIDE +--- ### Your turn @See ru.atom.thread.practice in tests @@ -194,7 +194,7 @@ interface BlockingQueue implements java.util.Queue { 1. Implement missing methods -#HSLIDE +--- ### Annotations 1. Threads 1. **[Annotations]** @@ -203,12 +203,12 @@ interface BlockingQueue implements java.util.Queue { 1. Match-maker -#HSLIDE +--- ### Annotations What annotations did you see before? -#HSLIDE +--- ### Override ```java @Target(ElementType.METHOD) @@ -217,7 +217,7 @@ public @interface Override { } ``` -#HSLIDE +--- ### Reflection API Reflection is an API to find information about classes/fields/methods in application runtime. @@ -225,7 +225,7 @@ in application runtime. @See ru.atom.annotation and tests -#HSLIDE +--- ### HTTP Web Server 1. Threads 1. Annotations @@ -234,7 +234,7 @@ in application runtime. 1. Match-maker -#HSLIDE +--- ### Web server **Web server** - is a program that processes HTTP Requests and provide HTTP responses. @@ -247,7 +247,7 @@ in application runtime. - Embedded Tomcat (**our choice**) -#HSLIDE +--- ### Alternative - application servers Alternatively large projects can use **Application Servers** to manage web application: - Sun GlassFish @@ -256,7 +256,7 @@ Alternatively large projects can use **Application Servers** to manage web appli **We will not go this way** -#HSLIDE +--- ### Servlet container Basic function of web server - to serve static content (html, css, images) But most web servers provide some functionality to apply **custom logic on HTTP Request** and return **custom HTTP Response**. @@ -266,16 +266,16 @@ This can be used to serve dynamic pages or for custom **web application** (that' Custom server logic in java can be embedded into **servlet container** (part of web-server, that manages **Servlets**) -#HSLIDE +--- ### Servlet servlet -#HSLIDE +--- ### Servlet **Servlet** - is class that handles HTTP Requests. Java provide low-level **Servlet API** -#HSLIDE +--- ### Web Server approximate behavior 1. Start 1. Initialize internal servlets @@ -285,7 +285,7 @@ Java provide low-level **Servlet API** 1. Process routing of outgoing response -#HSLIDE +--- ### Modern way **Servlet API** (a part of java API) - is low-level API People tend to use high-level frameworks to make web applications @@ -294,7 +294,7 @@ This frameworks use servlet API under the hood The most famous web framework is **Spring** -#HSLIDE +--- ### Spring 1. Threads 1. Annotations @@ -303,7 +303,7 @@ The most famous web framework is **Spring** 1. Match-maker -#HSLIDE +--- ### Spring exception is a universal open-source framework, used to develop web applications @@ -311,7 +311,7 @@ https://spring.io/ First version - **2002** -#HSLIDE +--- ### Spring modules It includes a number of modules for different functionality: - Spring MVC for building Web Applications @@ -323,19 +323,19 @@ It includes a number of modules for different functionality: Today we will build web application with **Spring MVC** module -#HSLIDE +--- ### MVC **MVC (Model-View-Controller)** - popular pattern used to build web apps -#HSLIDE +--- ### Spring MVC **Spring MVC** - Spring Module that make it easier to build MVC Applications (Like **Django**, **Rails**) exception -#HSLIDE +--- ### Spring Boot Spring is a powerful tool and has a lot of configuration options. **Spring Boot** is a project, that makes working with Spring easier: @@ -349,7 +349,7 @@ First version: **2014** **With Spring Boot our life is much easier :)** -#HSLIDE +--- ### Hello Spring Boot **@See ru.atom.boot.hw** All the magic works via **annotations** @@ -363,7 +363,7 @@ All the magic works via **annotations** *@ResponseBody* method returns result will be the **HTTP response body** -#HSLIDE +--- ### Important notes These notes are important to understand: 1. HelloController is **Singleton** (by default) - the same instance for all requests @@ -371,11 +371,11 @@ These notes are important to understand: Here comes **multi-threading** with **shared memory** (concurrency) - topic for further discussion -#HSLIDE +--- ### Match-maker practice @See ru.atom.thread.mm and tests -#HSLIDE +--- ### Match-maker Our Bomberman is a client-server game. @@ -384,17 +384,17 @@ As a client server game we have Clients or **Connections** Clients want to play. So, we have Games or **GameSessions** -#HSLIDE +--- ### Match-maker mm -#HSLIDE +--- ### Match-making algorithm mmalgo -#HSLIDE +--- ### Match-making algorithm **Assume we have a queue storing connections** @@ -409,7 +409,7 @@ Match-maker is an infinity-loop algorithm with steps - Continue to step #1 -#HSLIDE +--- ### Connection producer We do not have server to get connections for now. We need an instance to emulate client. @@ -418,7 +418,7 @@ We need an instance to emulate client. It is possible to have many producers. -#HSLIDE +--- ### Practice 2 #### We have Math-maker service implementation @@ -434,7 +434,7 @@ Math-maker service implementation - GameControllerIntegrationTest::list() -#HSLIDE +--- ### Summary 1. **Threads** are not difficult until concurrency comes 1. **Annotations** help to build meta-information about application and can be used in both compile-time and runtime @@ -445,7 +445,7 @@ Math-maker service implementation 1. Keep learning **HTTP** -#HSLIDE +--- **Оставьте обратную связь** (вам на почту придет анкета) From da84ba049e1aa3a2b32b64a28f0d71897a8d1f6a Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Tue, 20 Mar 2018 22:33:01 +0300 Subject: [PATCH 05/89] presentation --- lecture05/presentation/PITCHME.md | 5 ++++- lecture05/presentation/PITCHME.yaml | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lecture05/presentation/PITCHME.md b/lecture05/presentation/PITCHME.md index bda5eca3e9..d30616eac2 100644 --- a/lecture05/presentation/PITCHME.md +++ b/lecture05/presentation/PITCHME.md @@ -1,7 +1,8 @@ --- # Java lecture 5 -## Web server +## Spring, Threads, Annotations +2018 --- @@ -11,9 +12,11 @@ https://atom.mail.ru/ --- ### get ready +[https://github.com/rybalkinsd/atom](https://github.com/rybalkinsd/atom) ```bash > git fetch upstream > git checkout -b lecture05 upstream/lecture05 +> cd lecture05 ``` Refresh gradle project diff --git a/lecture05/presentation/PITCHME.yaml b/lecture05/presentation/PITCHME.yaml index 88e9885f8b..97d63e137f 100644 --- a/lecture05/presentation/PITCHME.yaml +++ b/lecture05/presentation/PITCHME.yaml @@ -1,3 +1,3 @@ -theme-override : lecture05/presentation/assets/css/PITCHME.css -logo : lecture05/presentation/assets/img/atom.png +theme-override : lecture02/presentation/assets/css/PITCHME.css +logo : lecture01/presentation/assets/img/sphere.png slide-number: true From efdb6c62a24d46668100987ef8c9f1a3cf043c3f Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Tue, 20 Mar 2018 22:33:54 +0300 Subject: [PATCH 06/89] presentation --- lecture05/presentation/PITCHME.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lecture05/presentation/PITCHME.md b/lecture05/presentation/PITCHME.md index d30616eac2..e635f9ea81 100644 --- a/lecture05/presentation/PITCHME.md +++ b/lecture05/presentation/PITCHME.md @@ -1,8 +1,8 @@ --- # Java -lecture 5 +2018/lecture 5 ## Spring, Threads, Annotations -2018 + --- From 25ee1b6307a7476a8d1789ba468caf79855a53b3 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Tue, 20 Mar 2018 22:34:32 +0300 Subject: [PATCH 07/89] presentation --- lecture05/presentation/PITCHME.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lecture05/presentation/PITCHME.md b/lecture05/presentation/PITCHME.md index e635f9ea81..a10a036d1f 100644 --- a/lecture05/presentation/PITCHME.md +++ b/lecture05/presentation/PITCHME.md @@ -7,7 +7,7 @@ --- ## Отметьтесь на портале -https://atom.mail.ru/ +https://sphere.mail.ru/ --- From 1641cd5278c229fdc643578d275247161f4892ef Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Wed, 21 Mar 2018 14:18:33 +0300 Subject: [PATCH 08/89] practice --- lecture05/build.gradle | 1 + lecture05/presentation/PITCHME.md | 151 +++++++----------- .../atom/annotation/AnnotationDemoTest.java | 9 +- 3 files changed, 67 insertions(+), 94 deletions(-) diff --git a/lecture05/build.gradle b/lecture05/build.gradle index 898ad8eb59..1795023d2a 100644 --- a/lecture05/build.gradle +++ b/lecture05/build.gradle @@ -8,6 +8,7 @@ repositories { apply plugin: 'java' apply plugin: 'checkstyle' +apply plugin: 'project-report' dependencies { // https://mvnrepository.com/artifact/org.slf4j/slf4j-api diff --git a/lecture05/presentation/PITCHME.md b/lecture05/presentation/PITCHME.md index a10a036d1f..a0d8454e71 100644 --- a/lecture05/presentation/PITCHME.md +++ b/lecture05/presentation/PITCHME.md @@ -22,29 +22,23 @@ https://sphere.mail.ru/ Refresh gradle project ---- -### Поиграем в web-server -Any questions on HTTP? - -**You must understand HTTP!** - - --- ### Agenda 1. Threads 1. Annotations +1. Spring, Spring Boot +1. Inversion of Control, Dependency Injection +1. Beans, ApplicationContext 1. Match-maker -1. HTTP Web Server -1. Spring - --- -### Threads +### Agenda 1. **[Threads]** 1. Annotations +1. Spring, Spring Boot +1. Inversion of Control, Dependency Injection +1. Beans, ApplicationContext 1. Match-maker -1. HTTP Web Server -1. Spring --- ### Threads intro @@ -198,11 +192,12 @@ interface BlockingQueue implements java.util.Queue { --- -### Annotations +### Agenda 1. Threads 1. **[Annotations]** -1. HTTP Web Server -1. Spring +1. Spring, Spring Boot +1. Inversion of Control, Dependency Injection +1. Beans, ApplicationContext 1. Match-maker @@ -229,80 +224,12 @@ in application runtime. --- -### HTTP Web Server -1. Threads -1. Annotations -1. **[HTTP Web Server]** -1. Spring -1. Match-maker - - ---- -### Web server -**Web server** - is a program that processes HTTP Requests and provide HTTP responses. - -**Web server can be a separate application, like:** -- Apache HTTP Server -- NGINX - -**Can be embedded into application:** -- Jetty -- Embedded Tomcat (**our choice**) - - ---- -### Alternative - application servers -Alternatively large projects can use **Application Servers** to manage web application: - - Sun GlassFish - - IBM WebSphere - - RedHat JBoss - -**We will not go this way** - ---- -### Servlet container -Basic function of web server - to serve static content (html, css, images) -But most web servers provide some functionality to apply **custom logic on HTTP Request** and return **custom HTTP Response**. - -This can be used to serve dynamic pages or for custom **web application** (that's how we will use it) - -Custom server logic in java can be embedded into **servlet container** (part of web-server, that manages **Servlets**) - - ---- -### Servlet -servlet - ---- -### Servlet -**Servlet** - is class that handles HTTP Requests. -Java provide low-level **Servlet API** - ---- -### Web Server approximate behavior -1. Start -1. Initialize internal servlets -1. Create a "mapping" **(request, /path)** -> handling servlet -1. Apply mapping on incoming request -1. Process **single request in single thread** but in parallel* -1. Process routing of outgoing response - - ---- -### Modern way -**Servlet API** (a part of java API) - is low-level API -People tend to use high-level frameworks to make web applications -This frameworks use servlet API under the hood - -The most famous web framework is **Spring** - - ---- -### Spring +### Agenda 1. Threads 1. Annotations -1. HTTP Web Server -1. **[Spring]** +1. **[Spring, Spring Boot]** +1. Inversion of Control, Dependency Injection +1. Beans, ApplicationContext 1. Match-maker @@ -357,8 +284,8 @@ First version: **2014** **@See ru.atom.boot.hw** All the magic works via **annotations** -1. Application entry point (HelloSpringBoot) -*@SpringBootApplication* auto-configures spring application +1. Application entry point (HelloSpring Boot) +*@Spring BootApplication* auto-configures spring application 1. Request controller - handles HTTP connections *@Controller* - let Spring recognize this class *@RequestMapping("hello")* - this class handles **HTTP Requests** to **/hello** url @@ -374,6 +301,50 @@ These notes are important to understand: Here comes **multi-threading** with **shared memory** (concurrency) - topic for further discussion + +1. Inversion of Control, Dependency Injection + +--- + +### Agenda +1. Threads +1. Annotations +1. Spring, Spring Boot +1. **[Inversion of Control, Dependency Injection]** +1. Beans, ApplicationContext +1. Match-maker + +--- + +### Inversion of Control + + +--- + +### Spring provides IoC container + +https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans + +--- + +### Agenda +1. Threads +1. Annotations +1. Spring, Spring Boot +1. Inversion of Control, Dependency Injection +1. **[Beans, ApplicationContext]** +1. Match-maker + +--- + +### Agenda +1. Threads +1. Annotations +1. Spring, Spring Boot +1. Inversion of Control, Dependency Injection +1. Beans, ApplicationContext +1. **[Match-maker]** + --- ### Match-maker practice @See ru.atom.thread.mm and tests diff --git a/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java b/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java index ff7ca325f6..e4e2a30bcb 100644 --- a/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java +++ b/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java @@ -3,6 +3,7 @@ import org.junit.Test; import org.springframework.web.bind.annotation.ResponseStatus; +import static junit.framework.TestCase.assertEquals; import static org.assertj.core.api.Assertions.assertThat; @@ -10,13 +11,13 @@ public class AnnotationDemoTest { @Test public void countOverride() throws Exception { - assertThat(AnnotationDemo.getNumberOfAnnotatedMethods( - ru.atom.boot.mm.ConnectionController.class, Override.class)).isEqualTo(0); + assertEquals(0, AnnotationDemo.getNumberOfAnnotatedMethods( + ru.atom.boot.mm.ConnectionController.class, Override.class)); } @Test public void countResponseStatus() throws Exception { - assertThat(AnnotationDemo.getNumberOfAnnotatedMethods( - ru.atom.boot.mm.ConnectionController.class, ResponseStatus.class)).isEqualTo(1); + assertEquals(1, AnnotationDemo.getNumberOfAnnotatedMethods( + ru.atom.boot.mm.ConnectionController.class, ResponseStatus.class)); } } From 9e1b4c8ce144cc2b86530eac6eb96fb3422772ba Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Wed, 21 Mar 2018 15:29:53 +0300 Subject: [PATCH 09/89] presentation --- lecture05/presentation/PITCHME.md | 80 ++++++++++++++++++- .../src/main/resources/application.properties | 2 + 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/lecture05/presentation/PITCHME.md b/lecture05/presentation/PITCHME.md index a0d8454e71..181527626e 100644 --- a/lecture05/presentation/PITCHME.md +++ b/lecture05/presentation/PITCHME.md @@ -306,6 +306,38 @@ Here comes **multi-threading** with **shared memory** (concurrency) - topic for --- +### Spring boot actuator +Spring boot actuator - usefool dependency, providing web interface to meta data of application and even interact with it +**Actuator endpoints:** +https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html +By default most endpoints are disabled. To enable them we need to enable them in **application.properties** + +### application.properties +The standard way to configure java application - **application.properties** should appear in classpath +To enable actuator endpoints: +```properties +management.endpoints.web.exposure.include=* +``` +We also can configure actuator and server ports there: +```properties +#server port: +server.port = 8080 +#actuator port: +management.server.port = 7001 +``` + +--- +### Useful actuator endpoints +**/actuator/health** +overall application status + +**/actuator/mappings** +available mappings + +**/actuator/beans** +all beans in context +--- + ### Agenda 1. Threads 1. Annotations @@ -317,13 +349,59 @@ Here comes **multi-threading** with **shared memory** (concurrency) - topic for --- ### Inversion of Control +**Principle:** control flow is transferred to external framework +**Why:** decoupling, low-connectivity, easier to test + +--- +### Dependency Injection +Objects lifecycle is managed by external framework +- instantiation +- wiring +- removal --- ### Spring provides IoC container +https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans +Interface of IoC Container in Spring: +**org.springframework.context.ApplicationContext** +It provides interface for accessing beans by name and type as far as basic functionality for + +--- + +### Beans +Beans are java objects, that are managed by **IoC Container** +How to make **bean** out of **POJO** (Plain Old Java Object)? +With configuration + +--- +### Spring configuration +There are several options for beans configuration: +- XML Description +- Groovy Description +- Annotations + +We will use annotations as this is the cleanest one + +--- + +### Beans Detection +For spring to create and manage beans, we must provide bean definitions +How to create bean definition with annotations: +- mark class with **@Configuration**/**@Component**/**@Controller**/**@Service**/**@Repository** or annotations, inheriting their semantics +- mark any method inside such class with **@Bean** (config method) + +--- + +### Beans autowiring +Once we have beans definitions, we can inject those beans with **@Autowired** +Possible targets: +- constructor +- field +- setter method +- config method -https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans --- diff --git a/lecture05/src/main/resources/application.properties b/lecture05/src/main/resources/application.properties index d4efc55086..591936dd85 100644 --- a/lecture05/src/main/resources/application.properties +++ b/lecture05/src/main/resources/application.properties @@ -1,3 +1,5 @@ +#server port: server.port = 8080 +#actuator port: management.server.port = 7001 management.endpoints.web.exposure.include=* \ No newline at end of file From 46c6d9563e9023197e2d7fbd0d5a0453ca60d260 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Wed, 21 Mar 2018 16:21:05 +0300 Subject: [PATCH 10/89] presentatino and practice --- lecture05/build.gradle | 1 - lecture05/presentation/PITCHME.md | 72 +++++++++---------- .../ru/atom/{boot => }/mm/MatchMakerApp.java | 7 +- .../controller}/ConnectionController.java | 11 +-- .../mm => mm/controller}/GameController.java | 10 ++- .../{thread/mm => mm/model}/Connection.java | 2 +- .../{thread/mm => mm/model}/GameSession.java | 3 +- .../mm => mm/service}/ConnectionProducer.java | 12 +++- .../ru/atom/mm/service/ConnectionQueue.java | 19 +++++ .../ru/atom/mm/service/GameRepository.java | 23 ++++++ .../{thread/mm => mm/service}/MatchMaker.java | 23 +++++- .../ru/atom/thread/mm/ConnectionQueue.java | 15 ---- .../ru/atom/thread/mm/GameRepository.java | 19 ----- .../atom/annotation/AnnotationDemoTest.java | 5 +- .../ConnectionControllerIntegrationTest.java | 2 +- .../mm/ConnectionControllerTest.java | 3 +- .../{boot => }/mm/GameControllerTest.java | 2 +- .../mm/GamesControllerIntegrationTest.java | 2 +- .../atom/{thread => }/mm/MatchMakerTest.java | 4 +- 19 files changed, 137 insertions(+), 98 deletions(-) rename lecture05/src/main/java/ru/atom/{boot => }/mm/MatchMakerApp.java (61%) rename lecture05/src/main/java/ru/atom/{boot/mm => mm/controller}/ConnectionController.java (82%) rename lecture05/src/main/java/ru/atom/{boot/mm => mm/controller}/GameController.java (77%) rename lecture05/src/main/java/ru/atom/{thread/mm => mm/model}/Connection.java (95%) rename lecture05/src/main/java/ru/atom/{thread/mm => mm/model}/GameSession.java (93%) rename lecture05/src/main/java/ru/atom/{thread/mm => mm/service}/ConnectionProducer.java (70%) create mode 100644 lecture05/src/main/java/ru/atom/mm/service/ConnectionQueue.java create mode 100644 lecture05/src/main/java/ru/atom/mm/service/GameRepository.java rename lecture05/src/main/java/ru/atom/{thread/mm => mm/service}/MatchMaker.java (61%) delete mode 100644 lecture05/src/main/java/ru/atom/thread/mm/ConnectionQueue.java delete mode 100644 lecture05/src/main/java/ru/atom/thread/mm/GameRepository.java rename lecture05/src/test/java/ru/atom/{boot => }/mm/ConnectionControllerIntegrationTest.java (97%) rename lecture05/src/test/java/ru/atom/{boot => }/mm/ConnectionControllerTest.java (91%) rename lecture05/src/test/java/ru/atom/{boot => }/mm/GameControllerTest.java (90%) rename lecture05/src/test/java/ru/atom/{boot => }/mm/GamesControllerIntegrationTest.java (88%) rename lecture05/src/test/java/ru/atom/{thread => }/mm/MatchMakerTest.java (92%) diff --git a/lecture05/build.gradle b/lecture05/build.gradle index 1795023d2a..898ad8eb59 100644 --- a/lecture05/build.gradle +++ b/lecture05/build.gradle @@ -8,7 +8,6 @@ repositories { apply plugin: 'java' apply plugin: 'checkstyle' -apply plugin: 'project-report' dependencies { // https://mvnrepository.com/artifact/org.slf4j/slf4j-api diff --git a/lecture05/presentation/PITCHME.md b/lecture05/presentation/PITCHME.md index 181527626e..bb8a444edd 100644 --- a/lecture05/presentation/PITCHME.md +++ b/lecture05/presentation/PITCHME.md @@ -203,7 +203,7 @@ interface BlockingQueue implements java.util.Queue { --- ### Annotations -What annotations did you see before? +Which annotations did you see before? --- @@ -222,6 +222,11 @@ in application runtime. @See ru.atom.annotation and tests +--- +### Retention policy +Annotation has **Retention policy**, which indicated, whether info about the annotation will be available at runtime +**RetentionPolicy.RUNTIME** guarantees that annotation will be available in **runtime** + --- ### Agenda @@ -253,18 +258,6 @@ It includes a number of modules for different functionality: Today we will build web application with **Spring MVC** module ---- -### MVC -**MVC (Model-View-Controller)** - popular pattern used to build web apps - - - ---- -### Spring MVC -**Spring MVC** - Spring Module that make it easier to build MVC Applications (Like **Django**, **Rails**) -exception - - --- ### Spring Boot Spring is a powerful tool and has a lot of configuration options. @@ -280,29 +273,13 @@ First version: **2014** --- -### Hello Spring Boot -**@See ru.atom.boot.hw** -All the magic works via **annotations** - -1. Application entry point (HelloSpring Boot) -*@Spring BootApplication* auto-configures spring application -1. Request controller - handles HTTP connections -*@Controller* - let Spring recognize this class -*@RequestMapping("hello")* - this class handles **HTTP Requests** to **/hello** url -*@RequestMapping("world")* - this method handles **HTTP Requests** to **/hello/world** url -*@ResponseBody* method returns result will be the **HTTP response body** - - ---- -### Important notes -These notes are important to understand: -1. HelloController is **Singleton** (by default) - the same instance for all requests -1. Every request runs in **new thread** (actually backed by thread pool) - -Here comes **multi-threading** with **shared memory** (concurrency) - topic for further discussion - - -1. Inversion of Control, Dependency Injection +### Spring boot distribution +```groovy + // dependencies, necessary for building generic web applicaitons + compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.0.RELEASE' + // actuator + compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator', version: '2.0.0.RELEASE' +``` --- @@ -371,6 +348,7 @@ It provides interface for accessing beans by name and type as far as basic funct --- ### Beans +https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-definition Beans are java objects, that are managed by **IoC Container** How to make **bean** out of **POJO** (Plain Old Java Object)? With configuration @@ -402,6 +380,28 @@ Possible targets: - setter method - config method +--- + +## ByType and ByName autowiring + +```java + +``` + +How do spring know + +--- + +### Bean scopes +https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-scopes +Beans can have different life span depending on requirements. + +**[Common scopes:]** +- Singleton (default) +- Prototype: single bean definition to any number of object instances +- request: single bean definition to the lifecycle of a single HTTP reques +- websocket: single bean definition to the lifecycle of a WebSocket +... --- diff --git a/lecture05/src/main/java/ru/atom/boot/mm/MatchMakerApp.java b/lecture05/src/main/java/ru/atom/mm/MatchMakerApp.java similarity index 61% rename from lecture05/src/main/java/ru/atom/boot/mm/MatchMakerApp.java rename to lecture05/src/main/java/ru/atom/mm/MatchMakerApp.java index 8fc383f323..57cc119384 100644 --- a/lecture05/src/main/java/ru/atom/boot/mm/MatchMakerApp.java +++ b/lecture05/src/main/java/ru/atom/mm/MatchMakerApp.java @@ -1,17 +1,12 @@ -package ru.atom.boot.mm; +package ru.atom.mm; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import ru.atom.thread.mm.MatchMaker; @SpringBootApplication public class MatchMakerApp { public static void main(String[] args) throws Exception { SpringApplication.run(MatchMakerApp.class, args); - - Thread matchMaker = new Thread(new MatchMaker()); - matchMaker.setName("match-maker"); - matchMaker.start(); } } diff --git a/lecture05/src/main/java/ru/atom/boot/mm/ConnectionController.java b/lecture05/src/main/java/ru/atom/mm/controller/ConnectionController.java similarity index 82% rename from lecture05/src/main/java/ru/atom/boot/mm/ConnectionController.java rename to lecture05/src/main/java/ru/atom/mm/controller/ConnectionController.java index aaccdae8ad..84ee7ff1c3 100644 --- a/lecture05/src/main/java/ru/atom/boot/mm/ConnectionController.java +++ b/lecture05/src/main/java/ru/atom/mm/controller/ConnectionController.java @@ -1,8 +1,9 @@ -package ru.atom.boot.mm; +package ru.atom.mm.controller; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; @@ -10,8 +11,8 @@ import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; -import ru.atom.thread.mm.Connection; -import ru.atom.thread.mm.ConnectionQueue; +import ru.atom.mm.model.Connection; +import ru.atom.mm.service.ConnectionQueue; @Controller @@ -19,6 +20,8 @@ public class ConnectionController { private static final Logger log = LogManager.getLogger(ConnectionController.class); + @Autowired + private ConnectionQueue connectionQueue; /** * curl test @@ -35,7 +38,7 @@ public void connect(@RequestParam("id") long id, @RequestParam("name") String name) { log.info("New connection id={} name={}", id, name); - ConnectionQueue.getInstance().offer(new Connection(id, name)); + connectionQueue.getQueue().offer(new Connection(id, name)); } /** diff --git a/lecture05/src/main/java/ru/atom/boot/mm/GameController.java b/lecture05/src/main/java/ru/atom/mm/controller/GameController.java similarity index 77% rename from lecture05/src/main/java/ru/atom/boot/mm/GameController.java rename to lecture05/src/main/java/ru/atom/mm/controller/GameController.java index 8e131e979a..28d4ec9e55 100644 --- a/lecture05/src/main/java/ru/atom/boot/mm/GameController.java +++ b/lecture05/src/main/java/ru/atom/mm/controller/GameController.java @@ -1,13 +1,14 @@ -package ru.atom.boot.mm; +package ru.atom.mm.controller; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; -import ru.atom.thread.mm.GameRepository; +import ru.atom.mm.service.GameRepository; /** * Created by sergey on 3/15/17. @@ -18,6 +19,9 @@ public class GameController { private static final Logger log = LogManager.getLogger(GameController.class); + @Autowired + private GameRepository gameRepository; + /** * curl test * @@ -30,6 +34,6 @@ public class GameController { @ResponseBody public String list() { log.info("Games list request"); - return GameRepository.getAll().toString(); + return gameRepository.getAll().toString(); } } diff --git a/lecture05/src/main/java/ru/atom/thread/mm/Connection.java b/lecture05/src/main/java/ru/atom/mm/model/Connection.java similarity index 95% rename from lecture05/src/main/java/ru/atom/thread/mm/Connection.java rename to lecture05/src/main/java/ru/atom/mm/model/Connection.java index 759b3302f7..6a50d1834d 100644 --- a/lecture05/src/main/java/ru/atom/thread/mm/Connection.java +++ b/lecture05/src/main/java/ru/atom/mm/model/Connection.java @@ -1,4 +1,4 @@ -package ru.atom.thread.mm; +package ru.atom.mm.model; /** * Created by sergey on 3/14/17. diff --git a/lecture05/src/main/java/ru/atom/thread/mm/GameSession.java b/lecture05/src/main/java/ru/atom/mm/model/GameSession.java similarity index 93% rename from lecture05/src/main/java/ru/atom/thread/mm/GameSession.java rename to lecture05/src/main/java/ru/atom/mm/model/GameSession.java index 567c153ada..4d2fb74605 100644 --- a/lecture05/src/main/java/ru/atom/thread/mm/GameSession.java +++ b/lecture05/src/main/java/ru/atom/mm/model/GameSession.java @@ -1,7 +1,8 @@ -package ru.atom.thread.mm; +package ru.atom.mm.model; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import ru.atom.mm.service.MatchMaker; import java.util.Arrays; import java.util.concurrent.atomic.AtomicLong; diff --git a/lecture05/src/main/java/ru/atom/thread/mm/ConnectionProducer.java b/lecture05/src/main/java/ru/atom/mm/service/ConnectionProducer.java similarity index 70% rename from lecture05/src/main/java/ru/atom/thread/mm/ConnectionProducer.java rename to lecture05/src/main/java/ru/atom/mm/service/ConnectionProducer.java index 7f5eccacce..09712a8f50 100644 --- a/lecture05/src/main/java/ru/atom/thread/mm/ConnectionProducer.java +++ b/lecture05/src/main/java/ru/atom/mm/service/ConnectionProducer.java @@ -1,25 +1,33 @@ -package ru.atom.thread.mm; +package ru.atom.mm.service; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.atom.mm.model.Connection; import java.util.concurrent.atomic.AtomicLong; /** * Created by sergey on 3/14/17. */ +@Service public class ConnectionProducer implements Runnable { private static final Logger log = LogManager.getLogger(ConnectionProducer.class); private static final String[] names = {"John", "Paul", "George", "Someone else"}; private static AtomicLong id = new AtomicLong(); + @Autowired + private ConnectionQueue connectionQueue; + + @Override public void run() { while (!Thread.currentThread().isInterrupted()) { long newId = id.getAndIncrement(); - ConnectionQueue.getInstance().offer(new Connection(newId, names[(int) (newId % names.length)])); + connectionQueue.getQueue().offer(new Connection(newId, names[(int) (newId % names.length)])); log.info("Connection {} added.", newId); try { Thread.sleep(1_000); diff --git a/lecture05/src/main/java/ru/atom/mm/service/ConnectionQueue.java b/lecture05/src/main/java/ru/atom/mm/service/ConnectionQueue.java new file mode 100644 index 0000000000..b38432ba5b --- /dev/null +++ b/lecture05/src/main/java/ru/atom/mm/service/ConnectionQueue.java @@ -0,0 +1,19 @@ +package ru.atom.mm.service; + +import org.springframework.stereotype.Repository; +import ru.atom.mm.model.Connection; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +/** + * Created by sergey on 3/14/17. + */ +@Repository +public class ConnectionQueue { + private BlockingQueue queue = new LinkedBlockingQueue<>(); + + public BlockingQueue getQueue() { + return queue; + } +} diff --git a/lecture05/src/main/java/ru/atom/mm/service/GameRepository.java b/lecture05/src/main/java/ru/atom/mm/service/GameRepository.java new file mode 100644 index 0000000000..bfdf8b6175 --- /dev/null +++ b/lecture05/src/main/java/ru/atom/mm/service/GameRepository.java @@ -0,0 +1,23 @@ +package ru.atom.mm.service; + +import org.springframework.stereotype.Repository; +import ru.atom.mm.model.GameSession; + +import java.util.Collection; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Created by sergey on 3/15/17. + */ +@Repository +public class GameRepository { + private ConcurrentHashMap map = new ConcurrentHashMap<>(); + + public void put(GameSession session) { + map.put(session.getId(), session); + } + + public Collection getAll() { + return map.values(); + } +} diff --git a/lecture05/src/main/java/ru/atom/thread/mm/MatchMaker.java b/lecture05/src/main/java/ru/atom/mm/service/MatchMaker.java similarity index 61% rename from lecture05/src/main/java/ru/atom/thread/mm/MatchMaker.java rename to lecture05/src/main/java/ru/atom/mm/service/MatchMaker.java index 60bcf27807..2652adb0de 100644 --- a/lecture05/src/main/java/ru/atom/thread/mm/MatchMaker.java +++ b/lecture05/src/main/java/ru/atom/mm/service/MatchMaker.java @@ -1,8 +1,13 @@ -package ru.atom.thread.mm; +package ru.atom.mm.service; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.atom.mm.model.Connection; +import ru.atom.mm.model.GameSession; +import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -10,9 +15,21 @@ /** * Created by sergey on 3/14/17. */ +@Service public class MatchMaker implements Runnable { private static final Logger log = LogManager.getLogger(MatchMaker.class); + @Autowired + private ConnectionQueue connectionQueue; + + @Autowired + private GameRepository gameRepository; + + + @PostConstruct + public void startThread() { + new Thread(this, "match-maker").start(); + } @Override public void run() { @@ -21,7 +38,7 @@ public void run() { while (!Thread.currentThread().isInterrupted()) { try { candidates.add( - ConnectionQueue.getInstance().poll(10_000, TimeUnit.SECONDS) + connectionQueue.getQueue().poll(10_000, TimeUnit.SECONDS) ); } catch (InterruptedException e) { log.warn("Timeout reached"); @@ -30,7 +47,7 @@ public void run() { if (candidates.size() == GameSession.PLAYERS_IN_GAME) { GameSession session = new GameSession(candidates.toArray(new Connection[0])); log.info(session); - GameRepository.put(session); + gameRepository.put(session); candidates.clear(); } } diff --git a/lecture05/src/main/java/ru/atom/thread/mm/ConnectionQueue.java b/lecture05/src/main/java/ru/atom/thread/mm/ConnectionQueue.java deleted file mode 100644 index 1f78b1e4ee..0000000000 --- a/lecture05/src/main/java/ru/atom/thread/mm/ConnectionQueue.java +++ /dev/null @@ -1,15 +0,0 @@ -package ru.atom.thread.mm; - -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -/** - * Created by sergey on 3/14/17. - */ -public class ConnectionQueue { - private static BlockingQueue instance = new LinkedBlockingQueue<>(); - - public static BlockingQueue getInstance() { - return instance; - } -} diff --git a/lecture05/src/main/java/ru/atom/thread/mm/GameRepository.java b/lecture05/src/main/java/ru/atom/thread/mm/GameRepository.java deleted file mode 100644 index 0266bede2b..0000000000 --- a/lecture05/src/main/java/ru/atom/thread/mm/GameRepository.java +++ /dev/null @@ -1,19 +0,0 @@ -package ru.atom.thread.mm; - -import java.util.Collection; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Created by sergey on 3/15/17. - */ -public class GameRepository { - private static ConcurrentHashMap map = new ConcurrentHashMap<>(); - - public static void put(GameSession session) { - map.put(session.getId(), session); - } - - public static Collection getAll() { - return map.values(); - } -} diff --git a/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java b/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java index e4e2a30bcb..32863622ca 100644 --- a/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java +++ b/lecture05/src/test/java/ru/atom/annotation/AnnotationDemoTest.java @@ -2,6 +2,7 @@ import org.junit.Test; import org.springframework.web.bind.annotation.ResponseStatus; +import ru.atom.mm.controller.ConnectionController; import static junit.framework.TestCase.assertEquals; import static org.assertj.core.api.Assertions.assertThat; @@ -12,12 +13,12 @@ public class AnnotationDemoTest { @Test public void countOverride() throws Exception { assertEquals(0, AnnotationDemo.getNumberOfAnnotatedMethods( - ru.atom.boot.mm.ConnectionController.class, Override.class)); + ConnectionController.class, Override.class)); } @Test public void countResponseStatus() throws Exception { assertEquals(1, AnnotationDemo.getNumberOfAnnotatedMethods( - ru.atom.boot.mm.ConnectionController.class, ResponseStatus.class)); + ConnectionController.class, ResponseStatus.class)); } } diff --git a/lecture05/src/test/java/ru/atom/boot/mm/ConnectionControllerIntegrationTest.java b/lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java similarity index 97% rename from lecture05/src/test/java/ru/atom/boot/mm/ConnectionControllerIntegrationTest.java rename to lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java index cede5d0169..ec09967551 100644 --- a/lecture05/src/test/java/ru/atom/boot/mm/ConnectionControllerIntegrationTest.java +++ b/lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java @@ -1,4 +1,4 @@ -package ru.atom.boot.mm; +package ru.atom.mm; import org.junit.Ignore; import org.junit.Test; diff --git a/lecture05/src/test/java/ru/atom/boot/mm/ConnectionControllerTest.java b/lecture05/src/test/java/ru/atom/mm/ConnectionControllerTest.java similarity index 91% rename from lecture05/src/test/java/ru/atom/boot/mm/ConnectionControllerTest.java rename to lecture05/src/test/java/ru/atom/mm/ConnectionControllerTest.java index 11cc769e31..2222e9ab9b 100644 --- a/lecture05/src/test/java/ru/atom/boot/mm/ConnectionControllerTest.java +++ b/lecture05/src/test/java/ru/atom/mm/ConnectionControllerTest.java @@ -1,7 +1,8 @@ -package ru.atom.boot.mm; +package ru.atom.mm; import org.junit.Ignore; import org.junit.Test; +import ru.atom.mm.controller.ConnectionController; import static org.assertj.core.api.Java6Assertions.assertThat; import static org.junit.Assert.assertFalse; diff --git a/lecture05/src/test/java/ru/atom/boot/mm/GameControllerTest.java b/lecture05/src/test/java/ru/atom/mm/GameControllerTest.java similarity index 90% rename from lecture05/src/test/java/ru/atom/boot/mm/GameControllerTest.java rename to lecture05/src/test/java/ru/atom/mm/GameControllerTest.java index f915742de8..422e6e26cd 100644 --- a/lecture05/src/test/java/ru/atom/boot/mm/GameControllerTest.java +++ b/lecture05/src/test/java/ru/atom/mm/GameControllerTest.java @@ -1,4 +1,4 @@ -package ru.atom.boot.mm; +package ru.atom.mm; import org.junit.Ignore; import org.junit.Test; diff --git a/lecture05/src/test/java/ru/atom/boot/mm/GamesControllerIntegrationTest.java b/lecture05/src/test/java/ru/atom/mm/GamesControllerIntegrationTest.java similarity index 88% rename from lecture05/src/test/java/ru/atom/boot/mm/GamesControllerIntegrationTest.java rename to lecture05/src/test/java/ru/atom/mm/GamesControllerIntegrationTest.java index bdfa86485e..8f61bfd56e 100644 --- a/lecture05/src/test/java/ru/atom/boot/mm/GamesControllerIntegrationTest.java +++ b/lecture05/src/test/java/ru/atom/mm/GamesControllerIntegrationTest.java @@ -1,4 +1,4 @@ -package ru.atom.boot.mm; +package ru.atom.mm; import org.junit.Ignore; import org.junit.Test; diff --git a/lecture05/src/test/java/ru/atom/thread/mm/MatchMakerTest.java b/lecture05/src/test/java/ru/atom/mm/MatchMakerTest.java similarity index 92% rename from lecture05/src/test/java/ru/atom/thread/mm/MatchMakerTest.java rename to lecture05/src/test/java/ru/atom/mm/MatchMakerTest.java index 86de6eeaf8..fa8254a440 100644 --- a/lecture05/src/test/java/ru/atom/thread/mm/MatchMakerTest.java +++ b/lecture05/src/test/java/ru/atom/mm/MatchMakerTest.java @@ -1,7 +1,9 @@ -package ru.atom.thread.mm; +package ru.atom.mm; import org.junit.Ignore; import org.junit.Test; +import ru.atom.mm.service.ConnectionProducer; +import ru.atom.mm.service.MatchMaker; import java.util.ArrayList; import java.util.List; From 7815ffa121d71b1f159713c8dfefe0dcda293282 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Wed, 21 Mar 2018 16:36:46 +0300 Subject: [PATCH 11/89] logger fixes --- .../java/ru/atom/mm/controller/ConnectionController.java | 7 ++++--- .../main/java/ru/atom/mm/controller/GameController.java | 8 +++++--- .../src/main/java/ru/atom/mm/model/GameSession.java | 9 +++++---- .../main/java/ru/atom/mm/service/ConnectionProducer.java | 6 +++--- .../src/main/java/ru/atom/mm/service/MatchMaker.java | 9 +++++---- .../atom/thread/instantiation/NotifierExtendsThread.java | 7 ++++--- .../thread/instantiation/NotifierImplementsRunnable.java | 6 +++--- lecture05/src/main/java/ru/atom/thread/join/Bomb.java | 9 +++++---- 8 files changed, 34 insertions(+), 27 deletions(-) diff --git a/lecture05/src/main/java/ru/atom/mm/controller/ConnectionController.java b/lecture05/src/main/java/ru/atom/mm/controller/ConnectionController.java index 84ee7ff1c3..17cf04d52a 100644 --- a/lecture05/src/main/java/ru/atom/mm/controller/ConnectionController.java +++ b/lecture05/src/main/java/ru/atom/mm/controller/ConnectionController.java @@ -1,8 +1,8 @@ package ru.atom.mm.controller; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -18,7 +18,8 @@ @Controller @RequestMapping("/connection") public class ConnectionController { - private static final Logger log = LogManager.getLogger(ConnectionController.class); + private static final Logger log = LoggerFactory.getLogger(ConnectionController.class); + @Autowired private ConnectionQueue connectionQueue; diff --git a/lecture05/src/main/java/ru/atom/mm/controller/GameController.java b/lecture05/src/main/java/ru/atom/mm/controller/GameController.java index 28d4ec9e55..4e1e3f2bbc 100644 --- a/lecture05/src/main/java/ru/atom/mm/controller/GameController.java +++ b/lecture05/src/main/java/ru/atom/mm/controller/GameController.java @@ -1,13 +1,14 @@ package ru.atom.mm.controller; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; +import ru.atom.mm.service.ConnectionProducer; import ru.atom.mm.service.GameRepository; /** @@ -17,7 +18,8 @@ @Controller @RequestMapping("/game") public class GameController { - private static final Logger log = LogManager.getLogger(GameController.class); + private static final Logger log = LoggerFactory.getLogger(GameController.class); + @Autowired private GameRepository gameRepository; diff --git a/lecture05/src/main/java/ru/atom/mm/model/GameSession.java b/lecture05/src/main/java/ru/atom/mm/model/GameSession.java index 4d2fb74605..efa0ea2c86 100644 --- a/lecture05/src/main/java/ru/atom/mm/model/GameSession.java +++ b/lecture05/src/main/java/ru/atom/mm/model/GameSession.java @@ -1,8 +1,8 @@ package ru.atom.mm.model; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import ru.atom.mm.service.MatchMaker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import ru.atom.mm.service.ConnectionProducer; import java.util.Arrays; import java.util.concurrent.atomic.AtomicLong; @@ -11,7 +11,8 @@ * Created by sergey on 3/14/17. */ public class GameSession { - private static final Logger log = LogManager.getLogger(MatchMaker.class); + private static final Logger log = LoggerFactory.getLogger(GameSession.class); + private static AtomicLong idGenerator = new AtomicLong(); public static final int PLAYERS_IN_GAME = 4; diff --git a/lecture05/src/main/java/ru/atom/mm/service/ConnectionProducer.java b/lecture05/src/main/java/ru/atom/mm/service/ConnectionProducer.java index 09712a8f50..33c604032e 100644 --- a/lecture05/src/main/java/ru/atom/mm/service/ConnectionProducer.java +++ b/lecture05/src/main/java/ru/atom/mm/service/ConnectionProducer.java @@ -1,7 +1,7 @@ package ru.atom.mm.service; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import ru.atom.mm.model.Connection; @@ -13,7 +13,7 @@ */ @Service public class ConnectionProducer implements Runnable { - private static final Logger log = LogManager.getLogger(ConnectionProducer.class); + private static final Logger log = LoggerFactory.getLogger(ConnectionProducer.class); private static final String[] names = {"John", "Paul", "George", "Someone else"}; private static AtomicLong id = new AtomicLong(); diff --git a/lecture05/src/main/java/ru/atom/mm/service/MatchMaker.java b/lecture05/src/main/java/ru/atom/mm/service/MatchMaker.java index 2652adb0de..03d2980ea8 100644 --- a/lecture05/src/main/java/ru/atom/mm/service/MatchMaker.java +++ b/lecture05/src/main/java/ru/atom/mm/service/MatchMaker.java @@ -1,7 +1,7 @@ package ru.atom.mm.service; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import ru.atom.mm.model.Connection; @@ -17,7 +17,8 @@ */ @Service public class MatchMaker implements Runnable { - private static final Logger log = LogManager.getLogger(MatchMaker.class); + private static final Logger log = LoggerFactory.getLogger(MatchMaker.class); + @Autowired private ConnectionQueue connectionQueue; @@ -46,7 +47,7 @@ public void run() { if (candidates.size() == GameSession.PLAYERS_IN_GAME) { GameSession session = new GameSession(candidates.toArray(new Connection[0])); - log.info(session); + log.info(session.toString()); gameRepository.put(session); candidates.clear(); } diff --git a/lecture05/src/main/java/ru/atom/thread/instantiation/NotifierExtendsThread.java b/lecture05/src/main/java/ru/atom/thread/instantiation/NotifierExtendsThread.java index aea5917227..f345718371 100644 --- a/lecture05/src/main/java/ru/atom/thread/instantiation/NotifierExtendsThread.java +++ b/lecture05/src/main/java/ru/atom/thread/instantiation/NotifierExtendsThread.java @@ -1,13 +1,14 @@ package ru.atom.thread.instantiation; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.LoggerFactory; +import ru.atom.mm.service.ConnectionProducer; /** * Created by sergey on 3/14/17. */ public class NotifierExtendsThread extends Thread { - private static final Logger log = LogManager.getLogger(NotifierExtendsThread.class); + private static final org.slf4j.Logger log = LoggerFactory.getLogger(NotifierExtendsThread.class); + @Override public void run() { diff --git a/lecture05/src/main/java/ru/atom/thread/instantiation/NotifierImplementsRunnable.java b/lecture05/src/main/java/ru/atom/thread/instantiation/NotifierImplementsRunnable.java index 530b040258..728cf2886c 100644 --- a/lecture05/src/main/java/ru/atom/thread/instantiation/NotifierImplementsRunnable.java +++ b/lecture05/src/main/java/ru/atom/thread/instantiation/NotifierImplementsRunnable.java @@ -1,13 +1,13 @@ package ru.atom.thread.instantiation; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.LoggerFactory; /** * Created by sergey on 3/14/17. */ public class NotifierImplementsRunnable implements Runnable { - private static final Logger log = LogManager.getLogger(NotifierImplementsRunnable.class); + private static final org.slf4j.Logger log = LoggerFactory.getLogger(NotifierImplementsRunnable.class); + @Override public void run() { diff --git a/lecture05/src/main/java/ru/atom/thread/join/Bomb.java b/lecture05/src/main/java/ru/atom/thread/join/Bomb.java index c78fba368c..76142f01e9 100644 --- a/lecture05/src/main/java/ru/atom/thread/join/Bomb.java +++ b/lecture05/src/main/java/ru/atom/thread/join/Bomb.java @@ -1,13 +1,14 @@ package ru.atom.thread.join; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; +import org.slf4j.LoggerFactory; +import ru.atom.thread.instantiation.NotifierExtendsThread; /** * Created by sergey on 3/14/17. */ public class Bomb implements Runnable { - private static final Logger log = LogManager.getLogger(Bomb.class); + private static final org.slf4j.Logger log = LoggerFactory.getLogger(Bomb.class); + private int countdownFrom; @@ -21,7 +22,7 @@ public void run() { while (!Thread.currentThread().isInterrupted() && countdownFrom > 0) { - log.info(countdownFrom); + log.info(String.valueOf(countdownFrom)); countdownFrom--; try { From 6a69cf0cee4d307f0901c6f6412f9bad5b0afc5b Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Wed, 21 Mar 2018 16:44:25 +0300 Subject: [PATCH 12/89] presentation fixes --- lecture05/presentation/PITCHME.md | 15 ++++++++++----- .../src/test/java/ru/atom/mm/MatchMakerTest.java | 4 ++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lecture05/presentation/PITCHME.md b/lecture05/presentation/PITCHME.md index bb8a444edd..128d00b745 100644 --- a/lecture05/presentation/PITCHME.md +++ b/lecture05/presentation/PITCHME.md @@ -289,6 +289,8 @@ Spring boot actuator - usefool dependency, providing web interface to meta data https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html By default most endpoints are disabled. To enable them we need to enable them in **application.properties** +--- + ### application.properties The standard way to configure java application - **application.properties** should appear in classpath To enable actuator endpoints: @@ -326,13 +328,13 @@ all beans in context --- ### Inversion of Control -**Principle:** control flow is transferred to external framework -**Why:** decoupling, low-connectivity, easier to test +**Principle:** control flow is transferred to external framework +**Why:** loose coupling, easier to develop, easier to test --- ### Dependency Injection -Objects lifecycle is managed by external framework +Objects lifecycle is managed by external framework (**IoC container**) - instantiation - wiring - removal @@ -341,9 +343,12 @@ Objects lifecycle is managed by external framework ### Spring provides IoC container https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans -Interface of IoC Container in Spring: +Interface of **IoC Container** in Spring: **org.springframework.context.ApplicationContext** -It provides interface for accessing beans by name and type as far as basic functionality for +- methods for accessing application components. Inherited from ListableBeanFactory. +- methods to load file resources in a generic fashion. Inherited from the ResourceLoader interface. +- methods to publish events to registered listeners. Inherited from the ApplicationEventPublisher interface. +- methods to resolve messages, supporting internationalization. Inherited from the MessageSource interface. --- diff --git a/lecture05/src/test/java/ru/atom/mm/MatchMakerTest.java b/lecture05/src/test/java/ru/atom/mm/MatchMakerTest.java index fa8254a440..419fc09658 100644 --- a/lecture05/src/test/java/ru/atom/mm/MatchMakerTest.java +++ b/lecture05/src/test/java/ru/atom/mm/MatchMakerTest.java @@ -2,6 +2,7 @@ import org.junit.Ignore; import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; import ru.atom.mm.service.ConnectionProducer; import ru.atom.mm.service.MatchMaker; @@ -14,6 +15,9 @@ @Ignore public class MatchMakerTest { + @Autowired + ConnectionProducer connectionProducer; + @Test public void singleProducer() throws Exception { Thread connectionProducer = new Thread(new ConnectionProducer()); From ad221edaffed2ba3454abe69e0a9809f59f9c0e4 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Wed, 21 Mar 2018 16:45:50 +0300 Subject: [PATCH 13/89] presentation fixes --- lecture05/presentation/PITCHME.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lecture05/presentation/PITCHME.md b/lecture05/presentation/PITCHME.md index 128d00b745..ea6b81cf38 100644 --- a/lecture05/presentation/PITCHME.md +++ b/lecture05/presentation/PITCHME.md @@ -345,10 +345,10 @@ Objects lifecycle is managed by external framework (**IoC container**) https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans Interface of **IoC Container** in Spring: **org.springframework.context.ApplicationContext** -- methods for accessing application components. Inherited from ListableBeanFactory. -- methods to load file resources in a generic fashion. Inherited from the ResourceLoader interface. -- methods to publish events to registered listeners. Inherited from the ApplicationEventPublisher interface. -- methods to resolve messages, supporting internationalization. Inherited from the MessageSource interface. +- methods for accessing application components. **ListableBeanFactory** +- methods to load file resources in a generic fashion. **ResourceLoader** +- methods to publish events to registered listeners. **ApplicationEventPublisher** +- methods to resolve messages, supporting internationalization. **MessageSource** --- From fa658c97b1ced3cf3495383f49d30b8c5c17e607 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Wed, 21 Mar 2018 16:46:43 +0300 Subject: [PATCH 14/89] presentation fixes --- lecture05/presentation/PITCHME.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lecture05/presentation/PITCHME.md b/lecture05/presentation/PITCHME.md index ea6b81cf38..25ba969040 100644 --- a/lecture05/presentation/PITCHME.md +++ b/lecture05/presentation/PITCHME.md @@ -353,7 +353,7 @@ Interface of **IoC Container** in Spring: --- ### Beans -https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-definition +https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-definition Beans are java objects, that are managed by **IoC Container** How to make **bean** out of **POJO** (Plain Old Java Object)? With configuration @@ -370,8 +370,8 @@ We will use annotations as this is the cleanest one --- ### Beans Detection -For spring to create and manage beans, we must provide bean definitions -How to create bean definition with annotations: +For spring to create and manage beans, we must provide bean definitions +**How to create bean definition with annotations:** - mark class with **@Configuration**/**@Component**/**@Controller**/**@Service**/**@Repository** or annotations, inheriting their semantics - mark any method inside such class with **@Bean** (config method) From 0f0d7975abf7a6d2abfe3216646d0692482189d4 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Wed, 21 Mar 2018 17:00:48 +0300 Subject: [PATCH 15/89] presentation fixes --- lecture05/presentation/PITCHME.md | 39 ++++++++++++------- .../ru/atom/mm/controller/GameController.java | 1 - .../ConnectionControllerIntegrationTest.java | 1 + 3 files changed, 26 insertions(+), 15 deletions(-) diff --git a/lecture05/presentation/PITCHME.md b/lecture05/presentation/PITCHME.md index 25ba969040..cded8df1c7 100644 --- a/lecture05/presentation/PITCHME.md +++ b/lecture05/presentation/PITCHME.md @@ -352,11 +352,22 @@ Interface of **IoC Container** in Spring: --- +### Agenda +1. Threads +1. Annotations +1. Spring, Spring Boot +1. Inversion of Control, Dependency Injection +1. **[Beans, ApplicationContext]** +1. Match-maker + +--- + ### Beans https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-definition Beans are java objects, that are managed by **IoC Container** + How to make **bean** out of **POJO** (Plain Old Java Object)? -With configuration +With bean definition configuration --- ### Spring configuration @@ -378,6 +389,7 @@ For spring to create and manage beans, we must provide bean definitions --- ### Beans autowiring +https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-autowired-annotation Once we have beans definitions, we can inject those beans with **@Autowired** Possible targets: - constructor @@ -388,13 +400,16 @@ Possible targets: --- ## ByType and ByName autowiring - ```java - +@Service +public class MatchMaker implements Runnable { + @Autowired //How do spring know which bean to inject? + private ConnectionQueue connectionQueue; +} ``` - -How do spring know - +- ByType: it will search the bean with type **ConnectionQueue** or implementation in ApplicationContext +- ByName: with **@Qualifier** annotation we can autowire bean by name +https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-autowired-annotation-qualifiers --- ### Bean scopes @@ -410,13 +425,9 @@ Beans can have different life span depending on requirements. --- -### Agenda -1. Threads -1. Annotations -1. Spring, Spring Boot -1. Inversion of Control, Dependency Injection -1. **[Beans, ApplicationContext]** -1. Match-maker +### Spring: see documentation +Both basic concepts and details are fully covered in spring documentation. +https://docs.spring.io/spring/docs/current/spring-framework-reference/index.html --- @@ -430,7 +441,7 @@ Beans can have different life span depending on requirements. --- ### Match-maker practice -@See ru.atom.thread.mm and tests +@See ru.atom.mm and tests --- ### Match-maker diff --git a/lecture05/src/main/java/ru/atom/mm/controller/GameController.java b/lecture05/src/main/java/ru/atom/mm/controller/GameController.java index 4e1e3f2bbc..a38b1f1f6f 100644 --- a/lecture05/src/main/java/ru/atom/mm/controller/GameController.java +++ b/lecture05/src/main/java/ru/atom/mm/controller/GameController.java @@ -8,7 +8,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; -import ru.atom.mm.service.ConnectionProducer; import ru.atom.mm.service.GameRepository; /** diff --git a/lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java b/lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java index ec09967551..705ad8e733 100644 --- a/lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java +++ b/lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java @@ -20,6 +20,7 @@ public class ConnectionControllerIntegrationTest { MockMvc mockMvc; @Test + @Ignore public void connect() throws Exception { mockMvc.perform(post("/connection/connect") .content("id=1&name=a") From 2efd58fce245aa9c05ba41fc5ee4a72bafc16fc0 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Wed, 21 Mar 2018 17:03:22 +0300 Subject: [PATCH 16/89] presentation fixes --- lecture05/presentation/PITCHME.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lecture05/presentation/PITCHME.md b/lecture05/presentation/PITCHME.md index cded8df1c7..af612af526 100644 --- a/lecture05/presentation/PITCHME.md +++ b/lecture05/presentation/PITCHME.md @@ -237,6 +237,13 @@ Annotation has **Retention policy**, which indicated, whether info about the ann 1. Beans, ApplicationContext 1. Match-maker +--- + +### Matchmaker example + +We will use MathMaker application to study basic concepts of Spring + +> @see MatchMakerApp --- ### Spring @@ -285,6 +292,7 @@ First version: **2014** ### Spring boot actuator Spring boot actuator - usefool dependency, providing web interface to meta data of application and even interact with it + **Actuator endpoints:** https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html By default most endpoints are disabled. To enable them we need to enable them in **application.properties** From 17e007505afcf01a53960a93fc98f2446a6f5e82 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Wed, 21 Mar 2018 17:07:10 +0300 Subject: [PATCH 17/89] presentation fixes --- .../src/test/java/ru/atom/thread/practice/EventProcessor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lecture05/src/test/java/ru/atom/thread/practice/EventProcessor.java b/lecture05/src/test/java/ru/atom/thread/practice/EventProcessor.java index 2c292e8800..a748493b85 100644 --- a/lecture05/src/test/java/ru/atom/thread/practice/EventProcessor.java +++ b/lecture05/src/test/java/ru/atom/thread/practice/EventProcessor.java @@ -12,10 +12,10 @@ public static void produceEvents(List eventProducers) { } public static long countTotalNumberOfGoodEvents() { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException();//TODO } public static long countTotalNumberOfBadEvents() { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException();//TODO } } From a0aa95fc180ed6915655a080c1e85c5c128eed7f Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Wed, 21 Mar 2018 17:09:29 +0300 Subject: [PATCH 18/89] practice fixes --- .../src/test/java/ru/atom/thread/practice/EventProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lecture05/src/test/java/ru/atom/thread/practice/EventProcessor.java b/lecture05/src/test/java/ru/atom/thread/practice/EventProcessor.java index a748493b85..5c09da31fb 100644 --- a/lecture05/src/test/java/ru/atom/thread/practice/EventProcessor.java +++ b/lecture05/src/test/java/ru/atom/thread/practice/EventProcessor.java @@ -8,7 +8,7 @@ */ public class EventProcessor { public static void produceEvents(List eventProducers) { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException();//TODO eventProducers here } public static long countTotalNumberOfGoodEvents() { From 206110dec336a65e8eded543bd6b707a914d4741 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Wed, 21 Mar 2018 18:16:34 +0300 Subject: [PATCH 19/89] gradle --- lecture05/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54333 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 +++++ 2 files changed, 5 insertions(+) create mode 100644 lecture05/gradle/wrapper/gradle-wrapper.jar create mode 100644 lecture05/gradle/wrapper/gradle-wrapper.properties diff --git a/lecture05/gradle/wrapper/gradle-wrapper.jar b/lecture05/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..c44b679acd3f794ddbb3aa5e919244914911014a GIT binary patch literal 54333 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
K7|BUm`^7>V&Zk%^_d-%A~k@lFe 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

Qox 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 E17(ftEC2ui literal 0 HcmV?d00001 diff --git a/lecture05/gradle/wrapper/gradle-wrapper.properties b/lecture05/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..568c50bf3a --- /dev/null +++ b/lecture05/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-bin.zip From b1f38864846142c9a18777ae830fee1e6159d41b Mon Sep 17 00:00:00 2001 From: rybalkinsd Date: Wed, 21 Mar 2018 18:24:40 +0300 Subject: [PATCH 20/89] tests --- .../src/test/java/ru/atom/mm/Config.java | 25 +++++++++++++++++++ .../ConnectionControllerIntegrationTest.java | 2 ++ .../ru/atom/mm/ConnectionControllerTest.java | 4 +-- .../java/ru/atom/mm/GameControllerTest.java | 3 +-- .../mm/GamesControllerIntegrationTest.java | 2 +- .../test/java/ru/atom/mm/MatchMakerTest.java | 7 ++++++ 6 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 lecture05/src/test/java/ru/atom/mm/Config.java diff --git a/lecture05/src/test/java/ru/atom/mm/Config.java b/lecture05/src/test/java/ru/atom/mm/Config.java new file mode 100644 index 0000000000..d35fae2c59 --- /dev/null +++ b/lecture05/src/test/java/ru/atom/mm/Config.java @@ -0,0 +1,25 @@ +package ru.atom.mm; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import ru.atom.mm.service.ConnectionProducer; +import ru.atom.mm.service.ConnectionQueue; +import ru.atom.mm.service.GameRepository; + +@TestConfiguration +public class Config { + @Bean + public ConnectionQueue connectionQueue() { + return new ConnectionQueue(); + } + + @Bean + public ConnectionProducer connectionProducer() { + return new ConnectionProducer(); + } + + @Bean + public GameRepository gameRepository() { + return new GameRepository(); + } +} diff --git a/lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java b/lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java index 705ad8e733..b53356ba2d 100644 --- a/lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java +++ b/lecture05/src/test/java/ru/atom/mm/ConnectionControllerIntegrationTest.java @@ -5,6 +5,7 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.context.annotation.Import; import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; @@ -15,6 +16,7 @@ @RunWith(SpringRunner.class) @WebMvcTest +@Import(Config.class) public class ConnectionControllerIntegrationTest { @Autowired MockMvc mockMvc; diff --git a/lecture05/src/test/java/ru/atom/mm/ConnectionControllerTest.java b/lecture05/src/test/java/ru/atom/mm/ConnectionControllerTest.java index 2222e9ab9b..d971dd229a 100644 --- a/lecture05/src/test/java/ru/atom/mm/ConnectionControllerTest.java +++ b/lecture05/src/test/java/ru/atom/mm/ConnectionControllerTest.java @@ -4,14 +4,13 @@ import org.junit.Test; import ru.atom.mm.controller.ConnectionController; -import static org.assertj.core.api.Java6Assertions.assertThat; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +@Ignore public class ConnectionControllerTest { @Test - @Ignore public void connect() throws Exception { ConnectionController connectionHandler = new ConnectionController(); assertTrue(connectionHandler.list().isEmpty()); @@ -24,7 +23,6 @@ public void connect() throws Exception { } @Test - @Ignore public void list() throws Exception { assertTrue(false); } diff --git a/lecture05/src/test/java/ru/atom/mm/GameControllerTest.java b/lecture05/src/test/java/ru/atom/mm/GameControllerTest.java index 422e6e26cd..f0787a0f4f 100644 --- a/lecture05/src/test/java/ru/atom/mm/GameControllerTest.java +++ b/lecture05/src/test/java/ru/atom/mm/GameControllerTest.java @@ -5,11 +5,10 @@ import static org.junit.Assert.assertTrue; - +@Ignore public class GameControllerTest { @Test - @Ignore public void list() throws Exception { assertTrue(false); } diff --git a/lecture05/src/test/java/ru/atom/mm/GamesControllerIntegrationTest.java b/lecture05/src/test/java/ru/atom/mm/GamesControllerIntegrationTest.java index 8f61bfd56e..782a28f6c8 100644 --- a/lecture05/src/test/java/ru/atom/mm/GamesControllerIntegrationTest.java +++ b/lecture05/src/test/java/ru/atom/mm/GamesControllerIntegrationTest.java @@ -6,10 +6,10 @@ /** * Some annotations here */ +@Ignore public class GamesControllerIntegrationTest { @Test - @Ignore public void list() throws Exception { } diff --git a/lecture05/src/test/java/ru/atom/mm/MatchMakerTest.java b/lecture05/src/test/java/ru/atom/mm/MatchMakerTest.java index 419fc09658..9765700d3d 100644 --- a/lecture05/src/test/java/ru/atom/mm/MatchMakerTest.java +++ b/lecture05/src/test/java/ru/atom/mm/MatchMakerTest.java @@ -2,7 +2,11 @@ import org.junit.Ignore; import org.junit.Test; +import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.junit4.SpringRunner; import ru.atom.mm.service.ConnectionProducer; import ru.atom.mm.service.MatchMaker; @@ -13,6 +17,9 @@ * Created by sergey on 3/14/17. */ @Ignore +@RunWith(SpringRunner.class) +@WebMvcTest +@Import(Config.class) public class MatchMakerTest { @Autowired From 380678b3454818d3a842c3c1fd9a9571df566be6 Mon Sep 17 00:00:00 2001 From: Sergey Rybalkin Date: Sat, 24 Mar 2018 19:09:37 +0300 Subject: [PATCH 21/89] Feature/game task (#869) * task: * Update readme11.md * Update readme11.md * Update readme11.md * Create README.md * Update README.md * Add files via upload * Update README.md * Delete readme11.md * Update README.md * Add files via upload * task fixes * update task * corrections --- tasks/bomberman-infrastructure/README.md | 173 ++++++++++++++++++ .../thread_per_request.jpg | Bin 0 -> 40129 bytes tasks/bomberman-infrastructure/top_view.png | Bin 0 -> 97917 bytes 3 files changed, 173 insertions(+) create mode 100644 tasks/bomberman-infrastructure/README.md create mode 100644 tasks/bomberman-infrastructure/thread_per_request.jpg create mode 100644 tasks/bomberman-infrastructure/top_view.png diff --git a/tasks/bomberman-infrastructure/README.md b/tasks/bomberman-infrastructure/README.md new file mode 100644 index 0000000000..1836c41478 --- /dev/null +++ b/tasks/bomberman-infrastructure/README.md @@ -0,0 +1,173 @@ +# Bomberman ifrastructure + +We are going to start our game development. +Now it's a part to create big part of our infrastructure, including landing page logic and, matchmaker. +**game server** will be implemented later + +![](top_view.png) + +API that our user see: + `join(name: String)` + User opens game web page (localhost:8080) and see the landing page (index page) + with the only button [Play] and a text form to enter his nickname. + + + +Under the hood (**Implement this service**): +1. Matchmaker service. + Matchmaker should handle `play` button request from user and provide a valid game session id to the user + User is waiting until Matchmaker will respond with the `game id`. + + Specification + ``` + Protocol: HTTP + Path: matchmaker/join + Method: POST + Host: {IP}:8080 (IP = localhost for local server tests) + Headers: + Content-Type: application/x-www-form-urlencoded + Body: + name={} + Response: + Code: 200 + Сontent-Type: text/plain + Body: game id + ``` + + 1.1) Matchmaker is creating a new games when necessary. + Matchmaker provides same gameId to N client connections(players) + Matchmaking algorithm was described in lectures + + 1.2) Matchmaker saves the info about the game to database: + gameId and all players involved (on game creation) + + Bonus: + + - Monitoring - how many players are in queue and other interesting data + - Matchmaking based on leaderboard + - Start match with not full players in game when have to wait for a long time + +2. Game service (for now it should a stub/mock only) + + API: + ``` + gameId create(playerCount: int): long + + connect(name: String, gameId: long) + + start(gameId: long) + ``` + + Under the hood: + At some point Matchmaker asks Game service to `create` a new game for `playerCount` users. + After that Matchmaker will provide this `gameId` to clients and clients will + `connect` to the exact game using `gameId` and `name` + + At some point Matchmaker starts the game with `gameId`. + In general it should be when number of connected players equals to number of players that should play in one game. + + Specification + ``` + Protocol: HTTP + Path: game/create + Method: POST + Host: {IP}:8090 (IP = localhost for local server tests) + Headers: + Content-Type: application/x-www-form-urlencoded + Body: + playerCount={} + Response: + Code: 200 + Сontent-Type: text/plain + Body: game id + ``` + + ``` + Protocol: HTTP + Path: game/start + Method: POST + Host: {IP}:8090 (IP = localhost for local server tests) + Headers: + Content-Type: application/x-www-form-urlencoded + Body: + gameId={} + Response: + Code: 200 + Сontent-Type: text/plain + Body: game id + ``` + + ``` + Protocol: WS + Path: game/connect?gameId={}&name={} + Host: {IP}:8090 (IP = localhost for local server tests) + + Result: + WS connection established + ``` + + Bonus: + + - Monitoring - how many games were played + - Leaderboard + - Player statistics + + +## Tech Stack: +### Spring & Spring-boot +**[Srping]( @TODO )** - the most popular java framework, web-mvc is a part of it. +**[Spring-boot]( @TODO)** - framework for fast configuration and deployment of java-spring applications. +**[Spring mvc]** - spring implementation of model-view-controller architectural pattern. + +**Spring mvc implements thread per request model** [[link]](http://stackoverflow.com/questions/15217524/what-is-the-difference-between-thread-per-connection-vs-thread-per-request) +Each request will be processed in separate thread. +![](thread_per_request.jpg) + + +## Deadline and HowTo? +- `git checkout -b matchmaker` and work in this branch +- Deadline: **09.04** lecture. +- This is team task (3-2 persons, **single submissions are not aloud**) +- Procedure: + 1. show us PR with green build + 1. show us a demo of your service + 1. show us your tests + 1. get ready for tricky questions + 1. java knowledge will be checked +- Base is **16 points** for this task +- The more features you will develop - the better rank you will get. Try to make the best service you can. +- If you are coping code from anywhere make sure you can explain what's happening. + +## What we will check? +1. Correct implementation +1. Green CI build (checkstyle) +1. Tests quality (both unit and integration with SpringBootTest) +1. Code coverage > 50% +1. Logging +1. Service deployment in docker (without using IDE) + + diff --git a/tasks/bomberman-infrastructure/thread_per_request.jpg b/tasks/bomberman-infrastructure/thread_per_request.jpg new file mode 100644 index 0000000000000000000000000000000000000000..67279a3dd0f9984616abfd7c257e78704dd32ce1 GIT binary patch literal 40129 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 GrvC*Ps-)cj literal 0 HcmV?d00001 diff --git a/tasks/bomberman-infrastructure/top_view.png b/tasks/bomberman-infrastructure/top_view.png new file mode 100644 index 0000000000000000000000000000000000000000..ba4cdc6c963496977bd8f315fd298ebc54af3b3d GIT binary patch literal 97917 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 yMmh#yEq`mlb2X)wK5lx41~woYnm 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%0D^WYW|M-!D$(~(W@JY3`bC51q`g9JF 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�y zt072ZjD|)JJ`xiLEGGD<&>~>vRP%)nnz@@@&CTKaIcj0~b%4oy|9!*9xDeqlkdmSm zVzLJ0W5R^2pK^YfIWvLc*;nwLhCCM;f}kP)g4hLEOHbdR7Fs=dn4w$hIOSIr6+yd= z`LG5Fm;$dvwQ} z6`#}tcc23JhRAq(!Y2X(S|>R#8fHkL?Bg4~R5?lBcjqx*g)FhRdbxF7!f6IQIC z&W(FVPYH`LRU{2O*ntj>jSTZ6@1dfEW5w>VW{R+Z`-ub2yv!-6PMkQvVpMHi-CEQf zp`jQTVLneXI$W7NK`+|b(Qz-VALj(RgSR8AsOyQYgBc8l|{sT$&+}imEkf055?zaG7BFGk_u3Xwy}cQ~p8>XPw!^0MH4L3YLc;jYM}!aAFdlkOodnQS0-qP98NU zaW-lFony-`DhKfXD1)j#eq`2{!W)%qeN$5}U^#$GpC(fB(Gw?9n38Y8@!Rsc z35id&P+*`7pju{w$ji5HwP(-19v3I9s-U@LMGldSVPPH^>xkOhYlFFb-0!`#qO>W! z^yCmmx3O~`;WW5Wu69jdWy8dEufX+in3<^o{gidz*fByT5CV+t>q?PiS4g{O|An|LIW&{?onn`+pkXSG@xgrw=e) Td%H+M_>iVc&5aTbH~Ie$6OWi( literal 0 HcmV?d00001 From 3acf8a9e2376395e0d46b49b52e21bdadaae52b4 Mon Sep 17 00:00:00 2001 From: Sergey Rybalkin Date: Sat, 24 Mar 2018 19:19:12 +0300 Subject: [PATCH 22/89] Update README.md --- tasks/bomberman-infrastructure/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/bomberman-infrastructure/README.md b/tasks/bomberman-infrastructure/README.md index 1836c41478..d9387f0c10 100644 --- a/tasks/bomberman-infrastructure/README.md +++ b/tasks/bomberman-infrastructure/README.md @@ -126,6 +126,7 @@ Each request will be processed in separate thread. ## Deadline and HowTo? - `git checkout -b matchmaker` and work in this branch +- create `game` directory in the root of repository and write code in this folder (travis-ci will build this directory) - Deadline: **09.04** lecture. - This is team task (3-2 persons, **single submissions are not aloud**) - Procedure: From c81e40760c4e98c7c24f0e32c1e820c77ee699d2 Mon Sep 17 00:00:00 2001 From: Sergey Rybalkin Date: Sat, 24 Mar 2018 19:20:50 +0300 Subject: [PATCH 23/89] Update README.md --- tasks/bomberman-infrastructure/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/bomberman-infrastructure/README.md b/tasks/bomberman-infrastructure/README.md index d9387f0c10..4b064d34f1 100644 --- a/tasks/bomberman-infrastructure/README.md +++ b/tasks/bomberman-infrastructure/README.md @@ -1,7 +1,7 @@ # Bomberman ifrastructure We are going to start our game development. -Now it's a part to create big part of our infrastructure, including landing page logic and, matchmaker. +Now it's a part to create big part of our infrastructure, including matchmaker and landing page logic. **game server** will be implemented later ![](top_view.png) From 17d3336fb67f9e5e870e67e896bf9ab4bdad6672 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Sat, 24 Mar 2018 22:47:13 +0300 Subject: [PATCH 24/89] thread interruption --- lecture05/presentation/PITCHME.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lecture05/presentation/PITCHME.md b/lecture05/presentation/PITCHME.md index af612af526..59d28d4289 100644 --- a/lecture05/presentation/PITCHME.md +++ b/lecture05/presentation/PITCHME.md @@ -128,8 +128,15 @@ new Thread( runnable ).start(); - Thread::interrupt - Thread::sleep +--- + +### Thread interruption +An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate. +A thread sends an interrupt by invoking interrupt on the Thread object for the thread to be interrupted. For the interrupt mechanism to work correctly, the interrupted thread must support its own interruption. +https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html --- + ### Waiting for thread termination @See ru.atom.thread.join and tests From 9d199e28a295f18406847c0ae8ee279b2bc995c9 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Mon, 26 Mar 2018 12:26:45 +0300 Subject: [PATCH 25/89] new gradle structure --- web_hackaton/build.gradle | 45 +++-- .../gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 54333 bytes .../gradle/wrapper/gradle-wrapper.properties | 5 + web_hackaton/gradlew | 172 ++++++++++++++++++ web_hackaton/gradlew.bat | 84 +++++++++ .../java/ru/atom/chat/ChatController.java | 9 +- 6 files changed, 290 insertions(+), 25 deletions(-) create mode 100644 web_hackaton/gradle/wrapper/gradle-wrapper.jar create mode 100644 web_hackaton/gradle/wrapper/gradle-wrapper.properties create mode 100755 web_hackaton/gradlew create mode 100644 web_hackaton/gradlew.bat diff --git a/web_hackaton/build.gradle b/web_hackaton/build.gradle index d67789fd1e..d24a64fc23 100644 --- a/web_hackaton/build.gradle +++ b/web_hackaton/build.gradle @@ -1,26 +1,31 @@ -dependencies { - compile rootProject.libraries.spring_boot - compile rootProject.libraries.log4j - - testCompile rootProject.libraries.okhttp - testCompile rootProject.libraries.junit - testCompile rootProject.libraries.spring_boot_test +plugins { + id 'org.springframework.boot' version '2.0.0.RELEASE' } -springBoot { - mainClass = "ru.atom.chat.ChatApplication" +repositories { + mavenCentral() } +apply plugin: 'java' +apply plugin: 'checkstyle' -sourceSets { - main { - java { - srcDirs = ['src/main/java'] - } - } - test { - java { - srcDirs = ['src/test/java'] - } - } +dependencies { + // https://mvnrepository.com/artifact/org.slf4j/slf4j-api + compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25' + // https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl + //compile group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.10.0' + // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web + compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.0.RELEASE' + // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator + compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator', version: '2.0.0.RELEASE' + // https://mvnrepository.com/artifact/junit/junit + testCompile group: 'junit', name: 'junit', version: '4.4' + // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test + testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.0.0.RELEASE' } + +checkstyle { + ignoreFailures = false + toolVersion = '7.5' + configFile = new File('../config/checkstyle/checkstyle.xml') +} \ No newline at end of file diff --git a/web_hackaton/gradle/wrapper/gradle-wrapper.jar b/web_hackaton/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..c44b679acd3f794ddbb3aa5e919244914911014a GIT binary patch literal 54333 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
K7|BUm`^7>V&Zk%^_d-%A~k@lFe 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

Qox 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 E17(ftEC2ui literal 0 HcmV?d00001 diff --git a/web_hackaton/gradle/wrapper/gradle-wrapper.properties b/web_hackaton/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000..f51202dd25 --- /dev/null +++ b/web_hackaton/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-bin.zip +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/web_hackaton/gradlew b/web_hackaton/gradlew new file mode 100755 index 0000000000..cccdd3d517 --- /dev/null +++ b/web_hackaton/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/web_hackaton/gradlew.bat b/web_hackaton/gradlew.bat new file mode 100644 index 0000000000..e95643d6a2 --- /dev/null +++ b/web_hackaton/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/web_hackaton/src/main/java/ru/atom/chat/ChatController.java b/web_hackaton/src/main/java/ru/atom/chat/ChatController.java index da7ee8da0b..d20b814ca8 100644 --- a/web_hackaton/src/main/java/ru/atom/chat/ChatController.java +++ b/web_hackaton/src/main/java/ru/atom/chat/ChatController.java @@ -1,7 +1,7 @@ package ru.atom.chat; -import org.apache.log4j.LogManager; -import org.apache.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; @@ -13,16 +13,15 @@ import java.util.Deque; import java.util.HashSet; -import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentLinkedDeque; -import java.util.concurrent.ConcurrentLinkedQueue; import java.util.stream.Collectors; @Controller @RequestMapping("chat") public class ChatController { - private static final Logger log = LogManager.getLogger(ChatController.class); + private static final Logger log = LoggerFactory.getLogger(ChatController.class); + private Deque messages = new ConcurrentLinkedDeque<>(); private Set online = new HashSet<>(); From 302d785649cb08a0997cda5c453b92dd279430c9 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Mon, 26 Mar 2018 12:29:20 +0300 Subject: [PATCH 26/89] presentation --- web_hackaton/presentation/PITCHME.md | 42 +++++++++++++++++++--------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/web_hackaton/presentation/PITCHME.md b/web_hackaton/presentation/PITCHME.md index 721d4e256e..0a342b8b60 100644 --- a/web_hackaton/presentation/PITCHME.md +++ b/web_hackaton/presentation/PITCHME.md @@ -1,25 +1,35 @@ -#HSLIDE +--- # Java ## Web hackaton -#HSLIDE +--- + +Отметьтесь на портале +https://sphere.mail.ru/ + +--- + ### get ready ```bash -> git fetch upstream -> git checkout -b web_hackaton upstream/web_hackaton +git fetch upstream +git checkout -b web_hackaton upstream/web_hackaton +cd web_hackaton ``` -#HSLIDE +--- + Разделитесь на группы по **3** -#HSLIDE +--- + - Реализуйте сервер для **чата** - Реализуйте как можно больше фич (следующий слайд) Подумайте, за какие фичи стоит взяться, а какие вам не под силу - 20.30 - заканчиваем реализацию и показываете нам **список фичей** и ссылку на сервер, по которой мы можем получить ваш **index.html** - группы с наибольшим количеством фичей показывают свой сервис -#HSLIDE +--- + **Features:** 1. chat/say, chat/chat, chat/logout - 4p 1. save history to file on server - 2p @@ -34,7 +44,8 @@ 1. test with server startup inside - 3p 1. authentication - 3p -#HSLIDE +--- + ## Chat REST API. Login login: ``` @@ -50,7 +61,8 @@ login: 400 - Too long name (longer than 30 symbols) ``` -#HSLIDE +--- + ## Chat REST API. View chat online: ``` @@ -62,7 +74,8 @@ online: Success code: 200 ``` -#HSLIDE +--- + ## Chat REST API. View online users online: ``` @@ -74,7 +87,8 @@ online: Success code: 200 ``` -#HSLIDE +--- + ## Chat REST API. Say say: ``` @@ -90,7 +104,8 @@ say: 401 - Not logged in ``` -#HSLIDE +--- + ## Chat REST API. Logout logout: ``` @@ -104,7 +119,8 @@ logout: Success code: 200 ``` -#HSLIDE +--- + **Оставьте обратную связь** (вам на почту придет анкета) From c1fbed42273ed9d8a36a115fde84bbc6db5688b6 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Mon, 26 Mar 2018 13:52:43 +0300 Subject: [PATCH 27/89] presentation --- web_hackaton/presentation/PITCHME.md | 1 + web_hackaton/presentation/PITCHME.yaml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/web_hackaton/presentation/PITCHME.md b/web_hackaton/presentation/PITCHME.md index 0a342b8b60..621ccee705 100644 --- a/web_hackaton/presentation/PITCHME.md +++ b/web_hackaton/presentation/PITCHME.md @@ -1,5 +1,6 @@ --- # Java +2018 ## Web hackaton --- diff --git a/web_hackaton/presentation/PITCHME.yaml b/web_hackaton/presentation/PITCHME.yaml index c28d621a8b..02470e7d9b 100644 --- a/web_hackaton/presentation/PITCHME.yaml +++ b/web_hackaton/presentation/PITCHME.yaml @@ -1,3 +1,3 @@ theme-override : lecture02/presentation/assets/css/PITCHME.css -logo : lecture02/presentation/assets/img/atom.png +logo : lecture02/presentation/assets/img/sphere.png slide-number: true From fd0eabd2f4d2991669e05b5618bcaaa782d15967 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Mon, 26 Mar 2018 13:55:40 +0300 Subject: [PATCH 28/89] presentation --- web_hackaton/presentation/PITCHME.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_hackaton/presentation/PITCHME.yaml b/web_hackaton/presentation/PITCHME.yaml index 02470e7d9b..97d63e137f 100644 --- a/web_hackaton/presentation/PITCHME.yaml +++ b/web_hackaton/presentation/PITCHME.yaml @@ -1,3 +1,3 @@ theme-override : lecture02/presentation/assets/css/PITCHME.css -logo : lecture02/presentation/assets/img/sphere.png +logo : lecture01/presentation/assets/img/sphere.png slide-number: true From 65c661082bddadff1a8b0564c8554cedac260768 Mon Sep 17 00:00:00 2001 From: "a.pomosov" Date: Mon, 26 Mar 2018 14:32:05 +0300 Subject: [PATCH 29/89] practice blob --- web_hackaton/build.gradle | 2 + .../java/ru/atom/chat/ChatController.java | 74 ++++---- .../src/main/resources/static/index.html | 165 ++++++------------ .../src/main/resources/static/styles.css | 44 +++++ .../test/java/ru/atom/chat/ChatClient.java | 2 - .../java/ru/atom/chat/ChatClientTest.java | 30 ++-- web_hackaton/web_hackaton.iml | 12 ++ 7 files changed, 168 insertions(+), 161 deletions(-) create mode 100644 web_hackaton/src/main/resources/static/styles.css create mode 100644 web_hackaton/web_hackaton.iml diff --git a/web_hackaton/build.gradle b/web_hackaton/build.gradle index d24a64fc23..63f9fe84c6 100644 --- a/web_hackaton/build.gradle +++ b/web_hackaton/build.gradle @@ -14,6 +14,8 @@ dependencies { compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25' // https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-slf4j-impl //compile group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: '2.10.0' + // https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp + compile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.10.0' // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.0.RELEASE' // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-actuator diff --git a/web_hackaton/src/main/java/ru/atom/chat/ChatController.java b/web_hackaton/src/main/java/ru/atom/chat/ChatController.java index d20b814ca8..69572b710f 100644 --- a/web_hackaton/src/main/java/ru/atom/chat/ChatController.java +++ b/web_hackaton/src/main/java/ru/atom/chat/ChatController.java @@ -11,10 +11,10 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; -import java.util.Deque; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.ConcurrentLinkedDeque; +import java.util.Map; +import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.stream.Collectors; @Controller @@ -22,9 +22,8 @@ public class ChatController { private static final Logger log = LoggerFactory.getLogger(ChatController.class); - - private Deque messages = new ConcurrentLinkedDeque<>(); - private Set online = new HashSet<>(); + private Queue messages = new ConcurrentLinkedQueue<>(); + private Map usersOnline = new ConcurrentHashMap<>(); /** * curl -X POST -i localhost:8080/chat/login -d "name=I_AM_STUPID" @@ -35,30 +34,34 @@ public class ChatController { consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) @ResponseStatus(HttpStatus.OK) public ResponseEntity login(@RequestParam("name") String name) { - if (name == null || name.isEmpty()) { - return new ResponseEntity<>("No name provided", HttpStatus.BAD_REQUEST); + if (name.length() < 1) { + return ResponseEntity.badRequest().body("Too short name, sorry :("); + } + if (name.length() > 20) { + return ResponseEntity.badRequest().body("Too long name, sorry :("); } - if (!online.add(name)) { - return new ResponseEntity<>("Already logged in", HttpStatus.BAD_REQUEST); + if (usersOnline.containsKey(name)) { + return ResponseEntity.badRequest().body("Already logged in:("); } - messages.addFirst("[" + name + "] is online"); - log.info(name + " logged in"); - return new ResponseEntity<>(HttpStatus.OK); + usersOnline.put(name, name); + messages.add("[" + name + "] logged in"); + return ResponseEntity.ok().build(); } /** - * curl -X POST -i localhost:8080/chat/logout -d "name=I_AM_STUPID" + * curl -i localhost:8080/chat/chat */ @RequestMapping( - path = "logout", - method = RequestMethod.POST, - consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) - @ResponseStatus(HttpStatus.OK) - public ResponseEntity logout(@RequestParam("name") String name) { - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + path = "chat", + method = RequestMethod.GET, + produces = MediaType.TEXT_PLAIN_VALUE) + public ResponseEntity chat() { + return new ResponseEntity<>(messages.stream() + .map(Object::toString) + .collect(Collectors.joining("\n")), + HttpStatus.OK); } - /** * curl -i localhost:8080/chat/online */ @@ -67,34 +70,31 @@ public ResponseEntity logout(@RequestParam("name") String name) { method = RequestMethod.GET, produces = MediaType.TEXT_PLAIN_VALUE) public ResponseEntity online() { - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + return new ResponseEntity<>(HttpStatus.BAD_REQUEST);//TODO } - /** - * curl -X POST -i localhost:8080/chat/say -d "name=I_AM_STUPID&msg=Hello everyone in this chat" + * curl -X POST -i localhost:8080/chat/logout -d "name=I_AM_STUPID" */ @RequestMapping( - path = "say", + path = "logout", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) @ResponseStatus(HttpStatus.OK) - public ResponseEntity say(@RequestParam("name") String name, @RequestParam("msg") String msg) { - return new ResponseEntity<>(HttpStatus.BAD_REQUEST); + public ResponseEntity logout(@RequestParam("name") String name) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST);//TODO } /** - * curl -i localhost:8080/chat/chat + * curl -X POST -i localhost:8080/chat/say -d "name=I_AM_STUPID&msg=Hello everyone in this chat" */ @RequestMapping( - path = "chat", - method = RequestMethod.GET, - produces = MediaType.TEXT_PLAIN_VALUE) - public ResponseEntity chat() { - return new ResponseEntity<>(messages.stream() - .map(Object::toString) - .collect(Collectors.joining("\n")), - HttpStatus.OK); + path = "say", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE) + @ResponseStatus(HttpStatus.OK) + public ResponseEntity say(@RequestParam("name") String name, @RequestParam("msg") String msg) { + return new ResponseEntity<>(HttpStatus.BAD_REQUEST);//TODO } } diff --git a/web_hackaton/src/main/resources/static/index.html b/web_hackaton/src/main/resources/static/index.html index fbcb2dfd7f..0b3cea89cd 100644 --- a/web_hackaton/src/main/resources/static/index.html +++ b/web_hackaton/src/main/resources/static/index.html @@ -1,56 +1,7 @@ - - + + + - -